1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

Merge branch 'es6' into es6-migration-3

This commit is contained in:
dkanada 2020-06-28 04:40:43 +09:00 committed by GitHub
commit 8e35cceaf0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
110 changed files with 4577 additions and 1412 deletions

View file

@ -31,7 +31,7 @@ define(['browser', 'dialog', 'globalize'], function (browser, dialog, globalize)
options.buttons = items;
return dialog(options).then(function (result) {
return dialog.show(options).then(function (result) {
if (result === 'ok') {
return Promise.resolve();
}

View file

@ -192,9 +192,14 @@ button::-moz-focus-inner {
/* Needed in case this is a button */
display: block;
/* Needed in case this is a button */
margin: 0 !important;
border: 0 !important;
padding: 0 !important;
cursor: pointer;
color: inherit;
width: 100%;
font-family: inherit;
font-size: inherit;
/* Needed in safari */
height: 100%;
@ -203,19 +208,12 @@ button::-moz-focus-inner {
contain: strict;
}
.cardContent-button {
border: 0 !important;
padding: 0 !important;
cursor: pointer;
color: inherit;
width: 100%;
vertical-align: middle;
font-family: inherit;
font-size: inherit;
.cardContent:not(.defaultCardBackground) {
background-color: transparent;
}
.cardContent-button:not(.defaultCardBackground) {
background-color: transparent;
.cardBox:not(.visualCardBox) .cardPadder {
background-color: #242424;
}
.visualCardBox .cardContent {
@ -223,7 +221,8 @@ button::-moz-focus-inner {
border-bottom-right-radius: 0;
}
.cardContent-shadow {
.cardContent-shadow,
.cardBox:not(.visualCardBox) .cardPadder {
box-shadow: 0 0.0725em 0.29em 0 rgba(0, 0, 0, 0.37);
}

View file

@ -368,9 +368,7 @@ import 'programStyles';
let apiClient;
let lastServerId;
for (let i = 0; i < items.length; i++) {
let item = items[i];
for (const [i, item] of items.entries()) {
let serverId = item.ServerId || options.serverId;
if (serverId !== lastServerId) {
@ -541,7 +539,7 @@ import 'programStyles';
imgType = 'Backdrop';
imgTag = item.ParentBackdropImageTags[0];
itemId = item.ParentBackdropItemId;
} else if (item.ImageTags && item.ImageTags.Primary) {
} else if (item.ImageTags && item.ImageTags.Primary && (item.Type !== 'Episode' || item.ChildCount !== 0)) {
imgType = 'Primary';
imgTag = item.ImageTags.Primary;
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
@ -556,7 +554,10 @@ import 'programStyles';
coverImage = (Math.abs(primaryImageAspectRatio - uiAspect) / uiAspect) <= 0.2;
}
}
} else if (item.SeriesPrimaryImageTag) {
imgType = 'Primary';
imgTag = item.SeriesPrimaryImageTag;
itemId = item.SeriesId;
} else if (item.PrimaryImageTag) {
imgType = 'Primary';
imgTag = item.PrimaryImageTag;
@ -577,10 +578,6 @@ import 'programStyles';
imgType = 'Primary';
imgTag = item.ParentPrimaryImageTag;
itemId = item.ParentPrimaryImageItemId;
} else if (item.SeriesPrimaryImageTag) {
imgType = 'Primary';
imgTag = item.SeriesPrimaryImageTag;
itemId = item.SeriesId;
} else if (item.AlbumId && item.AlbumPrimaryImageTag) {
imgType = 'Primary';
imgTag = item.AlbumPrimaryImageTag;
@ -1370,9 +1367,6 @@ import 'programStyles';
let cardScalableClose = '';
let cardContentClass = 'cardContent';
if (!options.cardLayout) {
cardContentClass += ' cardContent-shadow';
}
let blurhashAttrib = '';
if (blurhash && blurhash.length > 0) {
@ -1380,21 +1374,20 @@ import 'programStyles';
}
if (layoutManager.tv) {
// Don't use the IMG tag with safari because it puts a white border around it
cardImageContainerOpen = imgUrl ? ('<div class="' + cardImageContainerClass + ' ' + cardContentClass + ' lazy" data-src="' + imgUrl + '" ' + blurhashAttrib + '>') : ('<div class="' + cardImageContainerClass + ' ' + cardContentClass + '">');
cardImageContainerClose = '</div>';
} else {
// Don't use the IMG tag with safari because it puts a white border around it
cardImageContainerOpen = imgUrl ? ('<button data-action="' + action + '" class="cardContent-button ' + cardImageContainerClass + ' ' + cardContentClass + ' itemAction lazy" data-src="' + imgUrl + '" ' + blurhashAttrib + '>') : ('<button data-action="' + action + '" class="cardContent-button ' + cardImageContainerClass + ' ' + cardContentClass + ' itemAction">');
cardImageContainerOpen = imgUrl ? ('<button data-action="' + action + '" class="' + cardImageContainerClass + ' ' + cardContentClass + ' itemAction lazy" data-src="' + imgUrl + '" ' + blurhashAttrib + '>') : ('<button data-action="' + action + '" class="' + cardImageContainerClass + ' ' + cardContentClass + ' itemAction">');
cardImageContainerClose = '</button>';
}
let cardScalableClass = 'cardScalable';
cardImageContainerOpen = '<div class="' + cardBoxClass + '"><div class="' + cardScalableClass + '"><div class="cardPadder-' + shape + '"></div>' + cardImageContainerOpen;
cardImageContainerOpen = '<div class="' + cardBoxClass + '"><div class="' + cardScalableClass + '"><div class="cardPadder cardPadder-' + shape + '"></div>' + cardImageContainerOpen;
cardBoxClose = '</div>';
cardScalableClose = '</div>';

View file

@ -1,10 +1,21 @@
define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'actionsheet', 'emby-input', 'paper-icon-button-light', 'emby-button', 'listViewStyle', 'material-icons', 'formDialogStyle'], function (dom, dialogHelper, loading, connectionManager, globalize, actionsheet) {
'use strict';
import dom from 'dom';
import dialogHelper from 'dialogHelper';
import loading from 'loading';
import connectionManager from 'connectionManager';
import globalize from 'globalize';
import actionsheet from 'actionsheet';
import 'emby-input';
import 'paper-icon-button-light';
import 'emby-button';
import 'listViewStyle';
import 'material-icons';
import 'formDialogStyle';
return function (options) {
export default class channelMapper {
constructor(options) {
function mapChannel(button, channelId, providerChannelId) {
loading.show();
var providerId = options.providerId;
const providerId = options.providerId;
connectionManager.getApiClient(options.serverId).ajax({
type: 'POST',
url: ApiClient.getUrl('LiveTv/ChannelMappings'),
@ -14,8 +25,8 @@ define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'act
providerChannelId: providerChannelId
},
dataType: 'json'
}).then(function (mapping) {
var listItem = dom.parentWithClass(button, 'listItem');
}).then(mapping => {
const listItem = dom.parentWithClass(button, 'listItem');
button.setAttribute('data-providerid', mapping.ProviderChannelId);
listItem.querySelector('.secondary').innerHTML = getMappingSecondaryName(mapping, currentMappingOptions.ProviderName);
loading.hide();
@ -23,42 +34,42 @@ define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'act
}
function onChannelsElementClick(e) {
var btnMap = dom.parentWithClass(e.target, 'btnMap');
const btnMap = dom.parentWithClass(e.target, 'btnMap');
if (btnMap) {
var channelId = btnMap.getAttribute('data-id');
var providerChannelId = btnMap.getAttribute('data-providerid');
var menuItems = currentMappingOptions.ProviderChannels.map(function (m) {
const channelId = btnMap.getAttribute('data-id');
const providerChannelId = btnMap.getAttribute('data-providerid');
const menuItems = currentMappingOptions.ProviderChannels.map(m => {
return {
name: m.Name,
id: m.Id,
selected: m.Id.toLowerCase() === providerChannelId.toLowerCase()
};
}).sort(function (a, b) {
}).sort((a, b) => {
return a.name.localeCompare(b.name);
});
actionsheet.show({
positionTo: btnMap,
items: menuItems
}).then(function (newChannelId) {
}).then(newChannelId => {
mapChannel(btnMap, channelId, newChannelId);
});
}
}
function getChannelMappingOptions(serverId, providerId) {
var apiClient = connectionManager.getApiClient(serverId);
const apiClient = connectionManager.getApiClient(serverId);
return apiClient.getJSON(apiClient.getUrl('LiveTv/ChannelMappingOptions', {
providerId: providerId
}));
}
function getMappingSecondaryName(mapping, providerName) {
return (mapping.ProviderChannelName || '') + ' - ' + providerName;
return `${mapping.ProviderChannelName || ''} - ${providerName}`;
}
function getTunerChannelHtml(channel, providerName) {
var html = '';
let html = '';
html += '<div class="listItem">';
html += '<span class="material-icons listItemIcon dvr"></span>';
html += '<div class="listItemBody two-line">';
@ -73,16 +84,16 @@ define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'act
html += '</div>';
html += '</div>';
html += '<button class="btnMap autoSize" is="paper-icon-button-light" type="button" data-id="' + channel.Id + '" data-providerid="' + channel.ProviderChannelId + '"><span class="material-icons mode_edit"></span></button>';
html += `<button class="btnMap autoSize" is="paper-icon-button-light" type="button" data-id="${channel.Id}" data-providerid="${channel.ProviderChannelId}"><span class="material-icons mode_edit"></span></button>`;
return html += '</div>';
}
function getEditorHtml() {
var html = '';
let html = '';
html += '<div class="formDialogContent smoothScrollY">';
html += '<div class="dialogContentInner dialog-content-centered">';
html += '<form style="margin:auto;">';
html += '<h1>' + globalize.translate('HeaderChannels') + '</h1>';
html += `<h1>${globalize.translate('HeaderChannels')}</h1>`;
html += '<div class="channels paperList">';
html += '</div>';
html += '</form>';
@ -91,30 +102,29 @@ define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'act
}
function initEditor(dlg, options) {
getChannelMappingOptions(options.serverId, options.providerId).then(function (result) {
getChannelMappingOptions(options.serverId, options.providerId).then(result => {
currentMappingOptions = result;
var channelsElement = dlg.querySelector('.channels');
channelsElement.innerHTML = result.TunerChannels.map(function (channel) {
const channelsElement = dlg.querySelector('.channels');
channelsElement.innerHTML = result.TunerChannels.map(channel => {
return getTunerChannelHtml(channel, result.ProviderName);
}).join('');
channelsElement.addEventListener('click', onChannelsElementClick);
});
}
var currentMappingOptions;
var self = this;
let currentMappingOptions;
self.show = function () {
var dialogOptions = {
this.show = () => {
const dialogOptions = {
removeOnClose: true
};
dialogOptions.size = 'small';
var dlg = dialogHelper.createDialog(dialogOptions);
const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog');
dlg.classList.add('ui-body-a');
dlg.classList.add('background-theme-a');
var html = '';
var title = globalize.translate('MapChannels');
let html = '';
const title = globalize.translate('MapChannels');
html += '<div class="formDialogHeader">';
html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
html += '<h3 class="formDialogHeaderTitle">';
@ -124,13 +134,13 @@ define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'act
html += getEditorHtml();
dlg.innerHTML = html;
initEditor(dlg, options);
dlg.querySelector('.btnCancel').addEventListener('click', function () {
dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg);
});
return new Promise(function (resolve, reject) {
return new Promise(resolve => {
dlg.addEventListener('close', resolve);
dialogHelper.open(dlg);
});
};
};
});
}
}

View file

@ -53,7 +53,7 @@ define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize)
options.buttons = items;
return dialog(options).then(function (result) {
return dialog.show(options).then(function (result) {
if (result === 'ok') {
return Promise.resolve();
}

View file

@ -1,20 +1,31 @@
define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 'require', 'material-icons', 'emby-button', 'paper-icon-button-light', 'emby-input', 'formDialogStyle', 'flexStyles'], function (dialogHelper, dom, layoutManager, scrollHelper, globalize, require) {
'use strict';
import dialogHelper from 'dialogHelper';
import dom from 'dom';
import layoutManager from 'layoutManager';
import scrollHelper from 'scrollHelper';
import globalize from 'globalize';
import 'material-icons';
import 'emby-button';
import 'paper-icon-button-light';
import 'emby-input';
import 'formDialogStyle';
import 'flexStyles';
/* eslint-disable indent */
function showDialog(options, template) {
var dialogOptions = {
const dialogOptions = {
removeOnClose: true,
scrollY: false
};
var enableTvLayout = layoutManager.tv;
const enableTvLayout = layoutManager.tv;
if (enableTvLayout) {
dialogOptions.size = 'fullscreen';
}
var dlg = dialogHelper.createDialog(dialogOptions);
const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog');
@ -22,7 +33,7 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
dlg.classList.add('align-items-center');
dlg.classList.add('justify-content-center');
var formDialogContent = dlg.querySelector('.formDialogContent');
const formDialogContent = dlg.querySelector('.formDialogContent');
formDialogContent.classList.add('no-grow');
if (enableTvLayout) {
@ -30,7 +41,7 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
formDialogContent.style['max-height'] = '60%';
scrollHelper.centerFocus.on(formDialogContent, false);
} else {
formDialogContent.style.maxWidth = (Math.min((options.buttons.length * 150) + 200, dom.getWindowSize().innerWidth - 50)) + 'px';
formDialogContent.style.maxWidth = `${Math.min((options.buttons.length * 150) + 200, dom.getWindowSize().innerWidth - 50)}px`;
dlg.classList.add('dialog-fullscreen-lowres');
}
@ -44,27 +55,27 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
dlg.querySelector('.formDialogHeaderTitle').classList.add('hide');
}
var displayText = options.html || options.text || '';
const displayText = options.html || options.text || '';
dlg.querySelector('.text').innerHTML = displayText;
if (!displayText) {
dlg.querySelector('.dialogContentInner').classList.add('hide');
}
var i;
var length;
var html = '';
var hasDescriptions = false;
let i;
let length;
let html = '';
let hasDescriptions = false;
for (i = 0, length = options.buttons.length; i < length; i++) {
var item = options.buttons[i];
var autoFocus = i === 0 ? ' autofocus' : '';
const item = options.buttons[i];
const autoFocus = i === 0 ? ' autofocus' : '';
var buttonClass = 'btnOption raised formDialogFooterItem formDialogFooterItem-autosize';
let buttonClass = 'btnOption raised formDialogFooterItem formDialogFooterItem-autosize';
if (item.type) {
buttonClass += ' button-' + item.type;
buttonClass += ` button-${item.type}`;
}
if (item.description) {
@ -75,10 +86,10 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
buttonClass += ' formDialogFooterItem-vertical formDialogFooterItem-nomarginbottom';
}
html += '<button is="emby-button" type="button" class="' + buttonClass + '" data-id="' + item.id + '"' + autoFocus + '>' + item.name + '</button>';
html += `<button is="emby-button" type="button" class="${buttonClass}" data-id="${item.id}"${autoFocus}>${item.name}</button>`;
if (item.description) {
html += '<div class="formDialogFooterItem formDialogFooterItem-autosize fieldDescription" style="margin-top:.25em!important;margin-bottom:1.25em!important;">' + item.description + '</div>';
html += `<div class="formDialogFooterItem formDialogFooterItem-autosize fieldDescription" style="margin-top:.25em!important;margin-bottom:1.25em!important;">${item.description}</div>`;
}
}
@ -88,18 +99,18 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
dlg.querySelector('.formDialogFooter').classList.add('formDialogFooter-vertical');
}
var dialogResult;
let dialogResult;
function onButtonClick() {
dialogResult = this.getAttribute('data-id');
dialogHelper.close(dlg);
}
var buttons = dlg.querySelectorAll('.btnOption');
const buttons = dlg.querySelectorAll('.btnOption');
for (i = 0, length = buttons.length; i < length; i++) {
buttons[i].addEventListener('click', onButtonClick);
}
return dialogHelper.open(dlg).then(function () {
return dialogHelper.open(dlg).then(() => {
if (enableTvLayout) {
scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false);
@ -113,9 +124,9 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
});
}
return function (text, title) {
export async function show(text, title) {
var options;
let options;
if (typeof text === 'string') {
options = {
title: title,
@ -125,10 +136,13 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
options = text;
}
return new Promise(function (resolve, reject) {
require(['text!./dialog.template.html'], function (template) {
showDialog(options, template).then(resolve, reject);
});
const { default: template } = await import('text!./dialog.template.html');
return new Promise((resolve, reject) => {
showDialog(options, template).then(resolve, reject);
});
};
});
}
/* eslint-enable indent */
export default {
show: show
};

View file

@ -4,12 +4,8 @@
<div class="formDialogContent smoothScrollY">
<div class="dialogContentInner dialog-content-centered" style="padding-top:1em;padding-bottom: 1em; text-align: center;">
<div class="text">
</div>
<div class="text"></div>
</div>
</div>
<div class="formDialogFooter formDialogFooter-clear formDialogFooter-flex" style="padding-bottom: 1.5em;">
</div>
<div class="formDialogFooter formDialogFooter-clear formDialogFooter-flex" style="margin:1em"></div>

View file

@ -1,7 +1,15 @@
define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', 'dom', 'css!./dialoghelper.css', 'scrollStyles'], function (appRouter, focusManager, browser, layoutManager, inputManager, dom) {
'use strict';
import appRouter from 'appRouter';
import focusManager from 'focusManager';
import browser from 'browser';
import layoutManager from 'layoutManager';
import inputManager from 'inputManager';
import dom from 'dom';
import 'css!./dialoghelper.css';
import 'scrollStyles';
var globalOnOpenCallback;
/* eslint-disable indent */
let globalOnOpenCallback;
function enableAnimation() {
@ -25,7 +33,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
}
function tryRemoveElement(elem) {
var parentNode = elem.parentNode;
const parentNode = elem.parentNode;
if (parentNode) {
// Seeing crashes in edge webview
@ -39,14 +47,14 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
function DialogHashHandler(dlg, hash, resolve) {
var self = this;
const self = this;
self.originalUrl = window.location.href;
var activeElement = document.activeElement;
var removeScrollLockOnClose = false;
const activeElement = document.activeElement;
let removeScrollLockOnClose = false;
function onHashChange(e) {
var isBack = self.originalUrl === window.location.href;
const isBack = self.originalUrl === window.location.href;
if (isBack || !isOpened(dlg)) {
window.removeEventListener('popstate', onHashChange);
@ -84,7 +92,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
}
if (!self.closedByBack && isHistoryEnabled(dlg)) {
var state = history.state || {};
const state = history.state || {};
if (state.dialogId === hash) {
history.back();
}
@ -97,7 +105,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
if (dlg.getAttribute('data-removeonclose') !== 'false') {
removeCenterFocus(dlg);
var dialogContainer = dlg.dialogContainer;
const dialogContainer = dlg.dialogContainer;
if (dialogContainer) {
tryRemoveElement(dialogContainer);
dlg.dialogContainer = null;
@ -108,7 +116,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
//resolve();
// if we just called history.back(), then use a timeout to allow the history events to fire first
setTimeout(function () {
setTimeout(() => {
resolve({
element: dlg,
closedByBack: self.closedByBack
@ -118,7 +126,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
dlg.addEventListener('close', onDialogClosed);
var center = !dlg.classList.contains('dialog-fixedSize');
const center = !dlg.classList.contains('dialog-fixedSize');
if (center) {
dlg.classList.add('centeredDialog');
}
@ -141,7 +149,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
animateDialogOpen(dlg);
if (isHistoryEnabled(dlg)) {
appRouter.pushState({ dialogId: hash }, 'Dialog', '#' + hash);
appRouter.pushState({ dialogId: hash }, 'Dialog', `#${hash}`);
window.addEventListener('popstate', onHashChange);
} else {
@ -151,10 +159,10 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
function addBackdropOverlay(dlg) {
var backdrop = document.createElement('div');
const backdrop = document.createElement('div');
backdrop.classList.add('dialogBackdrop');
var backdropParent = dlg.dialogContainer || dlg;
const backdropParent = dlg.dialogContainer || dlg;
backdropParent.parentNode.insertBefore(backdrop, backdropParent);
dlg.backdrop = backdrop;
@ -162,7 +170,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
void backdrop.offsetWidth;
backdrop.classList.add('dialogBackdropOpened');
dom.addEventListener((dlg.dialogContainer || backdrop), 'click', function (e) {
dom.addEventListener((dlg.dialogContainer || backdrop), 'click', e => {
if (e.target === dlg.dialogContainer) {
close(dlg);
}
@ -170,7 +178,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
passive: true
});
dom.addEventListener((dlg.dialogContainer || backdrop), 'contextmenu', function (e) {
dom.addEventListener((dlg.dialogContainer || backdrop), 'contextmenu', e => {
if (e.target === dlg.dialogContainer) {
// Close the application dialog menu
close(dlg);
@ -184,26 +192,26 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
return dlg.getAttribute('data-history') === 'true';
}
function open(dlg) {
export function open(dlg) {
if (globalOnOpenCallback) {
globalOnOpenCallback(dlg);
}
var parent = dlg.parentNode;
const parent = dlg.parentNode;
if (parent) {
parent.removeChild(dlg);
}
var dialogContainer = document.createElement('div');
const dialogContainer = document.createElement('div');
dialogContainer.classList.add('dialogContainer');
dialogContainer.appendChild(dlg);
dlg.dialogContainer = dialogContainer;
document.body.appendChild(dialogContainer);
return new Promise(function (resolve, reject) {
return new Promise((resolve, reject) => {
new DialogHashHandler(dlg, 'dlg' + new Date().getTime(), resolve);
new DialogHashHandler(dlg, `dlg${new Date().getTime()}`, resolve);
});
}
@ -213,7 +221,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
return !dlg.classList.contains('hide');
}
function close(dlg) {
export function close(dlg) {
if (isOpened(dlg)) {
if (isHistoryEnabled(dlg)) {
@ -233,7 +241,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
cancelable: false
}));
var onAnimationFinish = function () {
const onAnimationFinish = () => {
focusManager.popScope(dlg);
dlg.classList.add('hide');
@ -249,7 +257,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
function animateDialogOpen(dlg) {
var onAnimationFinish = function () {
const onAnimationFinish = () => {
focusManager.pushScope(dlg);
if (dlg.getAttribute('data-autofocus') === 'true') {
@ -264,7 +272,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
if (enableAnimation()) {
var onFinish = function () {
const onFinish = () => {
dom.removeEventListener(dlg, dom.whichAnimationEvent(), onFinish, {
once: true
});
@ -283,24 +291,24 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
if (enableAnimation()) {
var animated = true;
let animated = true;
switch (dlg.animationConfig.exit.name) {
case 'fadeout':
dlg.style.animation = 'fadeout ' + dlg.animationConfig.exit.timing.duration + 'ms ease-out normal both';
dlg.style.animation = `fadeout ${dlg.animationConfig.exit.timing.duration}ms ease-out normal both`;
break;
case 'scaledown':
dlg.style.animation = 'scaledown ' + dlg.animationConfig.exit.timing.duration + 'ms ease-out normal both';
dlg.style.animation = `scaledown ${dlg.animationConfig.exit.timing.duration}ms ease-out normal both`;
break;
case 'slidedown':
dlg.style.animation = 'slidedown ' + dlg.animationConfig.exit.timing.duration + 'ms ease-out normal both';
dlg.style.animation = `slidedown ${dlg.animationConfig.exit.timing.duration}ms ease-out normal both`;
break;
default:
animated = false;
break;
}
var onFinish = function () {
const onFinish = () => {
dom.removeEventListener(dlg, dom.whichAnimationEvent(), onFinish, {
once: true
});
@ -318,7 +326,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
onAnimationFinish();
}
var supportsOverscrollBehavior = 'overscroll-behavior-y' in document.body.style;
const supportsOverscrollBehavior = 'overscroll-behavior-y' in document.body.style;
function shouldLockDocumentScroll(options) {
@ -343,7 +351,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
function removeBackdrop(dlg) {
var backdrop = dlg.backdrop;
const backdrop = dlg.backdrop;
if (!backdrop) {
return;
@ -351,7 +359,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
dlg.backdrop = null;
var onAnimationFinish = function () {
const onAnimationFinish = () => {
tryRemoveElement(backdrop);
};
@ -368,20 +376,20 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
}
function centerFocus(elem, horiz, on) {
require(['scrollHelper'], function (scrollHelper) {
var fn = on ? 'on' : 'off';
import('scrollHelper').then(scrollHelper => {
const fn = on ? 'on' : 'off';
scrollHelper.centerFocus[fn](elem, horiz);
});
}
function createDialog(options) {
export function createDialog(options) {
options = options || {};
// If there's no native dialog support, use a plain div
// Also not working well in samsung tizen browser, content inside not clickable
// Just go ahead and always use a plain div because we're seeing issues overlaying absoltutely positioned content over a modal dialog
var dlg = document.createElement('div');
const dlg = document.createElement('div');
dlg.classList.add('focuscontainer');
dlg.classList.add('hide');
@ -406,17 +414,17 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
dlg.setAttribute('data-autofocus', 'true');
}
var defaultEntryAnimation;
var defaultExitAnimation;
let defaultEntryAnimation;
let defaultExitAnimation;
defaultEntryAnimation = 'scaleup';
defaultExitAnimation = 'scaledown';
var entryAnimation = options.entryAnimation || defaultEntryAnimation;
var exitAnimation = options.exitAnimation || defaultExitAnimation;
const entryAnimation = options.entryAnimation || defaultEntryAnimation;
const exitAnimation = options.exitAnimation || defaultExitAnimation;
// If it's not fullscreen then lower the default animation speed to make it open really fast
var entryAnimationDuration = options.entryAnimationDuration || (options.size !== 'fullscreen' ? 180 : 280);
var exitAnimationDuration = options.exitAnimationDuration || (options.size !== 'fullscreen' ? 120 : 220);
const entryAnimationDuration = options.entryAnimationDuration || (options.size !== 'fullscreen' ? 180 : 280);
const exitAnimationDuration = options.exitAnimationDuration || (options.size !== 'fullscreen' ? 120 : 220);
dlg.animationConfig = {
// scale up
@ -461,7 +469,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
if (options.size) {
dlg.classList.add('dialog-fixedSize');
dlg.classList.add('dialog-' + options.size);
dlg.classList.add(`dialog-${options.size}`);
}
if (enableAnimation()) {
@ -469,16 +477,16 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
switch (dlg.animationConfig.entry.name) {
case 'fadein':
dlg.style.animation = 'fadein ' + entryAnimationDuration + 'ms ease-out normal';
dlg.style.animation = `fadein ${entryAnimationDuration}ms ease-out normal`;
break;
case 'scaleup':
dlg.style.animation = 'scaleup ' + entryAnimationDuration + 'ms ease-out normal both';
dlg.style.animation = `scaleup ${entryAnimationDuration}ms ease-out normal both`;
break;
case 'slideup':
dlg.style.animation = 'slideup ' + entryAnimationDuration + 'ms ease-out normal';
dlg.style.animation = `slideup ${entryAnimationDuration}ms ease-out normal`;
break;
case 'slidedown':
dlg.style.animation = 'slidedown ' + entryAnimationDuration + 'ms ease-out normal';
dlg.style.animation = `slidedown ${entryAnimationDuration}ms ease-out normal`;
break;
default:
break;
@ -488,12 +496,15 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
return dlg;
}
return {
open: open,
close: close,
createDialog: createDialog,
setOnOpen: function (val) {
globalOnOpenCallback = val;
}
};
});
export function setOnOpen(val) {
globalOnOpenCallback = val;
}
/* eslint-enable indent */
export default {
open: open,
close: close,
createDialog: createDialog,
setOnOpen: setOnOpen
};

View file

@ -55,7 +55,7 @@
/* Without this emby-checkbox is able to appear on top */
z-index: 1;
align-items: flex-end;
justify-content: flex-end;
justify-content: center;
flex-wrap: wrap;
}

View file

@ -168,7 +168,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function getPortraitShape() {
return enableScrollX() ? 'autooverflow' : 'auto';
return enableScrollX() ? 'overflowPortrait' : 'portrait';
}
function getLibraryButtonsHtml(items) {
@ -254,7 +254,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
return cardBuilder.getCardsHtml({
items: items,
shape: shape,
preferThumb: viewType !== 'movies' && itemType !== 'Channel' && viewType !== 'music' ? 'auto' : null,
preferThumb: viewType !== 'movies' && viewType !== 'tvshows' && itemType !== 'Channel' && viewType !== 'music' ? 'auto' : null,
showUnplayedIndicator: false,
showChildCountIndicator: true,
context: 'home',

View file

@ -58,6 +58,7 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
var html = ['<img style="max-width:100%;max-height:100%;" src="', e.target.result, '" title="', escape(theFile.name), '"/>'].join('');
page.querySelector('#imageOutput').innerHTML = html;
page.querySelector('#dropImageText').classList.add('hide');
page.querySelector('#fldUpload').classList.remove('hide');
};
})(file);

View file

@ -20,7 +20,7 @@
</div>
<div>
<div class="imageEditor-dropZone fieldDescription">
<div>${LabelDropImageHere}</div>
<div id="dropImageText">${LabelDropImageHere}</div>
<output id="imageOutput" class="flex align-items-center justify-content-center" style="position: absolute;top:0;left:0;right:0;bottom:0;width:100%;"></output>
<input type="file" accept="image/*" id="uploadImage" name="uploadImage" style="position: absolute;top:0;left:0;right:0;bottom:0;width:100%;opacity:0;" />
</div>

View file

@ -1,11 +1,11 @@
.lazy-image-fadein {
opacity: 1;
transition: opacity 0.7s;
transition: opacity 0.5s;
}
.lazy-image-fadein-fast {
opacity: 1;
transition: opacity 0.2s;
transition: opacity 0.1s;
}
.lazy-hidden {

View file

@ -403,7 +403,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
break;
case 'moremediainfo':
require(['itemMediaInfo'], function (itemMediaInfo) {
itemMediaInfo.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
itemMediaInfo.show(itemId, serverId).then(getResolveFunction(resolve, id), getResolveFunction(resolve, id));
});
break;
case 'refresh':

View file

@ -11,9 +11,9 @@
(entries) => {
entries.forEach(entry => {
callback(entry);
},
{rootMargin: '50%'});
});
});
},
{rootMargin: '25%'});
this.observer = observer;
}

View file

@ -1,5 +1,20 @@
define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutManager', 'globalize', 'datetime', 'apphost', 'css!./listview', 'emby-ratingbutton', 'emby-playstatebutton'], function (itemHelper, mediaInfo, indicators, connectionManager, layoutManager, globalize, datetime, appHost) {
'use strict';
/* eslint-disable indent */
/**
* Module for display list view.
* @module components/listview/listview
*/
import itemHelper from 'itemHelper';
import mediaInfo from 'mediaInfo';
import indicators from 'indicators';
import connectionManager from 'connectionManager';
import layoutManager from 'layoutManager';
import globalize from 'globalize';
import datetime from 'datetime';
import 'css!./listview';
import 'emby-ratingbutton';
import 'emby-playstatebutton';
function getIndex(item, options) {
@ -8,9 +23,9 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
return item.ParentIndexNumber == null ? '' : globalize.translate('ValueDiscNumber', item.ParentIndexNumber);
}
var sortBy = (options.sortBy || '').toLowerCase();
var code;
var name;
const sortBy = (options.sortBy || '').toLowerCase();
let code;
let name;
if (sortBy.indexOf('sortname') === 0) {
@ -69,10 +84,10 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
function getImageUrl(item, width) {
var apiClient = connectionManager.getApiClient(item.ServerId);
const apiClient = connectionManager.getApiClient(item.ServerId);
let itemId;
var options = {
const options = {
maxWidth: width * 2,
type: 'Primary'
};
@ -102,8 +117,8 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
function getChannelImageUrl(item, width) {
var apiClient = connectionManager.getApiClient(item.ServerId);
var options = {
const apiClient = connectionManager.getApiClient(item.ServerId);
const options = {
maxWidth: width * 2,
type: 'Primary'
};
@ -121,13 +136,13 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
function getTextLinesHtml(textlines, isLargeStyle) {
var html = '';
let html = '';
var largeTitleTagName = layoutManager.tv ? 'h2' : 'div';
const largeTitleTagName = layoutManager.tv ? 'h2' : 'div';
for (var i = 0, length = textlines.length; i < length; i++) {
for (let i = 0, length = textlines.length; i < length; i++) {
var text = textlines[i];
const text = textlines[i];
if (!text) {
continue;
@ -135,7 +150,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
if (i === 0) {
if (isLargeStyle) {
html += '<' + largeTitleTagName + ' class="listItemBodyText">';
html += `<${largeTitleTagName} class="listItemBodyText">`;
} else {
html += '<div class="listItemBodyText">';
}
@ -144,7 +159,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
}
html += (textlines[i] || '&nbsp;');
if (i === 0 && isLargeStyle) {
html += '</' + largeTitleTagName + '>';
html += `</${largeTitleTagName}>`;
} else {
html += '</div>';
}
@ -155,13 +170,13 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
function getRightButtonsHtml(options) {
var html = '';
let html = '';
for (var i = 0, length = options.rightButtons.length; i < length; i++) {
for (let i = 0, length = options.rightButtons.length; i < length; i++) {
var button = options.rightButtons[i];
const button = options.rightButtons[i];
html += '<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="custom" data-customaction="' + button.id + '" title="' + button.title + '"><span class="material-icons ' + button.icon + '"></span></button>';
html += `<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="custom" data-customaction="${button.id}" title="${button.title}"><span class="material-icons ${button.icon}"></span></button>`;
}
return html;
@ -171,34 +186,34 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
return item.Id;
}
function getListViewHtml(options) {
export function getListViewHtml(options) {
var items = options.items;
const items = options.items;
var groupTitle = '';
var action = options.action || 'link';
let groupTitle = '';
const action = options.action || 'link';
var isLargeStyle = options.imageSize === 'large';
var enableOverview = options.enableOverview;
const isLargeStyle = options.imageSize === 'large';
const enableOverview = options.enableOverview;
var clickEntireItem = layoutManager.tv ? true : false;
var outerTagName = clickEntireItem ? 'button' : 'div';
var enableSideMediaInfo = options.enableSideMediaInfo != null ? options.enableSideMediaInfo : true;
const clickEntireItem = layoutManager.tv ? true : false;
const outerTagName = clickEntireItem ? 'button' : 'div';
const enableSideMediaInfo = options.enableSideMediaInfo != null ? options.enableSideMediaInfo : true;
var outerHtml = '';
let outerHtml = '';
var enableContentWrapper = options.enableOverview && !layoutManager.tv;
var containerAlbumArtistIds = (options.containerAlbumArtists || []).map(getId);
const enableContentWrapper = options.enableOverview && !layoutManager.tv;
const containerAlbumArtistIds = (options.containerAlbumArtists || []).map(getId);
for (var i = 0, length = items.length; i < length; i++) {
for (let i = 0, length = items.length; i < length; i++) {
var item = items[i];
const item = items[i];
var html = '';
let html = '';
if (options.showIndex) {
var itemGroupTitle = getIndex(item, options);
const itemGroupTitle = getIndex(item, options);
if (itemGroupTitle !== groupTitle) {
@ -220,7 +235,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
}
}
var cssClass = 'listItem';
let cssClass = 'listItem';
if (options.border || (options.highlight !== false && !layoutManager.tv)) {
cssClass += ' listItem-border';
@ -234,28 +249,28 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
cssClass += ' listItem-focusscale';
}
var downloadWidth = 80;
let downloadWidth = 80;
if (isLargeStyle) {
cssClass += ' listItem-largeImage';
downloadWidth = 500;
}
var playlistItemId = item.PlaylistItemId ? (' data-playlistitemid="' + item.PlaylistItemId + '"') : '';
const playlistItemId = item.PlaylistItemId ? (` data-playlistitemid="${item.PlaylistItemId}"`) : '';
var positionTicksData = item.UserData && item.UserData.PlaybackPositionTicks ? (' data-positionticks="' + item.UserData.PlaybackPositionTicks + '"') : '';
var collectionIdData = options.collectionId ? (' data-collectionid="' + options.collectionId + '"') : '';
var playlistIdData = options.playlistId ? (' data-playlistid="' + options.playlistId + '"') : '';
var mediaTypeData = item.MediaType ? (' data-mediatype="' + item.MediaType + '"') : '';
var collectionTypeData = item.CollectionType ? (' data-collectiontype="' + item.CollectionType + '"') : '';
var channelIdData = item.ChannelId ? (' data-channelid="' + item.ChannelId + '"') : '';
const positionTicksData = item.UserData && item.UserData.PlaybackPositionTicks ? (` data-positionticks="${item.UserData.PlaybackPositionTicks}"`) : '';
const collectionIdData = options.collectionId ? (` data-collectionid="${options.collectionId}"`) : '';
const playlistIdData = options.playlistId ? (` data-playlistid="${options.playlistId}"`) : '';
const mediaTypeData = item.MediaType ? (` data-mediatype="${item.MediaType}"`) : '';
const collectionTypeData = item.CollectionType ? (` data-collectiontype="${item.CollectionType}"`) : '';
const channelIdData = item.ChannelId ? (` data-channelid="${item.ChannelId}"`) : '';
if (enableContentWrapper) {
cssClass += ' listItem-withContentWrapper';
}
html += '<' + outerTagName + ' class="' + cssClass + '"' + playlistItemId + ' data-action="' + action + '" data-isfolder="' + item.IsFolder + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-type="' + item.Type + '"' + mediaTypeData + collectionTypeData + channelIdData + positionTicksData + collectionIdData + playlistIdData + '>';
html += `<${outerTagName} class="${cssClass}"${playlistItemId} data-action="${action}" data-isfolder="${item.IsFolder}" data-id="${item.Id}" data-serverid="${item.ServerId}" data-type="${item.Type}"${mediaTypeData}${collectionTypeData}${channelIdData}${positionTicksData}${collectionIdData}${playlistIdData}>`;
if (enableContentWrapper) {
@ -278,37 +293,37 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
imageClass += ' listItemImage-large-tv';
}
var playOnImageClick = options.imagePlayButton && !layoutManager.tv;
const playOnImageClick = options.imagePlayButton && !layoutManager.tv;
if (!clickEntireItem) {
imageClass += ' itemAction';
}
var imageAction = playOnImageClick ? 'resume' : action;
const imageAction = playOnImageClick ? 'resume' : action;
let blurhashAttrib = '';
if (blurhash && blurhash.length > 0) {
blurhashAttrib = 'data-blurhash="' + blurhash + '"';
blurhashAttrib = `data-blurhash="${blurhash}"`;
}
if (imgUrl) {
html += '<div data-action="' + imageAction + '" class="' + imageClass + ' lazy" data-src="' + imgUrl + '" ' + blurhashAttrib + ' item-icon>';
html += `<div data-action="${imageAction}" class="${imageClass} lazy" data-src="${imgUrl}" ${blurhashAttrib} item-icon>`;
} else {
html += '<div class="' + imageClass + '">';
html += `<div class="${imageClass}">`;
}
var indicatorsHtml = '';
let indicatorsHtml = '';
indicatorsHtml += indicators.getPlayedIndicatorHtml(item);
if (indicatorsHtml) {
html += '<div class="indicators listItemIndicators">' + indicatorsHtml + '</div>';
html += `<div class="indicators listItemIndicators">${indicatorsHtml}</div>`;
}
if (playOnImageClick) {
html += '<button is="paper-icon-button-light" class="listItemImageButton itemAction" data-action="resume"><span class="material-icons listItemImageButton-icon play_arrow"></span></button>';
}
var progressHtml = indicators.getProgressBarHtml(item, {
const progressHtml = indicators.getProgressBarHtml(item, {
containerClass: 'listItemProgressBar'
});
@ -325,7 +340,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
html += '</div>';
}
var textlines = [];
const textlines = [];
if (options.showProgramDateTime) {
textlines.push(datetime.toLocaleString(datetime.parseISO8601Date(item.StartDate), {
@ -348,7 +363,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
}
}
var parentTitle = null;
let parentTitle = null;
if (options.showParentTitle) {
if (item.Type === 'Episode') {
@ -358,12 +373,12 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
}
}
var displayName = itemHelper.getDisplayName(item, {
let displayName = itemHelper.getDisplayName(item, {
includeParentInfo: options.includeParentInfoInTitle
});
if (options.showIndexNumber && item.IndexNumber != null) {
displayName = item.IndexNumber + '. ' + displayName;
displayName = `${item.IndexNumber}. ${displayName}`;
}
if (options.showParentTitle && options.parentTitleWithTitle) {
@ -394,14 +409,14 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
}
} else {
var showArtist = options.artist === true;
var artistItems = item.ArtistItems;
let showArtist = options.artist === true;
const artistItems = item.ArtistItems;
if (!showArtist && options.artist !== false) {
if (!artistItems || !artistItems.length) {
showArtist = true;
} else if (artistItems.length > 1 || containerAlbumArtistIds.indexOf(artistItems[0].Id) === -1) {
} else if (artistItems.length > 1 || !containerAlbumArtistIds.includes(artistItems[0].Id)) {
showArtist = true;
}
}
@ -409,7 +424,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
if (showArtist) {
if (artistItems && item.Type !== 'MusicAlbum') {
textlines.push(artistItems.map(function (a) {
textlines.push(artistItems.map(a => {
return a.Name;
}).join(', '));
}
@ -432,7 +447,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
cssClass += ' listItemBody-noleftpadding';
}
html += '<div class="' + cssClass + '">';
html += `<div class="${cssClass}">`;
const moreIcon = 'more_vert';
@ -441,14 +456,16 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
if (options.mediaInfo !== false) {
if (!enableSideMediaInfo) {
var mediaInfoClass = 'secondary listItemMediaInfo listItemBodyText';
const mediaInfoClass = 'secondary listItemMediaInfo listItemBodyText';
html += '<div class="' + mediaInfoClass + '">' + mediaInfo.getPrimaryMediaInfoHtml(item, {
html += `<div class="${mediaInfoClass}">`;
html += mediaInfo.getPrimaryMediaInfoHtml(item, {
episodeTitle: false,
originalAirDate: false,
subtitles: false
}) + '</div>';
});
html += '</div>';
}
}
@ -462,7 +479,8 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
if (options.mediaInfo !== false) {
if (enableSideMediaInfo) {
html += '<div class="secondary listItemMediaInfo">' + mediaInfo.getPrimaryMediaInfoHtml(item, {
html += '<div class="secondary listItemMediaInfo">';
html += mediaInfo.getPrimaryMediaInfoHtml(item, {
year: false,
container: false,
@ -470,7 +488,8 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
criticRating: false,
endsAt: false
}) + '</div>';
});
html += '</div>';
}
}
@ -487,7 +506,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
}
if (options.moreButton !== false) {
html += '<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="menu"><span class="material-icons ' + moreIcon + '"></span></button>';
html += `<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="menu"><span class="material-icons ${moreIcon}"></span></button>`;
}
if (options.infoButton) {
@ -500,15 +519,15 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
if (options.enableUserDataButtons !== false) {
var userData = item.UserData || {};
var likes = userData.Likes == null ? '' : userData.Likes;
const userData = item.UserData || {};
const likes = userData.Likes == null ? '' : userData.Likes;
if (itemHelper.canMarkPlayed(item)) {
html += '<button is="emby-playstatebutton" type="button" class="listItemButton paper-icon-button-light" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-played="' + (userData.Played) + '"><span class="material-icons check"></span></button>';
html += `<button is="emby-playstatebutton" type="button" class="listItemButton paper-icon-button-light" data-id="${item.Id}" data-serverid="${item.ServerId}" data-itemtype="${item.Type}" data-played="${userData.Played}"><span class="material-icons check"></span></button>`;
}
if (itemHelper.canRate(item)) {
html += '<button is="emby-ratingbutton" type="button" class="listItemButton paper-icon-button-light" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-likes="' + likes + '" data-isfavorite="' + (userData.IsFavorite) + '"><span class="material-icons favorite"></span></button>';
html += `<button is="emby-ratingbutton" type="button" class="listItemButton paper-icon-button-light" data-id="${item.Id}" data-serverid="${item.ServerId}" data-itemtype="${item.Type}" data-likes="${likes}" data-isfavorite="${userData.IsFavorite}"><span class="material-icons favorite"></span></button>`;
}
}
}
@ -524,7 +543,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
}
}
html += '</' + outerTagName + '>';
html += `</${outerTagName}>`;
outerHtml += html;
}
@ -532,7 +551,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
return outerHtml;
}
return {
getListViewHtml: getListViewHtml
};
});
/* eslint-enable indent */
export default {
getListViewHtml: getListViewHtml
};

View file

@ -1,92 +0,0 @@
define(['loading', 'events', 'dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 'require', 'material-icons', 'emby-button', 'paper-icon-button-light', 'emby-input', 'formDialogStyle', 'flexStyles'], function (loading, events, dialogHelper, dom, layoutManager, scrollHelper, globalize, require) {
'use strict';
function showDialog(instance, options, template) {
var dialogOptions = {
removeOnClose: true,
scrollY: false
};
var enableTvLayout = layoutManager.tv;
if (enableTvLayout) {
dialogOptions.size = 'fullscreen';
}
var dlg = dialogHelper.createDialog(dialogOptions);
var configuredButtons = [];
dlg.classList.add('formDialog');
dlg.innerHTML = globalize.translateHtml(template, 'core');
dlg.classList.add('align-items-center');
dlg.classList.add('justify-items-center');
var formDialogContent = dlg.querySelector('.formDialogContent');
formDialogContent.style['flex-grow'] = 'initial';
formDialogContent.style['max-width'] = '50%';
formDialogContent.style['max-height'] = '60%';
if (enableTvLayout) {
scrollHelper.centerFocus.on(formDialogContent, false);
dlg.querySelector('.formDialogHeader').style.marginTop = '15%';
} else {
dlg.classList.add('dialog-fullscreen-lowres');
}
//dlg.querySelector('.btnCancel').addEventListener('click', function (e) {
// dialogHelper.close(dlg);
//});
dlg.querySelector('.formDialogHeaderTitle').innerHTML = options.title;
dlg.querySelector('.text').innerHTML = options.text;
instance.dlg = dlg;
return dialogHelper.open(dlg).then(function () {
if (enableTvLayout) {
scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false);
}
loading.hide();
});
}
function LoadingDialog(options) {
this.options = options;
}
LoadingDialog.prototype.show = function () {
var instance = this;
loading.show();
return new Promise(function (resolve, reject) {
require(['text!./../dialog/dialog.template.html'], function (template) {
showDialog(instance, instance.options, template);
resolve();
});
});
};
LoadingDialog.prototype.setTitle = function (title) {
};
LoadingDialog.prototype.setText = function (text) {
};
LoadingDialog.prototype.hide = function () {
if (this.dlg) {
dialogHelper.close(this.dlg);
this.dlg = null;
}
};
LoadingDialog.prototype.destroy = function () {
this.dlg = null;
this.options = null;
};
return LoadingDialog;
});

View file

@ -308,8 +308,8 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
}
});
context.removeEventListener('submit', onEditorClick);
context.addEventListener('submit', onEditorClick);
context.removeEventListener('click', onEditorClick);
context.addEventListener('click', onEditorClick);
var form = context.querySelector('form');
form.removeEventListener('submit', onSubmit);

View file

@ -7,7 +7,6 @@
<div class="formDialogContent smoothScrollY" style="padding-top:2em;">
<form class="popupEditPersonForm dialogContentInner dialog-content-centered">
<div class="inputContainer">
<input type="text" is="emby-input" class="txtPersonName" required="required" label="${LabelName}" />
</div>
@ -23,6 +22,7 @@
<option value="Writer">${Writer}</option>
</select>
</div>
<div class="inputContainer fldRole hide">
<input is="emby-input" type="text" class="txtPersonRole" label="${LabelPersonRole}" />
<div class="fieldDescription">${LabelPersonRoleHelp}</div>
@ -33,6 +33,5 @@
<span>${Save}</span>
</button>
</div>
</form>
</div>

View file

@ -241,6 +241,15 @@ import connectionManager from 'connectionManager';
navigator.mediaSession.setActionHandler('seekforward', function () {
execute('fastForward');
});
/* eslint-disable-next-line compat/compat */
navigator.mediaSession.setActionHandler('seekto', function (object) {
let item = playbackManager.getPlayerState(currentPlayer).NowPlayingItem;
// Convert to ms
let duration = parseInt(item.RunTimeTicks ? (item.RunTimeTicks / 10000) : 0);
let wantedTime = object.seekTime * 1000;
playbackManager.seekPercent(wantedTime / duration * 100, currentPlayer);
});
}
events.on(playbackManager, 'playerchange', function () {

View file

@ -2,12 +2,12 @@
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1">
<span class="material-icons arrow_back"></span>
</button>
<h3 class="formDialogHeaderTitle"></h3>
</div>
<div class="formDialogContent smoothScrollY">
<div class="dialogContentInner dialog-content-centered" style="padding-top:2em;">
<form>
<div class="inputContainer">
<input is="emby-input" type="text" id="txtInput" label="" />
@ -19,7 +19,6 @@
<span class="submitText"></span>
</button>
</div>
</form>
</div>
</div>

View file

@ -196,7 +196,7 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
context.querySelector('.nowPlayingPageImage').classList.remove('nowPlayingPageImageAudio');
}
} else {
imgContainer.innerHTML = '<div class="nowPlayingPageImageContainerNoAlbum"><button data-action="link" class="cardContent-button cardImageContainer coveredImage ' + cardBuilder.getDefaultBackgroundClass(item.Name) + ' cardContent cardContent-shadow itemAction"><span class="cardImageIcon material-icons album"></span></button></div>';
imgContainer.innerHTML = '<div class="nowPlayingPageImageContainerNoAlbum"><button data-action="link" class="cardImageContainer coveredImage ' + cardBuilder.getDefaultBackgroundClass(item.Name) + ' cardContent cardContent-shadow itemAction"><span class="cardImageIcon material-icons album"></span></button></div>';
}
}

View file

@ -1,158 +0,0 @@
define(['loading', 'events', 'dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 'require', 'material-icons', 'emby-button', 'paper-icon-button-light', 'emby-input', 'formDialogStyle', 'flexStyles'], function (loading, events, dialogHelper, dom, layoutManager, scrollHelper, globalize, require) {
'use strict';
var currentApiClient;
var currentDlg;
var currentInstance;
function reloadPageWhenServerAvailable(retryCount) {
var apiClient = currentApiClient;
if (!apiClient) {
return;
}
// Don't use apiclient method because we don't want it reporting authentication under the old version
apiClient.getJSON(apiClient.getUrl('System/Info')).then(function (info) {
// If this is back to false, the restart completed
if (!info.IsShuttingDown) {
currentInstance.restarted = true;
dialogHelper.close(currentDlg);
} else {
retryReload(retryCount);
}
}, function () {
retryReload(retryCount);
});
}
function retryReload(retryCount) {
setTimeout(function () {
retryCount = retryCount || 0;
retryCount++;
if (retryCount < 150) {
reloadPageWhenServerAvailable(retryCount);
}
}, 500);
}
function startRestart(instance, apiClient, dlg) {
currentApiClient = apiClient;
currentDlg = dlg;
currentInstance = instance;
apiClient.restartServer().then(function () {
setTimeout(reloadPageWhenServerAvailable, 250);
});
}
function showDialog(instance, options, template) {
var dialogOptions = {
removeOnClose: true,
scrollY: false
};
var enableTvLayout = layoutManager.tv;
if (enableTvLayout) {
dialogOptions.size = 'fullscreen';
}
var dlg = dialogHelper.createDialog(dialogOptions);
var configuredButtons = [];
dlg.classList.add('formDialog');
dlg.innerHTML = globalize.translateHtml(template, 'core');
dlg.classList.add('align-items-center');
dlg.classList.add('justify-items-center');
var formDialogContent = dlg.querySelector('.formDialogContent');
formDialogContent.style['flex-grow'] = 'initial';
if (enableTvLayout) {
formDialogContent.style['max-width'] = '50%';
formDialogContent.style['max-height'] = '60%';
scrollHelper.centerFocus.on(formDialogContent, false);
} else {
formDialogContent.style.maxWidth = (Math.min((configuredButtons.length * 150) + 200, dom.getWindowSize().innerWidth - 50)) + 'px';
dlg.classList.add('dialog-fullscreen-lowres');
}
dlg.querySelector('.formDialogHeaderTitle').innerHTML = globalize.translate('HeaderRestartingServer');
dlg.querySelector('.text').innerHTML = globalize.translate('RestartPleaseWaitMessage');
var i;
var length;
var html = '';
for (i = 0, length = configuredButtons.length; i < length; i++) {
var item = configuredButtons[i];
var autoFocus = i === 0 ? ' autofocus' : '';
var buttonClass = 'btnOption raised formDialogFooterItem formDialogFooterItem-autosize';
if (item.type) {
buttonClass += ' button-' + item.type;
}
html += '<button is="emby-button" type="button" class="' + buttonClass + '" data-id="' + item.id + '"' + autoFocus + '>' + item.name + '</button>';
}
dlg.querySelector('.formDialogFooter').innerHTML = html;
function onButtonClick() {
dialogHelper.close(dlg);
}
var buttons = dlg.querySelectorAll('.btnOption');
for (i = 0, length = buttons.length; i < length; i++) {
buttons[i].addEventListener('click', onButtonClick);
}
var dlgPromise = dialogHelper.open(dlg);
startRestart(instance, options.apiClient, dlg);
return dlgPromise.then(function () {
if (enableTvLayout) {
scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false);
}
instance.destroy();
loading.hide();
if (instance.restarted) {
events.trigger(instance, 'restarted');
}
});
}
function ServerRestartDialog(options) {
this.options = options;
}
ServerRestartDialog.prototype.show = function () {
var instance = this;
loading.show();
return new Promise(function (resolve, reject) {
require(['text!./../dialog/dialog.template.html'], function (template) {
showDialog(instance, instance.options, template).then(resolve, reject);
});
});
};
ServerRestartDialog.prototype.destroy = function () {
currentApiClient = null;
currentDlg = null;
currentInstance = null;
this.options = null;
};
return ServerRestartDialog;
});

View file

@ -1,18 +1,30 @@
define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'globalize', 'loading', 'dom', 'recordingHelper'], function (playbackManager, inputManager, connectionManager, appRouter, globalize, loading, dom, recordingHelper) {
'use strict';
/* eslint-disable indent */
/**
* Module shortcuts.
* @module components/shortcuts
*/
import playbackManager from 'playbackManager';
import inputManager from 'inputManager';
import connectionManager from 'connectionManager';
import appRouter from 'appRouter';
import globalize from 'globalize';
import dom from 'dom';
import recordingHelper from 'recordingHelper';
function playAllFromHere(card, serverId, queue) {
var parent = card.parentNode;
var className = card.classList.length ? ('.' + card.classList[0]) : '';
var cards = parent.querySelectorAll(className + '[data-id]');
const parent = card.parentNode;
const className = card.classList.length ? (`.${card.classList[0]}`) : '';
const cards = parent.querySelectorAll(`${className}[data-id]`);
var ids = [];
const ids = [];
var foundCard = false;
var startIndex;
let foundCard = false;
let startIndex;
for (var i = 0, length = cards.length; i < length; i++) {
for (let i = 0, length = cards.length; i < length; i++) {
if (cards[i] === card) {
foundCard = true;
startIndex = i;
@ -22,12 +34,12 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
}
}
var itemsContainer = dom.parentWithClass(card, 'itemsContainer');
const itemsContainer = dom.parentWithClass(card, 'itemsContainer');
if (itemsContainer && itemsContainer.fetchData) {
var queryOptions = queue ? { StartIndex: startIndex } : {};
const queryOptions = queue ? { StartIndex: startIndex } : {};
return itemsContainer.fetchData(queryOptions).then(function (result) {
return itemsContainer.fetchData(queryOptions).then(result => {
if (queue) {
return playbackManager.queue({
@ -64,7 +76,7 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
function showProgramDialog(item) {
require(['recordingCreator'], function (recordingCreator) {
import('recordingCreator').then(({default:recordingCreator}) => {
recordingCreator.show(item.Id, item.ServerId);
});
@ -73,11 +85,11 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
function getItem(button) {
button = dom.parentWithAttribute(button, 'data-id');
var serverId = button.getAttribute('data-serverid');
var id = button.getAttribute('data-id');
var type = button.getAttribute('data-type');
const serverId = button.getAttribute('data-serverid');
const id = button.getAttribute('data-id');
const type = button.getAttribute('data-type');
var apiClient = connectionManager.getApiClient(serverId);
const apiClient = connectionManager.getApiClient(serverId);
if (type === 'Timer') {
return apiClient.getLiveTvTimer(id);
@ -99,19 +111,19 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
function showContextMenu(card, options) {
getItem(card).then(function (item) {
getItem(card).then(item => {
var playlistId = card.getAttribute('data-playlistid');
var collectionId = card.getAttribute('data-collectionid');
const playlistId = card.getAttribute('data-playlistid');
const collectionId = card.getAttribute('data-collectionid');
if (playlistId) {
var elem = dom.parentWithAttribute(card, 'data-playlistitemid');
const elem = dom.parentWithAttribute(card, 'data-playlistitemid');
item.PlaylistItemId = elem ? elem.getAttribute('data-playlistitemid') : null;
}
require(['itemContextMenu'], function (itemContextMenu) {
import('itemContextMenu').then(({default: itemContextMenu}) => {
connectionManager.getApiClient(item.ServerId).getCurrentUser().then(function (user) {
connectionManager.getApiClient(item.ServerId).getCurrentUser().then(user => {
itemContextMenu.show(Object.assign({
item: item,
play: true,
@ -122,9 +134,7 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
collectionId: collectionId,
user: user
}, options || {})).then(function (result) {
var itemsContainer;
}, options || {})).then(result => {
if (result.command === 'playallfromhere' || result.command === 'queueallfromhere') {
executeAction(card, options.positionTo, result.command);
@ -157,9 +167,9 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
function showPlayMenu(card, target) {
var item = getItemInfoFromCard(card);
const item = getItemInfoFromCard(card);
require(['playMenu'], function (playMenu) {
import('playMenu').then(({default: playMenu}) => {
playMenu.show({
@ -170,7 +180,7 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
}
function sendToast(text) {
require(['toast'], function (toast) {
import('toast').then(({default: toast}) => {
toast(text);
});
}
@ -179,19 +189,19 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
target = target || card;
var id = card.getAttribute('data-id');
let id = card.getAttribute('data-id');
if (!id) {
card = dom.parentWithAttribute(card, 'data-id');
id = card.getAttribute('data-id');
}
var item = getItemInfoFromCard(card);
const item = getItemInfoFromCard(card);
var serverId = item.ServerId;
var type = item.Type;
const serverId = item.ServerId;
const type = item.Type;
var playableItemId = type === 'Program' ? item.ChannelId : item.Id;
const playableItemId = type === 'Program' ? item.ChannelId : item.Id;
if (item.MediaType === 'Photo' && action === 'link') {
action = 'play';
@ -213,7 +223,7 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
});
} else if (action === 'play' || action === 'resume') {
var startPositionTicks = parseInt(card.getAttribute('data-positionticks') || '0');
const startPositionTicks = parseInt(card.getAttribute('data-positionticks') || '0');
playbackManager.play({
ids: [playableItemId],
@ -244,7 +254,7 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
onRecordCommand(serverId, id, type, card.getAttribute('data-timerid'), card.getAttribute('data-seriestimerid'));
} else if (action === 'menu') {
var options = target.getAttribute('data-playoptions') === 'false' ?
const options = target.getAttribute('data-playoptions') === 'false' ?
{
shuffle: false,
instantMix: false,
@ -261,7 +271,7 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
} else if (action === 'playmenu') {
showPlayMenu(card, target);
} else if (action === 'edit') {
getItem(target).then(function (item) {
getItem(target).then(item => {
editItem(item, serverId);
});
} else if (action === 'playtrailer') {
@ -270,9 +280,9 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
getItem(target).then(addToPlaylist);
} else if (action === 'custom') {
var customAction = target.getAttribute('data-customaction');
const customAction = target.getAttribute('data-customaction');
card.dispatchEvent(new CustomEvent('action-' + customAction, {
card.dispatchEvent(new CustomEvent(`action-${customAction}`, {
detail: {
playlistItemId: card.getAttribute('data-playlistitemid')
},
@ -283,7 +293,7 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
}
function addToPlaylist(item) {
require(['playlistEditor'], function (playlistEditor) {
import('playlistEditor').then(({default: playlistEditor}) => {
new playlistEditor().show({
items: [item.Id],
@ -295,35 +305,35 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
function playTrailer(item) {
var apiClient = connectionManager.getApiClient(item.ServerId);
const apiClient = connectionManager.getApiClient(item.ServerId);
apiClient.getLocalTrailers(apiClient.getCurrentUserId(), item.Id).then(function (trailers) {
apiClient.getLocalTrailers(apiClient.getCurrentUserId(), item.Id).then(trailers => {
playbackManager.play({ items: trailers });
});
}
function editItem(item, serverId) {
var apiClient = connectionManager.getApiClient(serverId);
const apiClient = connectionManager.getApiClient(serverId);
return new Promise(function (resolve, reject) {
return new Promise((resolve, reject) => {
var serverId = apiClient.serverInfo().Id;
const serverId = apiClient.serverInfo().Id;
if (item.Type === 'Timer') {
if (item.ProgramId) {
require(['recordingCreator'], function (recordingCreator) {
import('recordingCreator').then(({default: recordingCreator}) => {
recordingCreator.show(item.ProgramId, serverId).then(resolve, reject);
});
} else {
require(['recordingEditor'], function (recordingEditor) {
import('recordingEditor').then(({default: recordingEditor}) => {
recordingEditor.show(item.Id, serverId).then(resolve, reject);
});
}
} else {
require(['metadataEditor'], function (metadataEditor) {
import('metadataEditor').then(({default: metadataEditor}) => {
metadataEditor.show(item.Id, serverId).then(resolve, reject);
});
@ -335,19 +345,19 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
if (type === 'Program' || timerId || seriesTimerId) {
var programId = type === 'Program' ? id : null;
const programId = type === 'Program' ? id : null;
recordingHelper.toggleRecording(serverId, programId, timerId, seriesTimerId);
}
}
function onClick(e) {
export function onClick(e) {
var card = dom.parentWithClass(e.target, 'itemAction');
const card = dom.parentWithClass(e.target, 'itemAction');
if (card) {
var actionElement = card;
var action = actionElement.getAttribute('data-action');
let actionElement = card;
let action = actionElement.getAttribute('data-action');
if (!action) {
actionElement = dom.parentWithAttribute(actionElement, 'data-action');
@ -368,12 +378,12 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
function onCommand(e) {
var cmd = e.detail.command;
const cmd = e.detail.command;
if (cmd === 'play' || cmd === 'resume' || cmd === 'record' || cmd === 'menu' || cmd === 'info') {
var target = e.target;
var card = dom.parentWithClass(target, 'itemAction') || dom.parentWithAttribute(target, 'data-id');
const target = e.target;
const card = dom.parentWithClass(target, 'itemAction') || dom.parentWithAttribute(target, 'data-id');
if (card) {
e.preventDefault();
@ -383,7 +393,7 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
}
}
function on(context, options) {
export function on(context, options) {
options = options || {};
@ -396,7 +406,7 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
}
}
function off(context, options) {
export function off(context, options) {
options = options || {};
context.removeEventListener('click', onClick);
@ -406,23 +416,24 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
}
}
function getShortcutAttributesHtml(item, serverId) {
export function getShortcutAttributesHtml(item, serverId) {
var html = 'data-id="' + item.Id + '" data-serverid="' + (serverId || item.ServerId) + '" data-type="' + item.Type + '" data-mediatype="' + item.MediaType + '" data-channelid="' + item.ChannelId + '" data-isfolder="' + item.IsFolder + '"';
let html = `data-id="${item.Id}" data-serverid="${serverId || item.ServerId}" data-type="${item.Type}" data-mediatype="${item.MediaType}" data-channelid="${item.ChannelId}" data-isfolder="${item.IsFolder}"`;
var collectionType = item.CollectionType;
const collectionType = item.CollectionType;
if (collectionType) {
html += ' data-collectiontype="' + collectionType + '"';
html += ` data-collectiontype="${collectionType}"`;
}
return html;
}
return {
on: on,
off: off,
onClick: onClick,
getShortcutAttributesHtml: getShortcutAttributesHtml
};
/* eslint-enable indent */
export default {
on: on,
off: off,
onClick: onClick,
getShortcutAttributesHtml: getShortcutAttributesHtml
};
});

View file

@ -2,9 +2,20 @@
* Image viewer component
* @module components/slideshow/slideshow
*/
define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'focusManager', 'browser', 'apphost', 'css!./style', 'material-icons', 'paper-icon-button-light'], function (dialogHelper, inputManager, connectionManager, layoutManager, focusManager, browser, appHost) {
define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'focusManager', 'browser', 'apphost', 'dom', 'css!./style', 'material-icons', 'paper-icon-button-light'], function (dialogHelper, inputManager, connectionManager, layoutManager, focusManager, browser, appHost, dom) {
'use strict';
/**
* Name of transition event.
*/
const transitionEndEventName = dom.whichTransitionEvent();
/**
* Flag to use fake image to fix blurry zoomed image.
* At least WebKit doesn't restore quality for zoomed images.
*/
const useFakeZoomImage = browser.safari;
/**
* Retrieves an item's image URL from the API.
* @param {object|string} item - Item used to generate the image URL.
@ -240,6 +251,41 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f
}
}
/**
* Handles zoom changes.
*/
function onZoomChange(scale, imageEl, slideEl) {
const zoomImage = slideEl.querySelector('.swiper-zoom-fakeimg');
if (zoomImage) {
zoomImage.style.width = zoomImage.style.height = scale * 100 + '%';
if (scale > 1) {
if (zoomImage.classList.contains('swiper-zoom-fakeimg-hidden')) {
// Await for Swiper style changes
setTimeout(() => {
const callback = () => {
imageEl.removeEventListener(transitionEndEventName, callback);
zoomImage.classList.remove('swiper-zoom-fakeimg-hidden');
};
// Swiper set 'transition-duration: 300ms' for auto zoom
// and 'transition-duration: 0s' for touch zoom
const transitionDuration = parseFloat(imageEl.style.transitionDuration.replace(/[a-z]/i, ''));
if (transitionDuration > 0) {
imageEl.addEventListener(transitionEndEventName, callback);
} else {
callback();
}
}, 0);
}
} else {
zoomImage.classList.add('swiper-zoom-fakeimg-hidden');
}
}
}
/**
* Initializes the Swiper instance and binds the relevant events.
* @param {HTMLElement} dialog - Element containing the dialog.
@ -260,8 +306,7 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f
loop: false,
zoom: {
minRatio: 1,
toggle: true,
containerClass: 'slider-zoom-container'
toggle: true
},
autoplay: !options.interactive,
keyboard: {
@ -288,6 +333,10 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f
swiperInstance.on('autoplayStart', onAutoplayStart);
swiperInstance.on('autoplayStop', onAutoplayStop);
if (useFakeZoomImage) {
swiperInstance.on('zoomChange', onZoomChange);
}
});
}
@ -328,7 +377,10 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f
function getSwiperSlideHtmlFromSlide(item) {
var html = '';
html += '<div class="swiper-slide" data-original="' + item.originalImage + '" data-itemid="' + item.Id + '" data-serverid="' + item.ServerId + '">';
html += '<div class="slider-zoom-container">';
html += '<div class="swiper-zoom-container">';
if (useFakeZoomImage) {
html += `<div class="swiper-zoom-fakeimg swiper-zoom-fakeimg-hidden" style="background-image: url('${item.originalImage}')"></div>`;
}
html += '<img src="' + item.originalImage + '" class="swiper-slide-img">';
html += '</div>';
if (item.title || item.subtitle) {

View file

@ -40,16 +40,6 @@
text-shadow: 3px 3px 0 #000, -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
}
.swiper-slide-img {
max-height: 100%;
max-width: 100%;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
margin: auto;
}
.slideshowButtonIcon {
color: #fff;
opacity: 0.7;
@ -135,13 +125,18 @@
color: #ccc;
}
.swiper-slide {
display: flex;
flex-direction: column;
.swiper-zoom-fakeimg {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-position: 50% 50%;
background-repeat: no-repeat;
background-size: contain;
z-index: 1;
pointer-events: none;
}
.slider-zoom-container {
margin: auto;
max-height: 100%;
max-width: 100%;
.swiper-zoom-fakeimg-hidden {
display: none;
}

View file

@ -65,8 +65,6 @@ class TimeSyncManager {
this.pings = 0; // number of pings
this.measurement = null; // current time sync
this.measurements = [];
this.startPing();
}
/**