You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
953 lines
33 KiB
953 lines
33 KiB
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
/* eslint-env browser */
|
|
import _ from 'lodash';
|
|
import { HomeAssistant } from 'custom-card-helpers';
|
|
import Plex from './modules/Plex';
|
|
import { fetchEntityRegistry } from './modules/utils';
|
|
|
|
class PlexMeetsHomeAssistantEditor extends HTMLElement {
|
|
content: any;
|
|
|
|
plexPort: number | false = false;
|
|
|
|
plexProtocol: 'http' | 'https' = 'http';
|
|
|
|
plex: Plex | undefined;
|
|
|
|
config: Record<string, any> = {};
|
|
|
|
ip: any = document.createElement('paper-input');
|
|
|
|
token: any = document.createElement('paper-input');
|
|
|
|
port: any = document.createElement('paper-input');
|
|
|
|
maxCount: any = document.createElement('paper-input');
|
|
|
|
maxRows: any = document.createElement('paper-input');
|
|
|
|
displayTitleMain: any = document.createElement('paper-dropdown-menu');
|
|
|
|
displaySubtitleMain: any = document.createElement('paper-dropdown-menu');
|
|
|
|
useHorizontalScroll: any = document.createElement('paper-dropdown-menu');
|
|
|
|
minWidth: any = document.createElement('paper-input');
|
|
|
|
minEpisodeWidth: any = document.createElement('paper-input');
|
|
|
|
minExpandedWidth: any = document.createElement('paper-input');
|
|
|
|
minExpandedHeight: any = document.createElement('paper-input');
|
|
|
|
fontSize1: any = document.createElement('paper-input');
|
|
|
|
fontSize2: any = document.createElement('paper-input');
|
|
|
|
fontSize3: any = document.createElement('paper-input');
|
|
|
|
fontSize4: any = document.createElement('paper-input');
|
|
|
|
cardTitle: any = document.createElement('paper-input');
|
|
|
|
libraryName: any = document.createElement('paper-dropdown-menu');
|
|
|
|
protocol: any = document.createElement('paper-dropdown-menu');
|
|
|
|
tabs: any = document.createElement('paper-tabs');
|
|
|
|
sort: any = document.createElement('paper-dropdown-menu');
|
|
|
|
sortOrder: any = document.createElement('paper-dropdown-menu');
|
|
|
|
playTrailer: any = document.createElement('paper-dropdown-menu');
|
|
|
|
showExtras: any = document.createElement('paper-dropdown-menu');
|
|
|
|
showSearch: any = document.createElement('paper-dropdown-menu');
|
|
|
|
runBefore: any = document.createElement('paper-dropdown-menu');
|
|
|
|
runAfter: any = document.createElement('paper-dropdown-menu');
|
|
|
|
entitiesSection: any = document.createElement('div');
|
|
|
|
devicesTabs = 0;
|
|
|
|
hassObj: HomeAssistant | undefined;
|
|
|
|
entities: Array<any> = [];
|
|
|
|
scriptEntities: Array<string> = [];
|
|
|
|
sections: Array<Record<string, any>> = [];
|
|
|
|
collections: Array<Record<string, any>> = [];
|
|
|
|
playlists: Array<Record<string, any>> = [];
|
|
|
|
clients: Record<string, any> = {};
|
|
|
|
entitiesRegistry: false | Array<Record<string, any>> = false;
|
|
|
|
plexValidSection = document.createElement('div');
|
|
|
|
loaded = false;
|
|
|
|
livetv: Record<string, any> = {};
|
|
|
|
fireEvent = (
|
|
node: HTMLElement,
|
|
type: string,
|
|
detail: Record<string, any>,
|
|
options: Record<string, any> = {}
|
|
): Event => {
|
|
// eslint-disable-next-line no-param-reassign
|
|
detail = detail === null || detail === undefined ? {} : detail;
|
|
const event: any = new Event(type, {
|
|
bubbles: options.bubbles === undefined ? true : options.bubbles,
|
|
cancelable: Boolean(options.cancelable),
|
|
composed: options.composed === undefined ? true : options.composed
|
|
});
|
|
event.detail = detail;
|
|
node.dispatchEvent(event);
|
|
return event;
|
|
};
|
|
|
|
valueUpdated = (): void => {
|
|
const originalConfig = _.clone(this.config);
|
|
this.config.protocol = this.protocol.value;
|
|
this.config.ip = this.ip.value.replace(/^https?\:\/\//i, '').replace(/\/$/, '');
|
|
this.config.token = this.token.value;
|
|
this.config.port = this.port.value;
|
|
if (this.loaded) {
|
|
if (!this.config.entity) {
|
|
this.config.entity = [];
|
|
}
|
|
if (!_.isEmpty(this.libraryName.value)) {
|
|
this.config.libraryName = this.libraryName.value;
|
|
|
|
let sortOrderValue = '';
|
|
if (_.isEqual(this.sortOrder.value, 'Ascending')) {
|
|
sortOrderValue = 'asc';
|
|
} else if (_.isEqual(this.sortOrder.value, 'Descending')) {
|
|
sortOrderValue = 'desc';
|
|
}
|
|
if (!_.isEmpty(sortOrderValue) && !_.isEmpty(this.sort.value)) {
|
|
this.config.sort = `${this.sort.value}:${sortOrderValue}`;
|
|
} else {
|
|
this.config.sort = ``;
|
|
}
|
|
|
|
if (_.isEmpty(this.maxCount.value)) {
|
|
this.config.maxCount = '';
|
|
} else {
|
|
this.config.maxCount = this.maxCount.value;
|
|
}
|
|
|
|
if (_.isEmpty(this.maxRows.value)) {
|
|
this.config.maxRows = '';
|
|
} else {
|
|
this.config.maxRows = this.maxRows.value;
|
|
}
|
|
|
|
if (_.isEmpty(this.useHorizontalScroll.value)) {
|
|
this.config.useHorizontalScroll = 'No';
|
|
} else {
|
|
this.config.useHorizontalScroll = this.useHorizontalScroll.value;
|
|
}
|
|
|
|
if (_.isEmpty(this.displayTitleMain.value)) {
|
|
this.config.displayTitleMain = 'Yes';
|
|
} else {
|
|
this.config.displayTitleMain = this.displayTitleMain.value;
|
|
}
|
|
|
|
if (_.isEmpty(this.displaySubtitleMain.value)) {
|
|
this.config.displaySubtitleMain = 'Yes';
|
|
} else {
|
|
this.config.displaySubtitleMain = this.displaySubtitleMain.value;
|
|
}
|
|
|
|
if (_.isEmpty(this.minWidth.value)) {
|
|
this.config.minWidth = '';
|
|
} else {
|
|
this.config.minWidth = this.minWidth.value;
|
|
}
|
|
|
|
if (_.isEmpty(this.minEpisodeWidth.value)) {
|
|
this.config.minEpisodeWidth = '';
|
|
} else {
|
|
this.config.minEpisodeWidth = this.minEpisodeWidth.value;
|
|
}
|
|
|
|
if (_.isEmpty(this.minExpandedWidth.value)) {
|
|
this.config.minExpandedWidth = '';
|
|
} else {
|
|
this.config.minExpandedWidth = this.minExpandedWidth.value;
|
|
}
|
|
|
|
if (_.isEmpty(this.fontSize1.value)) {
|
|
this.config.fontSize1 = '';
|
|
} else {
|
|
this.config.fontSize1 = this.fontSize1.value;
|
|
}
|
|
|
|
if (_.isEmpty(this.fontSize2.value)) {
|
|
this.config.fontSize2 = '';
|
|
} else {
|
|
this.config.fontSize2 = this.fontSize2.value;
|
|
}
|
|
|
|
if (_.isEmpty(this.fontSize3.value)) {
|
|
this.config.fontSize3 = '';
|
|
} else {
|
|
this.config.fontSize3 = this.fontSize3.value;
|
|
}
|
|
|
|
if (_.isEmpty(this.fontSize4.value)) {
|
|
this.config.fontSize4 = '';
|
|
} else {
|
|
this.config.fontSize4 = this.fontSize4.value;
|
|
}
|
|
|
|
if (_.isEmpty(this.minExpandedHeight.value)) {
|
|
this.config.minExpandedHeight = '';
|
|
} else {
|
|
this.config.minExpandedHeight = this.minExpandedHeight.value;
|
|
}
|
|
|
|
if (_.isEmpty(this.cardTitle.value)) {
|
|
this.config.title = '';
|
|
} else {
|
|
this.config.title = this.cardTitle.value;
|
|
}
|
|
|
|
if (!_.isEmpty(this.entities)) {
|
|
this.config.entity = [];
|
|
_.forEach(this.entities, entity => {
|
|
if (!_.isEmpty(entity.value) && !_.includes(this.config.entity, entity.value)) {
|
|
this.config.entity.push(entity.value);
|
|
}
|
|
});
|
|
}
|
|
if (_.isEqual(this.playTrailer.value, 'Yes')) {
|
|
this.config.playTrailer = true;
|
|
} else if (_.isEqual(this.playTrailer.value, 'No')) {
|
|
this.config.playTrailer = false;
|
|
} else if (_.isEqual(this.playTrailer.value, 'Muted')) {
|
|
this.config.playTrailer = 'muted';
|
|
}
|
|
if (_.isEqual(this.showExtras.value, 'Yes')) {
|
|
this.config.showExtras = true;
|
|
} else if (_.isEqual(this.showExtras.value, 'No')) {
|
|
this.config.showExtras = false;
|
|
}
|
|
if (_.isEqual(this.showSearch.value, 'Yes')) {
|
|
this.config.showSearch = true;
|
|
} else if (_.isEqual(this.showSearch.value, 'No')) {
|
|
this.config.showSearch = false;
|
|
}
|
|
this.config.runBefore = this.runBefore.value;
|
|
this.config.runAfter = this.runAfter.value;
|
|
}
|
|
}
|
|
if (!_.isEqual(this.config, originalConfig)) {
|
|
this.fireEvent(this, 'config-changed', { config: this.config });
|
|
}
|
|
};
|
|
|
|
render = async (): Promise<void> => {
|
|
const addDropdownItem = (text: string, disabled = false): HTMLElement => {
|
|
const libraryItem: any = document.createElement('paper-item');
|
|
libraryItem.innerHTML = text.replace(/ /g, ' ');
|
|
libraryItem.label = text;
|
|
if (disabled) {
|
|
libraryItem.disabled = true;
|
|
}
|
|
return libraryItem;
|
|
};
|
|
const createEntitiesDropdown = (selected: string, changeHandler: Function): HTMLElement | false => {
|
|
if (this.entitiesRegistry) {
|
|
const entitiesDropDown: any = document.createElement('paper-dropdown-menu');
|
|
const entities: any = document.createElement('paper-listbox');
|
|
|
|
entities.appendChild(addDropdownItem(''));
|
|
const addedEntityStrings: Array<string> = [];
|
|
_.forEach(this.entitiesRegistry, entityRegistry => {
|
|
if (
|
|
_.isEqual(entityRegistry.platform, 'cast') ||
|
|
_.isEqual(entityRegistry.platform, 'kodi') ||
|
|
_.isEqual(entityRegistry.platform, 'androidtv')
|
|
) {
|
|
const entityName = `${entityRegistry.platform} | ${entityRegistry.entity_id}`;
|
|
entities.appendChild(addDropdownItem(entityName));
|
|
addedEntityStrings.push(entityName);
|
|
}
|
|
});
|
|
_.forEach(this.clients, value => {
|
|
const entityName = `plexPlayer | ${value.name} | ${value.address} | ${value.machineIdentifier}`;
|
|
entities.appendChild(addDropdownItem(entityName));
|
|
addedEntityStrings.push(entityName);
|
|
});
|
|
|
|
if (_.isArray(this.config.entity)) {
|
|
_.forEach(this.config.entity, value => {
|
|
if (!_.includes(addedEntityStrings, value)) {
|
|
entities.appendChild(addDropdownItem(value));
|
|
addedEntityStrings.push(value);
|
|
}
|
|
});
|
|
}
|
|
|
|
entities.slot = 'dropdown-content';
|
|
entitiesDropDown.label = 'Entity';
|
|
entitiesDropDown.value = selected;
|
|
entitiesDropDown.appendChild(entities);
|
|
entitiesDropDown.style.width = '100%';
|
|
entitiesDropDown.className = 'entitiesDropDown';
|
|
entitiesDropDown.addEventListener('value-changed', changeHandler);
|
|
this.entities.push(entitiesDropDown);
|
|
return entitiesDropDown;
|
|
}
|
|
return false;
|
|
};
|
|
if (this.content) this.content.remove();
|
|
if (this.hassObj && !this.entitiesRegistry) {
|
|
_.forOwn(this.hassObj.states, (value, key) => {
|
|
if (_.startsWith(key, 'script.')) {
|
|
this.scriptEntities.push(key);
|
|
}
|
|
});
|
|
this.entitiesRegistry = await fetchEntityRegistry(this.hassObj.connection);
|
|
}
|
|
|
|
this.entities = [];
|
|
this.content = document.createElement('div');
|
|
|
|
const plexTitle = document.createElement('h2');
|
|
plexTitle.innerHTML = 'Plex Configuration';
|
|
plexTitle.style.margin = '0px';
|
|
plexTitle.style.padding = '0px';
|
|
this.content.appendChild(plexTitle);
|
|
|
|
this.protocol.innerHTML = '';
|
|
const protocolItems: any = document.createElement('paper-listbox');
|
|
// eslint-disable-next-line no-restricted-globals
|
|
const pageProtocol = location.protocol;
|
|
if (_.isEqual(pageProtocol, 'http:')) {
|
|
protocolItems.appendChild(addDropdownItem('http'));
|
|
}
|
|
protocolItems.appendChild(addDropdownItem('https'));
|
|
protocolItems.slot = 'dropdown-content';
|
|
this.protocol.label = 'Plex Protocol';
|
|
this.protocol.appendChild(protocolItems);
|
|
this.protocol.style.width = '100%';
|
|
this.protocol.addEventListener('value-changed', this.valueUpdated);
|
|
if (_.isEmpty(this.config.protocol)) {
|
|
if (_.isEqual(pageProtocol, 'http:')) {
|
|
this.protocol.value = 'http';
|
|
} else {
|
|
this.protocol.value = 'https';
|
|
}
|
|
} else {
|
|
this.protocol.value = this.config.protocol;
|
|
}
|
|
this.content.appendChild(this.protocol);
|
|
|
|
this.ip.label = 'Plex IP Address / Hostname';
|
|
if (this.config.ip) {
|
|
this.ip.value = this.config.ip.replace(/^https?\:\/\//i, '').replace(/\/$/, '');
|
|
} else {
|
|
this.ip.value = this.config.ip;
|
|
}
|
|
|
|
this.ip.addEventListener('change', this.valueUpdated);
|
|
this.content.appendChild(this.ip);
|
|
|
|
this.port.label = 'Plex Port (Optional)';
|
|
this.port.value = this.config.port;
|
|
this.port.type = 'number';
|
|
this.port.addEventListener('change', this.valueUpdated);
|
|
this.content.appendChild(this.port);
|
|
|
|
this.token.label = 'Plex Token';
|
|
this.token.value = this.config.token;
|
|
this.token.addEventListener('change', this.valueUpdated);
|
|
this.content.appendChild(this.token);
|
|
|
|
this.libraryName.innerHTML = '';
|
|
const libraryItems: any = document.createElement('paper-listbox');
|
|
|
|
libraryItems.appendChild(addDropdownItem('Smart Libraries', true));
|
|
libraryItems.appendChild(addDropdownItem('Continue Watching'));
|
|
libraryItems.appendChild(addDropdownItem('Deck'));
|
|
libraryItems.appendChild(addDropdownItem('Recently Added'));
|
|
libraryItems.appendChild(addDropdownItem('Watch Next'));
|
|
libraryItems.slot = 'dropdown-content';
|
|
this.libraryName.label = 'Plex Library';
|
|
this.libraryName.disabled = true;
|
|
this.libraryName.appendChild(libraryItems);
|
|
this.libraryName.style.width = '100%';
|
|
this.libraryName.addEventListener('value-changed', this.valueUpdated);
|
|
|
|
const warningLibrary = document.createElement('div');
|
|
warningLibrary.style.color = 'red';
|
|
this.content.appendChild(this.libraryName);
|
|
this.content.appendChild(warningLibrary);
|
|
|
|
this.appendChild(this.content);
|
|
|
|
this.plex = new Plex(
|
|
this.config.ip.replace(/^https?\:\/\//i, '').replace(/\/$/, ''),
|
|
this.plexPort,
|
|
this.config.token,
|
|
this.plexProtocol,
|
|
this.config.sort
|
|
);
|
|
|
|
this.sections = await this.plex.getSections();
|
|
this.livetv = await this.plex.getLiveTV();
|
|
this.collections = await this.plex.getCollections();
|
|
this.playlists = await this.plex.getPlaylists();
|
|
this.clients = await this.plex.getClients();
|
|
|
|
this.plexValidSection.style.display = 'none';
|
|
this.plexValidSection.innerHTML = '';
|
|
|
|
let hasUIConfig = true;
|
|
let canConvert = true;
|
|
if (_.isArray(this.config.entity)) {
|
|
// eslint-disable-next-line consistent-return
|
|
_.forEach(this.config.entity, entity => {
|
|
if (_.isObjectLike(entity)) {
|
|
canConvert = !_.includes(_.keys(this.config.entity), 'plexPlayer');
|
|
hasUIConfig = false;
|
|
return false;
|
|
}
|
|
});
|
|
} else if (_.isObjectLike(this.config.entity)) {
|
|
canConvert = !_.includes(_.keys(this.config.entity), 'plexPlayer');
|
|
hasUIConfig = false;
|
|
if (canConvert) {
|
|
const convertedEntities: Array<string> = [];
|
|
hasUIConfig = true;
|
|
if (_.isObjectLike(this.config.entity)) {
|
|
_.forOwn(this.config.entity, value => {
|
|
if (_.isString(value)) {
|
|
convertedEntities.push(value);
|
|
} else if (_.isArray(value)) {
|
|
_.forEach(value, valueStr => {
|
|
convertedEntities.push(valueStr);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
this.config.entity = convertedEntities;
|
|
}
|
|
}
|
|
|
|
const devicesTitle = document.createElement('h2');
|
|
devicesTitle.innerHTML = `Devices Configuration`;
|
|
devicesTitle.style.lineHeight = '29px';
|
|
devicesTitle.style.marginBottom = '0px';
|
|
devicesTitle.style.marginTop = '20px';
|
|
if (hasUIConfig) {
|
|
const addDeviceButton = document.createElement('button');
|
|
addDeviceButton.style.float = 'right';
|
|
addDeviceButton.style.fontSize = '20px';
|
|
addDeviceButton.style.cursor = 'pointer';
|
|
addDeviceButton.innerHTML = '+';
|
|
addDeviceButton.addEventListener('click', () => {
|
|
const entitiesDropdown = createEntitiesDropdown('', this.valueUpdated);
|
|
if (entitiesDropdown) {
|
|
this.entitiesSection.appendChild(entitiesDropdown);
|
|
}
|
|
});
|
|
devicesTitle.appendChild(addDeviceButton);
|
|
}
|
|
|
|
this.plexValidSection.appendChild(devicesTitle);
|
|
this.entitiesSection.innerHTML = '';
|
|
this.plexValidSection.appendChild(this.entitiesSection);
|
|
if (hasUIConfig) {
|
|
if (_.isString(this.config.entity)) {
|
|
this.config.entity = [this.config.entity];
|
|
}
|
|
if (_.isArray(this.config.entity)) {
|
|
_.forEach(this.config.entity, entity => {
|
|
if (_.isString(entity)) {
|
|
const entitiesDropdown = createEntitiesDropdown(entity, this.valueUpdated);
|
|
if (entitiesDropdown) {
|
|
this.entitiesSection.appendChild(entitiesDropdown);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
} else {
|
|
const entitiesUINotAvailable = document.createElement('div');
|
|
entitiesUINotAvailable.innerHTML =
|
|
'Devices configuration is not available when using plexPlayer client device.<br/>You can edit any other settings through UI and use <b>Show code editor</b> to edit entities.<br/><br/>If you are not using server settings for plexPlayer with <b>identifier</b> and <b>server</b> key, you can migrate your settings to UI by removing plexPlayer section and readd through UI.';
|
|
this.plexValidSection.appendChild(entitiesUINotAvailable);
|
|
}
|
|
|
|
const viewTitle = document.createElement('h2');
|
|
viewTitle.innerHTML = `View Configuration`;
|
|
viewTitle.style.lineHeight = '29px';
|
|
viewTitle.style.marginBottom = '0px';
|
|
viewTitle.style.marginTop = '20px';
|
|
this.plexValidSection.appendChild(viewTitle);
|
|
|
|
this.cardTitle.label = 'Card title (Optional)';
|
|
this.cardTitle.value = this.config.title;
|
|
this.cardTitle.addEventListener('change', this.valueUpdated);
|
|
this.plexValidSection.appendChild(this.cardTitle);
|
|
|
|
this.maxCount.label = 'Maximum number of items to display (Optional)';
|
|
this.maxCount.value = this.config.maxCount;
|
|
this.maxCount.type = 'number';
|
|
this.maxCount.addEventListener('change', this.valueUpdated);
|
|
this.plexValidSection.appendChild(this.maxCount);
|
|
|
|
this.useHorizontalScroll.innerHTML = '';
|
|
const useHorizontalScrollItems: any = document.createElement('paper-listbox');
|
|
useHorizontalScrollItems.appendChild(addDropdownItem('Yes'));
|
|
useHorizontalScrollItems.appendChild(addDropdownItem('No'));
|
|
useHorizontalScrollItems.slot = 'dropdown-content';
|
|
this.useHorizontalScroll.label = 'Use horizontal scroll';
|
|
this.useHorizontalScroll.appendChild(useHorizontalScrollItems);
|
|
this.useHorizontalScroll.style.width = '100%';
|
|
this.useHorizontalScroll.addEventListener('value-changed', this.valueUpdated);
|
|
if (_.isEmpty(this.config.useHorizontalScroll)) {
|
|
this.useHorizontalScroll.value = 'No';
|
|
} else {
|
|
this.useHorizontalScroll.value = this.config.useHorizontalScroll;
|
|
}
|
|
this.plexValidSection.appendChild(this.useHorizontalScroll);
|
|
|
|
this.maxRows.label = 'Maximum number of rows to display (Optional)';
|
|
this.maxRows.value = this.config.maxRows;
|
|
this.maxRows.type = 'number';
|
|
this.maxRows.addEventListener('change', this.valueUpdated);
|
|
this.plexValidSection.appendChild(this.maxRows);
|
|
|
|
this.sort.innerHTML = '';
|
|
|
|
const sortItems: any = document.createElement('paper-listbox');
|
|
sortItems.slot = 'dropdown-content';
|
|
this.sort.label = 'Sort';
|
|
this.sort.appendChild(sortItems);
|
|
this.sort.style.width = '100%';
|
|
this.sort.addEventListener('value-changed', this.valueUpdated);
|
|
this.plexValidSection.appendChild(this.sort);
|
|
|
|
this.sortOrder.innerHTML = '';
|
|
const sortOrderItems: any = document.createElement('paper-listbox');
|
|
sortOrderItems.appendChild(addDropdownItem('Ascending'));
|
|
sortOrderItems.appendChild(addDropdownItem('Descending'));
|
|
sortOrderItems.slot = 'dropdown-content';
|
|
this.sortOrder.label = 'Sort Order';
|
|
this.sortOrder.appendChild(sortOrderItems);
|
|
this.sortOrder.style.width = '100%';
|
|
this.sortOrder.addEventListener('value-changed', this.valueUpdated);
|
|
if (_.isEmpty(this.config.sort)) {
|
|
this.sortOrder.value = 'Ascending';
|
|
} else {
|
|
const sortOrder = this.config.sort.split(':')[1];
|
|
if (_.isEmpty(sortOrder)) {
|
|
this.sortOrder.value = 'Ascending';
|
|
} else if (_.isEqual(sortOrder, 'asc')) {
|
|
this.sortOrder.value = 'Ascending';
|
|
} else if (_.isEqual(sortOrder, 'desc')) {
|
|
this.sortOrder.value = 'Descending';
|
|
}
|
|
}
|
|
this.plexValidSection.appendChild(this.sortOrder);
|
|
|
|
this.playTrailer.innerHTML = '';
|
|
const playTrailerItems: any = document.createElement('paper-listbox');
|
|
playTrailerItems.appendChild(addDropdownItem('Yes'));
|
|
playTrailerItems.appendChild(addDropdownItem('Muted'));
|
|
playTrailerItems.appendChild(addDropdownItem('No'));
|
|
playTrailerItems.slot = 'dropdown-content';
|
|
this.playTrailer.label = 'Play Trailer';
|
|
this.playTrailer.appendChild(playTrailerItems);
|
|
this.playTrailer.style.width = '100%';
|
|
this.playTrailer.addEventListener('value-changed', this.valueUpdated);
|
|
let playTrailerValue = 'Yes';
|
|
if (_.isEqual(this.config.playTrailer, 'muted')) {
|
|
playTrailerValue = 'Muted';
|
|
} else if (!this.config.playTrailer) {
|
|
playTrailerValue = 'No';
|
|
}
|
|
this.playTrailer.value = playTrailerValue;
|
|
this.plexValidSection.appendChild(this.playTrailer);
|
|
|
|
this.showExtras.innerHTML = '';
|
|
const showExtrasItems: any = document.createElement('paper-listbox');
|
|
showExtrasItems.appendChild(addDropdownItem('Yes'));
|
|
showExtrasItems.appendChild(addDropdownItem('No'));
|
|
showExtrasItems.slot = 'dropdown-content';
|
|
this.showExtras.label = 'Show Extras';
|
|
this.showExtras.appendChild(showExtrasItems);
|
|
this.showExtras.style.width = '100%';
|
|
this.showExtras.addEventListener('value-changed', this.valueUpdated);
|
|
let showExtrasValue = 'Yes';
|
|
if (!this.config.showExtras) {
|
|
showExtrasValue = 'No';
|
|
}
|
|
this.showExtras.value = showExtrasValue;
|
|
this.plexValidSection.appendChild(this.showExtras);
|
|
|
|
this.showSearch.innerHTML = '';
|
|
const showSearchItems: any = document.createElement('paper-listbox');
|
|
showSearchItems.appendChild(addDropdownItem('Yes'));
|
|
showSearchItems.appendChild(addDropdownItem('No'));
|
|
showSearchItems.slot = 'dropdown-content';
|
|
this.showSearch.label = 'Show Search';
|
|
this.showSearch.appendChild(showSearchItems);
|
|
this.showSearch.style.width = '100%';
|
|
this.showSearch.addEventListener('value-changed', this.valueUpdated);
|
|
let showSearchValue = 'Yes';
|
|
if (!this.config.showSearch) {
|
|
showSearchValue = 'No';
|
|
}
|
|
this.showSearch.value = showSearchValue;
|
|
this.plexValidSection.appendChild(this.showSearch);
|
|
|
|
this.runBefore.innerHTML = '';
|
|
const runBeforeItems: any = document.createElement('paper-listbox');
|
|
runBeforeItems.appendChild(addDropdownItem(''));
|
|
_.forEach(this.scriptEntities, entity => {
|
|
runBeforeItems.appendChild(addDropdownItem(entity));
|
|
});
|
|
runBeforeItems.slot = 'dropdown-content';
|
|
this.runBefore.label = 'Script to execute before starting the media (Optional)';
|
|
this.runBefore.appendChild(runBeforeItems);
|
|
this.runBefore.style.width = '100%';
|
|
this.runBefore.addEventListener('value-changed', this.valueUpdated);
|
|
this.runBefore.value = this.config.runBefore;
|
|
this.plexValidSection.appendChild(this.runBefore);
|
|
|
|
this.runAfter.innerHTML = '';
|
|
const runAfterItems: any = document.createElement('paper-listbox');
|
|
runAfterItems.appendChild(addDropdownItem(''));
|
|
_.forEach(this.scriptEntities, entity => {
|
|
runAfterItems.appendChild(addDropdownItem(entity));
|
|
});
|
|
runAfterItems.slot = 'dropdown-content';
|
|
this.runAfter.label = 'Script to execute after starting the media (Optional)';
|
|
this.runAfter.appendChild(runAfterItems);
|
|
this.runAfter.style.width = '100%';
|
|
this.runAfter.addEventListener('value-changed', this.valueUpdated);
|
|
this.runAfter.value = this.config.runAfter;
|
|
this.plexValidSection.appendChild(this.runAfter);
|
|
|
|
const styleTitle = document.createElement('h2');
|
|
styleTitle.innerHTML = `Style Configuration`;
|
|
styleTitle.style.lineHeight = '29px';
|
|
styleTitle.style.marginBottom = '0px';
|
|
styleTitle.style.marginTop = '20px';
|
|
this.plexValidSection.appendChild(styleTitle);
|
|
|
|
this.minWidth.label = 'Minimum width of the card (Optional)';
|
|
this.minWidth.value = this.config.minWidth;
|
|
this.minWidth.type = 'number';
|
|
this.minWidth.addEventListener('change', this.valueUpdated);
|
|
this.plexValidSection.appendChild(this.minWidth);
|
|
|
|
this.minExpandedWidth.label = 'Expanded width of the card (Optional)';
|
|
this.minExpandedWidth.value = this.config.minExpandedWidth;
|
|
this.minExpandedWidth.type = 'number';
|
|
this.minExpandedWidth.addEventListener('change', this.valueUpdated);
|
|
this.plexValidSection.appendChild(this.minExpandedWidth);
|
|
|
|
this.minExpandedHeight.label = 'Expanded height of the card (Optional)';
|
|
this.minExpandedHeight.value = this.config.minExpandedHeight;
|
|
this.minExpandedHeight.type = 'number';
|
|
this.minExpandedHeight.addEventListener('change', this.valueUpdated);
|
|
this.plexValidSection.appendChild(this.minExpandedHeight);
|
|
|
|
this.minEpisodeWidth.label = 'Minimum width of the episode card (Optional)';
|
|
this.minEpisodeWidth.value = this.config.minEpisodeWidth;
|
|
this.minEpisodeWidth.type = 'number';
|
|
this.minEpisodeWidth.addEventListener('change', this.valueUpdated);
|
|
this.plexValidSection.appendChild(this.minEpisodeWidth);
|
|
|
|
this.displayTitleMain.innerHTML = '';
|
|
const displayTitleMainItems: any = document.createElement('paper-listbox');
|
|
displayTitleMainItems.appendChild(addDropdownItem('Yes'));
|
|
displayTitleMainItems.appendChild(addDropdownItem('No'));
|
|
displayTitleMainItems.slot = 'dropdown-content';
|
|
this.displayTitleMain.label = 'Display title under poster';
|
|
this.displayTitleMain.appendChild(displayTitleMainItems);
|
|
this.displayTitleMain.style.width = '100%';
|
|
this.displayTitleMain.addEventListener('value-changed', this.valueUpdated);
|
|
if (_.isEmpty(this.config.displayTitleMain)) {
|
|
this.displayTitleMain.value = 'Yes';
|
|
} else {
|
|
this.displayTitleMain.value = this.config.displayTitleMain;
|
|
}
|
|
this.plexValidSection.appendChild(this.displayTitleMain);
|
|
|
|
this.fontSize1.label = 'Font size used in titles under cards (Optional)';
|
|
this.fontSize1.value = this.config.fontSize1;
|
|
this.fontSize1.type = 'number';
|
|
this.fontSize1.addEventListener('change', this.valueUpdated);
|
|
this.plexValidSection.appendChild(this.fontSize1);
|
|
|
|
this.displaySubtitleMain.innerHTML = '';
|
|
const displaySubtitleMainItems: any = document.createElement('paper-listbox');
|
|
displaySubtitleMainItems.appendChild(addDropdownItem('Yes'));
|
|
displaySubtitleMainItems.appendChild(addDropdownItem('No'));
|
|
displaySubtitleMainItems.slot = 'dropdown-content';
|
|
this.displaySubtitleMain.label = 'Display sub-title under poster';
|
|
this.displaySubtitleMain.appendChild(displaySubtitleMainItems);
|
|
this.displaySubtitleMain.style.width = '100%';
|
|
this.displaySubtitleMain.addEventListener('value-changed', this.valueUpdated);
|
|
if (_.isEmpty(this.config.displaySubtitleMain)) {
|
|
this.displaySubtitleMain.value = 'Yes';
|
|
} else {
|
|
this.displaySubtitleMain.value = this.config.displaySubtitleMain;
|
|
}
|
|
this.plexValidSection.appendChild(this.displaySubtitleMain);
|
|
|
|
this.fontSize2.label = 'Font size used in sub-titles under cards (Optional)';
|
|
this.fontSize2.value = this.config.fontSize2;
|
|
this.fontSize2.type = 'number';
|
|
this.fontSize2.addEventListener('change', this.valueUpdated);
|
|
this.plexValidSection.appendChild(this.fontSize2);
|
|
|
|
this.fontSize3.label = 'Font size used in title of the opened content (Optional)';
|
|
this.fontSize3.value = this.config.fontSize3;
|
|
this.fontSize3.type = 'number';
|
|
this.fontSize3.addEventListener('change', this.valueUpdated);
|
|
this.plexValidSection.appendChild(this.fontSize3);
|
|
|
|
this.fontSize4.label =
|
|
'Font size used in sub-titles, to-view count and description of the opened content (Optional)';
|
|
this.fontSize4.value = this.config.fontSize4;
|
|
this.fontSize4.type = 'number';
|
|
this.fontSize4.addEventListener('change', this.valueUpdated);
|
|
this.plexValidSection.appendChild(this.fontSize4);
|
|
|
|
if (!_.isEmpty(this.livetv)) {
|
|
libraryItems.appendChild(addDropdownItem('Live TV', true));
|
|
_.forEach(_.keys(this.livetv), (livetv: string) => {
|
|
if (_.isEqual(this.config.libraryName, livetv)) {
|
|
warningLibrary.innerHTML = `Warning: ${this.config.libraryName} play action currently only supported with Kodi.<br/>You might also need custom build of kodi-media-sensors, see <a href="https://github.com/JurajNyiri/PlexMeetsHomeAssistant/blob/main/DETAILED_CONFIGURATION.md#kodi" target="_blank">detailed configuration</a> for more information.`;
|
|
}
|
|
libraryItems.appendChild(addDropdownItem(livetv));
|
|
});
|
|
}
|
|
if (!_.isEmpty(this.sections)) {
|
|
libraryItems.appendChild(addDropdownItem('Libraries', true));
|
|
_.forEach(this.sections, (section: Record<string, any>) => {
|
|
libraryItems.appendChild(addDropdownItem(section.title));
|
|
});
|
|
if (!_.isEmpty(this.collections)) {
|
|
libraryItems.appendChild(addDropdownItem('Collections', true));
|
|
_.forEach(this.collections, (collection: Record<string, any>) => {
|
|
libraryItems.appendChild(addDropdownItem(collection.title));
|
|
});
|
|
}
|
|
if (!_.isEmpty(this.playlists)) {
|
|
libraryItems.appendChild(addDropdownItem('Playlists', true));
|
|
_.forEach(this.playlists, (playlist: Record<string, any>) => {
|
|
libraryItems.appendChild(addDropdownItem(playlist.title));
|
|
});
|
|
}
|
|
|
|
this.libraryName.disabled = false;
|
|
this.libraryName.value = this.config.libraryName;
|
|
|
|
let libraryType = '';
|
|
// eslint-disable-next-line consistent-return
|
|
_.forEach(this.sections, section => {
|
|
if (_.isEqual(section.title, this.libraryName.value)) {
|
|
libraryType = section.type;
|
|
return false;
|
|
}
|
|
});
|
|
if (_.isEqual(libraryType, 'show')) {
|
|
sortItems.appendChild(addDropdownItem('titleSort'));
|
|
sortItems.appendChild(addDropdownItem('title'));
|
|
sortItems.appendChild(addDropdownItem('year'));
|
|
sortItems.appendChild(addDropdownItem('originallyAvailableAt'));
|
|
sortItems.appendChild(addDropdownItem('rating'));
|
|
sortItems.appendChild(addDropdownItem('audienceRating'));
|
|
sortItems.appendChild(addDropdownItem('userRating'));
|
|
sortItems.appendChild(addDropdownItem('contentRating'));
|
|
sortItems.appendChild(addDropdownItem('unviewedLeafCount'));
|
|
sortItems.appendChild(addDropdownItem('episode.addedAt'));
|
|
sortItems.appendChild(addDropdownItem('addedAt'));
|
|
sortItems.appendChild(addDropdownItem('lastViewedAt'));
|
|
this.sort.style.display = 'block';
|
|
this.sortOrder.style.display = 'block';
|
|
} else if (_.isEqual(libraryType, 'movie')) {
|
|
sortItems.appendChild(addDropdownItem('titleSort'));
|
|
sortItems.appendChild(addDropdownItem('title'));
|
|
sortItems.appendChild(addDropdownItem('originallyAvailableAt'));
|
|
sortItems.appendChild(addDropdownItem('rating'));
|
|
sortItems.appendChild(addDropdownItem('audienceRating'));
|
|
sortItems.appendChild(addDropdownItem('userRating'));
|
|
sortItems.appendChild(addDropdownItem('duration'));
|
|
sortItems.appendChild(addDropdownItem('viewOffset'));
|
|
sortItems.appendChild(addDropdownItem('viewCount'));
|
|
sortItems.appendChild(addDropdownItem('addedAt'));
|
|
sortItems.appendChild(addDropdownItem('lastViewedAt'));
|
|
sortItems.appendChild(addDropdownItem('mediaHeight'));
|
|
sortItems.appendChild(addDropdownItem('mediaBitrate'));
|
|
this.sort.style.display = 'block';
|
|
this.sortOrder.style.display = 'block';
|
|
} else {
|
|
this.sort.style.display = 'none';
|
|
this.sortOrder.style.display = 'none';
|
|
this.config.sort = '';
|
|
}
|
|
|
|
if (_.isEmpty(this.config.sort)) {
|
|
this.sort.value = '';
|
|
this.sortOrder.value = '';
|
|
} else {
|
|
// eslint-disable-next-line prefer-destructuring
|
|
this.sort.value = this.config.sort.split(':')[0];
|
|
const sortOrder = this.config.sort.split(':')[1];
|
|
if (_.isEmpty(sortOrder)) {
|
|
this.sortOrder.value = 'Ascending';
|
|
} else if (_.isEqual(sortOrder, 'asc')) {
|
|
this.sortOrder.value = 'Ascending';
|
|
} else if (_.isEqual(sortOrder, 'desc')) {
|
|
this.sortOrder.value = 'Descending';
|
|
}
|
|
}
|
|
|
|
this.plexValidSection.style.display = 'block';
|
|
}
|
|
this.loaded = true;
|
|
this.content.appendChild(this.plexValidSection);
|
|
};
|
|
|
|
setConfig = (config: Record<string, any>): void => {
|
|
this.config = JSON.parse(JSON.stringify(config));
|
|
|
|
if (config.port && !_.isEqual(config.port, '')) {
|
|
this.plexPort = config.port;
|
|
} else {
|
|
this.plexPort = false;
|
|
}
|
|
|
|
// eslint-disable-next-line no-restricted-globals
|
|
const pageProtocol = location.protocol;
|
|
if (config.protocol) {
|
|
this.plexProtocol = config.protocol;
|
|
} else if (_.isEqual(pageProtocol, 'http:')) {
|
|
this.config.protocol = 'http';
|
|
} else {
|
|
this.config.protocol = 'https';
|
|
}
|
|
|
|
if (!config.sort) {
|
|
this.config.sort = 'titleSort:asc';
|
|
}
|
|
|
|
if (!_.isNil(config.playTrailer)) {
|
|
this.config.playTrailer = config.playTrailer;
|
|
} else {
|
|
this.config.playTrailer = true;
|
|
}
|
|
|
|
if (!_.isNil(config.showExtras)) {
|
|
this.config.showExtras = config.showExtras;
|
|
} else {
|
|
this.config.showExtras = true;
|
|
}
|
|
|
|
if (!_.isNil(config.showSearch)) {
|
|
this.config.showSearch = config.showSearch;
|
|
} else {
|
|
this.config.showSearch = true;
|
|
}
|
|
|
|
if (!_.isNil(config.runBefore)) {
|
|
this.config.runBefore = config.runBefore;
|
|
}
|
|
|
|
if (!_.isNil(config.runAfter)) {
|
|
this.config.runAfter = config.runAfter;
|
|
}
|
|
|
|
if (!_.isNil(config.title)) {
|
|
this.config.title = config.title;
|
|
}
|
|
|
|
if (_.isNumber(this.config.maxCount)) {
|
|
this.config.maxCount = `${this.config.maxCount}`;
|
|
}
|
|
|
|
if (_.isNumber(this.config.maxRows)) {
|
|
this.config.maxRows = `${this.config.maxRows}`;
|
|
}
|
|
|
|
if (!_.isNil(this.config.useHorizontalScroll)) {
|
|
this.config.useHorizontalScroll = `${this.config.useHorizontalScroll}`;
|
|
}
|
|
|
|
if (!_.isNil(this.config.displayTitleMain)) {
|
|
this.config.displayTitleMain = `${this.config.displayTitleMain}`;
|
|
}
|
|
|
|
if (!_.isNil(this.config.displaySubtitleMain)) {
|
|
this.config.displaySubtitleMain = `${this.config.displaySubtitleMain}`;
|
|
}
|
|
|
|
if (_.isNumber(this.config.minWidth)) {
|
|
this.config.minWidth = `${this.config.minWidth}`;
|
|
}
|
|
|
|
if (_.isNumber(this.config.minEpisodeWidth)) {
|
|
this.config.minEpisodeWidth = `${this.config.minEpisodeWidth}`;
|
|
}
|
|
|
|
if (_.isNumber(this.config.minExpandedWidth)) {
|
|
this.config.minExpandedWidth = `${this.config.minExpandedWidth}`;
|
|
}
|
|
|
|
if (_.isNumber(this.config.fontSize1)) {
|
|
this.config.fontSize1 = `${this.config.fontSize1}`;
|
|
}
|
|
|
|
if (_.isNumber(this.config.fontSize2)) {
|
|
this.config.fontSize2 = `${this.config.fontSize2}`;
|
|
}
|
|
|
|
if (_.isNumber(this.config.fontSize3)) {
|
|
this.config.fontSize3 = `${this.config.fontSize3}`;
|
|
}
|
|
|
|
if (_.isNumber(this.config.fontSize4)) {
|
|
this.config.fontSize4 = `${this.config.fontSize4}`;
|
|
}
|
|
|
|
if (_.isNumber(this.config.minExpandedHeight)) {
|
|
this.config.minExpandedHeight = `${this.config.minExpandedHeight}`;
|
|
}
|
|
|
|
this.render();
|
|
};
|
|
|
|
configChanged = (newConfig: any): void => {
|
|
const event: any = new Event('config-changed', {
|
|
bubbles: true,
|
|
composed: true
|
|
});
|
|
event.detail = { config: newConfig };
|
|
this.dispatchEvent(event);
|
|
};
|
|
|
|
set hass(hass: HomeAssistant) {
|
|
this.hassObj = hass;
|
|
}
|
|
}
|
|
export default PlexMeetsHomeAssistantEditor;
|