Update: Full functionality with typescript

pull/16/head
Juraj Nyíri 3 years ago
parent 2ab5c840c7
commit 10a40c6c4f

@ -45,6 +45,14 @@
"ts": "never", "ts": "never",
"tsx": "never" "tsx": "never"
} }
],
"@typescript-eslint/no-this-alias": [
"error",
{
"allowedNames": [
"self"
] // Allow `const self = this`; `[]` by default
}
] ]
} }
} }

@ -18772,34 +18772,28 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.loadCustomStyles(); this.loadCustomStyles();
}; };
this.render = (hass) => { this.render = (hass) => {
console.log('render');
this.previousPositions = []; this.previousPositions = [];
// todo: find a better way to detect resize... // todo: find a better way to detect resize...
// todo: uncomment
/*
setInterval(() => { setInterval(() => {
if (this.movieElems.length > 0) { if (this.movieElems.length > 0) {
if (this.previousPositions.length === 0) { if (this.previousPositions.length === 0) {
for (let i = 0; i < this.movieElems.length; i + 1) { for (let i = 0; i < this.movieElems.length; i += 1) {
this.previousPositions[i] = {}; this.previousPositions[i] = {};
this.previousPositions[i].top = this.movieElems[i].parentElement.offsetTop; this.previousPositions[i].top = this.movieElems[i].parentElement.offsetTop;
this.previousPositions[i].left = this.movieElems[i].parentElement.offsetLeft; this.previousPositions[i].left = this.movieElems[i].parentElement.offsetLeft;
} }
} }
for (let i = 0; i < this.movieElems.length; i + 1) { for (let i = 0; i < this.movieElems.length; i += 1) {
if ( if (this.previousPositions[i] &&
this.previousPositions[i] &&
this.movieElems[i].dataset.clicked !== 'true' && this.movieElems[i].dataset.clicked !== 'true' &&
(this.previousPositions[i].top !== this.movieElems[i].parentElement.offsetTop || (this.previousPositions[i].top !== this.movieElems[i].parentElement.offsetTop ||
this.previousPositions[i].left !== this.movieElems[i].parentElement.offsetLeft) this.previousPositions[i].left !== this.movieElems[i].parentElement.offsetLeft)) {
) {
this.renderPage(hass); this.renderPage(hass);
this.previousPositions = []; this.previousPositions = [];
} }
} }
} }
}, 100); }, 100);
*/
this.renderPage(hass); this.renderPage(hass);
}; };
this.loadInitialData = async (hass) => { this.loadInitialData = async (hass) => {
@ -18821,79 +18815,19 @@ class PlexMeetsHomeAssistant extends HTMLElement {
} }
catch (err) { catch (err) {
// todo: proper timeout here // todo: proper timeout here
this.error = `Plex server did not respond.`; this.error = `Plex server did not respond.<br/>Details of the error: ${escapeHtml(err.message)}`;
this.renderPage(hass); this.renderPage(hass);
} }
/*
// eslint-disable-next-line no-shadow
.then(sectionsData => {
// eslint-disable-next-line array-callback-return
sectionsData.some(sectionData => {
// eslint-disable-next-line no-param-reassign
sectionData = parser.parseFromString(sectionData, 'text/xml');
const sectionType = sectionData.getElementsByTagName('MediaContainer')[0].attributes.viewGroup
.textContent;
const sectionTitle = sectionData.getElementsByTagName('MediaContainer')[0].attributes.title1.textContent;
this.data[sectionTitle] = [];
let titles = [];
if (sectionType === 'movie') {
titles = sectionData.getElementsByTagName('Video');
} else if (sectionType === 'show') {
titles = sectionData.getElementsByTagName('Directory');
} else {
// todo
}
// eslint-disable-next-line array-callback-return
Array.from(titles).some((title: any) => {
this.data[sectionTitle].push({
title: title.attributes.title ? title.attributes.title.textContent : undefined,
summary: title.attributes.summary ? title.attributes.summary.textContent : undefined,
key: title.attributes.key ? title.attributes.key.textContent : undefined,
guid: title.attributes.guid ? title.attributes.guid.textContent : undefined,
rating: title.attributes.rating ? title.attributes.rating.textContent : undefined,
audienceRating: title.attributes.audienceRating
? title.attributes.audienceRating.textContent
: undefined,
year: title.attributes.year ? title.attributes.year.textContent : undefined,
thumb: title.attributes.thumb ? title.attributes.thumb.textContent : undefined,
art: title.attributes.art ? title.attributes.art.textContent : undefined,
contentRating: title.attributes.contentRating
? title.attributes.contentRating.textContent
: undefined,
duration: title.attributes.duration ? title.attributes.duration.textContent : undefined,
type: sectionType || undefined
});
});
});
if (this.data[this.config.libraryName] === undefined) {
this.error = `Library name ${this.config.libraryName} does not exist.`;
}
this.loading = false;
this.render(hass);
})
.catch(err => {
this.error = `Plex sections requests did not respond within ${this.requestTimeout / 1000} seconds.`;
this.renderPage(hass);
});
})
.catch(err => {
this.error = `Plex server did not respond within ${this.requestTimeout / 1000} seconds.`;
this.renderPage(hass);
});
*/
}; };
// todo: run also on resize
this.calculatePositions = () => { this.calculatePositions = () => {
// todo: figure out why loop is needed here and do it properly // todo: figure out why loop is needed here and do it properly
/*
const setLeftOffsetsInterval = setInterval(() => { const setLeftOffsetsInterval = setInterval(() => {
this.movieElems = this.getElementsByClassName('movieElem'); this.movieElems = this.getElementsByClassName('movieElem');
for (let i = 0; i < this.movieElems.length; i + 1) { for (let i = 0; i < this.movieElems.length; i += 1) {
if (this.movieElems[i].offsetLeft === 0) { if (this.movieElems[i].offsetLeft === 0) {
break; break;
} else { }
else {
clearInterval(setLeftOffsetsInterval); clearInterval(setLeftOffsetsInterval);
} }
this.movieElems[i].style.left = `${this.movieElems[i].offsetLeft}px`; this.movieElems[i].style.left = `${this.movieElems[i].offsetLeft}px`;
@ -18902,10 +18836,9 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.movieElems[i].dataset.top = this.movieElems[i].offsetTop; this.movieElems[i].dataset.top = this.movieElems[i].offsetTop;
} }
}, 10); }, 10);
*/
}; };
this.minimizeAll = () => { this.minimizeAll = () => {
for (let i = 0; i < this.movieElems.length; i + 1) { for (let i = 0; i < this.movieElems.length; i += 1) {
if (this.movieElems[i].dataset.clicked === 'true') { if (this.movieElems[i].dataset.clicked === 'true') {
this.movieElems[i].style.width = `${this.width}px`; this.movieElems[i].style.width = `${this.width}px`;
this.movieElems[i].style.height = `${this.height}px`; this.movieElems[i].style.height = `${this.height}px`;
@ -18990,37 +18923,33 @@ class PlexMeetsHomeAssistant extends HTMLElement {
if (!this.playSupported) { if (!this.playSupported) {
movieElem.style.cursor = 'pointer'; movieElem.style.cursor = 'pointer';
} }
movieElem.addEventListener('click', event => { const self = this;
/* todo movieElem.addEventListener('click', function handleClick() {
console.log(data);
if (this.dataset.clicked === 'true') { if (this.dataset.clicked === 'true') {
_this.hideDetails(); self.hideDetails();
this.style.width = `${_this.width}px`; this.style.width = `${self.width}px`;
this.style.height = `${_this.height}px`; this.style.height = `${self.height}px`;
this.style['z-index'] = 1; this.style.zIndex = '1';
this.style.top = `${this.dataset.top}px`; this.style.top = `${this.dataset.top}px`;
this.style.left = `${this.dataset.left}px`; this.style.left = `${this.dataset.left}px`;
setTimeout(() => {
const __this = this; this.dataset.clicked = 'false';
setTimeout(function() {
__this.dataset.clicked = false;
}, 500); }, 500);
self.hideBackground();
_this.hideBackground(); }
} else { else {
_this.minimizeAll(); self.minimizeAll();
_this.showDetails(data); self.showDetails(data);
const doc = document.documentElement; const doc = document.documentElement;
const top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0); const top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
_this.showBackground(); self.showBackground();
this.style.width = `${_this.expandedWidth}px`; this.style.width = `${self.expandedWidth}px`;
this.style.height = `${_this.expandedHeight}px`; this.style.height = `${self.expandedHeight}px`;
this.style['z-index'] = 3; this.style.zIndex = '3';
this.style.left = '16px'; this.style.left = '16px';
this.style.top = `${top + 16}px`; this.style.top = `${top + 16}px`;
this.dataset.clicked = true; this.dataset.clicked = 'true';
} }
*/
}); });
const playButton = this.getPlayButton(); const playButton = this.getPlayButton();
const interactiveArea = document.createElement('div'); const interactiveArea = document.createElement('div');
@ -19269,23 +19198,32 @@ class PlexMeetsHomeAssistant extends HTMLElement {
playButton.name = 'playButton'; playButton.name = 'playButton';
return playButton; return playButton;
}; };
this.getData = (url) => { // todo: define custom type
console.log(url); this.setConfig = (config) => {
return new Promise((resolve, reject) => { this.plexProtocol = 'http';
const xhr = new XMLHttpRequest(); if (!config.entity_id) {
xhr.open('GET', url, true); throw new Error('You need to define an entity_id');
xhr.timeout = this.requestTimeout; }
xhr.onload = function () { if (!config.token) {
resolve(xhr.responseText); throw new Error('You need to define a token');
}; }
xhr.ontimeout = function (e) { if (!config.ip) {
reject(e); throw new Error('You need to define a ip');
}; }
xhr.send(null); if (!config.port) {
}); throw new Error('You need to define a port');
}
if (!config.libraryName) {
throw new Error('You need to define a libraryName');
}
this.config = config;
if (config.protocol) {
this.plexProtocol = config.protocol;
}
if (config.maxCount) {
this.maxCount = config.maxCount;
}
}; };
// The height of your card. Home Assistant uses this to automatically
// distribute all cards over the available columns.
this.getCardSize = () => { this.getCardSize = () => {
return 3; return 3;
}; };
@ -19302,31 +19240,5 @@ class PlexMeetsHomeAssistant extends HTMLElement {
} }
} }
} }
// todo: define custom type
setConfig(config) {
this.plexProtocol = 'http';
if (!config.entity_id) {
throw new Error('You need to define an entity_id');
}
if (!config.token) {
throw new Error('You need to define a token');
}
if (!config.ip) {
throw new Error('You need to define a ip');
}
if (!config.port) {
throw new Error('You need to define a port');
}
if (!config.libraryName) {
throw new Error('You need to define a libraryName');
}
this.config = config;
if (config.protocol) {
this.plexProtocol = config.protocol;
}
if (config.maxCount) {
this.maxCount = config.maxCount;
}
}
} }
customElements.define('plex-meets-homeassistant', PlexMeetsHomeAssistant); customElements.define('plex-meets-homeassistant', PlexMeetsHomeAssistant);

@ -1,7 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable no-underscore-dangle */
/* eslint-env browser */ /* eslint-env browser */
import { HomeAssistant, LovelaceCardEditor } from 'custom-card-helpers'; import { HomeAssistant } from 'custom-card-helpers';
import _ from 'lodash'; import _ from 'lodash';
import Plex from './modules/Plex'; import Plex from './modules/Plex';
import { escapeHtml } from './utils'; import { escapeHtml } from './utils';
@ -118,22 +117,19 @@ class PlexMeetsHomeAssistant extends HTMLElement {
} }
render = (hass: HomeAssistant): void => { render = (hass: HomeAssistant): void => {
console.log('render');
this.previousPositions = []; this.previousPositions = [];
// todo: find a better way to detect resize... // todo: find a better way to detect resize...
// todo: uncomment
/*
setInterval(() => { setInterval(() => {
if (this.movieElems.length > 0) { if (this.movieElems.length > 0) {
if (this.previousPositions.length === 0) { if (this.previousPositions.length === 0) {
for (let i = 0; i < this.movieElems.length; i + 1) { for (let i = 0; i < this.movieElems.length; i += 1) {
this.previousPositions[i] = {}; this.previousPositions[i] = {};
this.previousPositions[i].top = this.movieElems[i].parentElement.offsetTop; this.previousPositions[i].top = this.movieElems[i].parentElement.offsetTop;
this.previousPositions[i].left = this.movieElems[i].parentElement.offsetLeft; this.previousPositions[i].left = this.movieElems[i].parentElement.offsetLeft;
} }
} }
for (let i = 0; i < this.movieElems.length; i + 1) { for (let i = 0; i < this.movieElems.length; i += 1) {
if ( if (
this.previousPositions[i] && this.previousPositions[i] &&
this.movieElems[i].dataset.clicked !== 'true' && this.movieElems[i].dataset.clicked !== 'true' &&
@ -146,7 +142,7 @@ class PlexMeetsHomeAssistant extends HTMLElement {
} }
} }
}, 100); }, 100);
*/
this.renderPage(hass); this.renderPage(hass);
}; };
@ -171,78 +167,16 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.render(hass); this.render(hass);
} catch (err) { } catch (err) {
// todo: proper timeout here // todo: proper timeout here
this.error = `Plex server did not respond.`; this.error = `Plex server did not respond.<br/>Details of the error: ${escapeHtml(err.message)}`;
this.renderPage(hass); this.renderPage(hass);
} }
/*
// eslint-disable-next-line no-shadow
.then(sectionsData => {
// eslint-disable-next-line array-callback-return
sectionsData.some(sectionData => {
// eslint-disable-next-line no-param-reassign
sectionData = parser.parseFromString(sectionData, 'text/xml');
const sectionType = sectionData.getElementsByTagName('MediaContainer')[0].attributes.viewGroup
.textContent;
const sectionTitle = sectionData.getElementsByTagName('MediaContainer')[0].attributes.title1.textContent;
this.data[sectionTitle] = [];
let titles = [];
if (sectionType === 'movie') {
titles = sectionData.getElementsByTagName('Video');
} else if (sectionType === 'show') {
titles = sectionData.getElementsByTagName('Directory');
} else {
// todo
}
// eslint-disable-next-line array-callback-return
Array.from(titles).some((title: any) => {
this.data[sectionTitle].push({
title: title.attributes.title ? title.attributes.title.textContent : undefined,
summary: title.attributes.summary ? title.attributes.summary.textContent : undefined,
key: title.attributes.key ? title.attributes.key.textContent : undefined,
guid: title.attributes.guid ? title.attributes.guid.textContent : undefined,
rating: title.attributes.rating ? title.attributes.rating.textContent : undefined,
audienceRating: title.attributes.audienceRating
? title.attributes.audienceRating.textContent
: undefined,
year: title.attributes.year ? title.attributes.year.textContent : undefined,
thumb: title.attributes.thumb ? title.attributes.thumb.textContent : undefined,
art: title.attributes.art ? title.attributes.art.textContent : undefined,
contentRating: title.attributes.contentRating
? title.attributes.contentRating.textContent
: undefined,
duration: title.attributes.duration ? title.attributes.duration.textContent : undefined,
type: sectionType || undefined
});
});
});
if (this.data[this.config.libraryName] === undefined) {
this.error = `Library name ${this.config.libraryName} does not exist.`;
}
this.loading = false;
this.render(hass);
})
.catch(err => {
this.error = `Plex sections requests did not respond within ${this.requestTimeout / 1000} seconds.`;
this.renderPage(hass);
});
})
.catch(err => {
this.error = `Plex server did not respond within ${this.requestTimeout / 1000} seconds.`;
this.renderPage(hass);
});
*/
}; };
// todo: run also on resize calculatePositions = (): void => {
calculatePositions = () => {
// todo: figure out why loop is needed here and do it properly // todo: figure out why loop is needed here and do it properly
/*
const setLeftOffsetsInterval = setInterval(() => { const setLeftOffsetsInterval = setInterval(() => {
this.movieElems = this.getElementsByClassName('movieElem'); this.movieElems = this.getElementsByClassName('movieElem');
for (let i = 0; i < this.movieElems.length; i + 1) { for (let i = 0; i < this.movieElems.length; i += 1) {
if (this.movieElems[i].offsetLeft === 0) { if (this.movieElems[i].offsetLeft === 0) {
break; break;
} else { } else {
@ -254,11 +188,10 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.movieElems[i].dataset.top = this.movieElems[i].offsetTop; this.movieElems[i].dataset.top = this.movieElems[i].offsetTop;
} }
}, 10); }, 10);
*/
}; };
minimizeAll = () => { minimizeAll = (): void => {
for (let i = 0; i < this.movieElems.length; i + 1) { for (let i = 0; i < this.movieElems.length; i += 1) {
if (this.movieElems[i].dataset.clicked === 'true') { if (this.movieElems[i].dataset.clicked === 'true') {
this.movieElems[i].style.width = `${this.width}px`; this.movieElems[i].style.width = `${this.width}px`;
this.movieElems[i].style.height = `${this.height}px`; this.movieElems[i].style.height = `${this.height}px`;
@ -274,7 +207,7 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.hideDetails(); this.hideDetails();
}; };
hideDetails = () => { hideDetails = (): void => {
const doc = document.documentElement; const doc = document.documentElement;
const top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0); const top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
if (this.detailElem) { if (this.detailElem) {
@ -285,7 +218,7 @@ class PlexMeetsHomeAssistant extends HTMLElement {
} }
}; };
showDetails = (data: any) => { showDetails = (data: any): void => {
const doc = document.documentElement; const doc = document.documentElement;
const top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0); const top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
if (this.detailElem) { if (this.detailElem) {
@ -328,19 +261,19 @@ class PlexMeetsHomeAssistant extends HTMLElement {
} }
}; };
showBackground = () => { showBackground = (): void => {
const contentbg = this.getElementsByClassName('contentbg'); const contentbg = this.getElementsByClassName('contentbg');
(contentbg[0] as HTMLElement).style.zIndex = '2'; (contentbg[0] as HTMLElement).style.zIndex = '2';
(contentbg[0] as HTMLElement).style.backgroundColor = 'rgba(0,0,0,0.9)'; (contentbg[0] as HTMLElement).style.backgroundColor = 'rgba(0,0,0,0.9)';
}; };
hideBackground = () => { hideBackground = (): void => {
const contentbg = this.getElementsByClassName('contentbg'); const contentbg = this.getElementsByClassName('contentbg');
(contentbg[0] as HTMLElement).style.zIndex = '1'; (contentbg[0] as HTMLElement).style.zIndex = '1';
(contentbg[0] as HTMLElement).style.backgroundColor = 'rgba(0,0,0,0)'; (contentbg[0] as HTMLElement).style.backgroundColor = 'rgba(0,0,0,0)';
}; };
getMovieElement = (data: any, hass: HomeAssistant, serverID: string) => { getMovieElement = (data: any, hass: HomeAssistant, serverID: string): HTMLDivElement => {
const thumbURL = `${this.plexProtocol}://${this.config.ip}:${this.config.port}/photo/:/transcode?width=${this.expandedWidth}&height=${this.expandedHeight}&minSize=1&upscale=1&url=${data.thumb}&X-Plex-Token=${this.config.token}`; const thumbURL = `${this.plexProtocol}://${this.config.ip}:${this.config.port}/photo/:/transcode?width=${this.expandedWidth}&height=${this.expandedHeight}&minSize=1&upscale=1&url=${data.thumb}&X-Plex-Token=${this.config.token}`;
const container = document.createElement('div'); const container = document.createElement('div');
@ -358,37 +291,34 @@ class PlexMeetsHomeAssistant extends HTMLElement {
movieElem.style.cursor = 'pointer'; movieElem.style.cursor = 'pointer';
} }
movieElem.addEventListener('click', event => { const self = this;
/* todo movieElem.addEventListener('click', function handleClick() {
console.log(data);
if (this.dataset.clicked === 'true') { if (this.dataset.clicked === 'true') {
_this.hideDetails(); self.hideDetails();
this.style.width = `${_this.width}px`; this.style.width = `${self.width}px`;
this.style.height = `${_this.height}px`; this.style.height = `${self.height}px`;
this.style['z-index'] = 1; this.style.zIndex = '1';
this.style.top = `${this.dataset.top}px`; this.style.top = `${this.dataset.top}px`;
this.style.left = `${this.dataset.left}px`; this.style.left = `${this.dataset.left}px`;
const __this = this; setTimeout(() => {
setTimeout(function() { this.dataset.clicked = 'false';
__this.dataset.clicked = false;
}, 500); }, 500);
_this.hideBackground(); self.hideBackground();
} else { } else {
_this.minimizeAll(); self.minimizeAll();
_this.showDetails(data); self.showDetails(data);
const doc = document.documentElement; const doc = document.documentElement;
const top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0); const top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
_this.showBackground(); self.showBackground();
this.style.width = `${_this.expandedWidth}px`; this.style.width = `${self.expandedWidth}px`;
this.style.height = `${_this.expandedHeight}px`; this.style.height = `${self.expandedHeight}px`;
this.style['z-index'] = 3; this.style.zIndex = '3';
this.style.left = '16px'; this.style.left = '16px';
this.style.top = `${top + 16}px`; this.style.top = `${top + 16}px`;
this.dataset.clicked = true; this.dataset.clicked = 'true';
} }
*/
}); });
const playButton = this.getPlayButton(); const playButton = this.getPlayButton();
@ -432,7 +362,7 @@ class PlexMeetsHomeAssistant extends HTMLElement {
return container; return container;
}; };
loadCustomStyles = () => { loadCustomStyles = (): void => {
const style = document.createElement('style'); const style = document.createElement('style');
style.textContent = ` style.textContent = `
@ -644,7 +574,7 @@ class PlexMeetsHomeAssistant extends HTMLElement {
this.appendChild(style); this.appendChild(style);
}; };
getPlayButton = () => { getPlayButton = (): HTMLButtonElement => {
const playButton = document.createElement('button'); const playButton = document.createElement('button');
playButton.name = 'playButton'; playButton.name = 'playButton';
@ -652,7 +582,7 @@ class PlexMeetsHomeAssistant extends HTMLElement {
}; };
// todo: define custom type // todo: define custom type
setConfig(config: any) { setConfig = (config: any): void => {
this.plexProtocol = 'http'; this.plexProtocol = 'http';
if (!config.entity_id) { if (!config.entity_id) {
throw new Error('You need to define an entity_id'); throw new Error('You need to define an entity_id');
@ -676,27 +606,9 @@ class PlexMeetsHomeAssistant extends HTMLElement {
if (config.maxCount) { if (config.maxCount) {
this.maxCount = config.maxCount; this.maxCount = config.maxCount;
} }
}
getData = (url: string) => {
console.log(url);
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.timeout = this.requestTimeout;
xhr.onload = function() {
resolve(xhr.responseText);
};
xhr.ontimeout = function(e) {
reject(e);
};
xhr.send(null);
});
}; };
// The height of your card. Home Assistant uses this to automatically getCardSize = (): number => {
// distribute all cards over the available columns.
getCardSize = () => {
return 3; return 3;
}; };
} }

Loading…
Cancel
Save