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

Merge branch 'unstable' into show-mobile-seek

This commit is contained in:
Ian Walton 2020-08-25 22:19:59 -04:00
commit 201685a60b
137 changed files with 3677 additions and 4123 deletions

File diff suppressed because it is too large Load diff

View file

@ -55,7 +55,7 @@ function replaceAll(originalString, strReplace, strWith) {
function generateDeviceId() {
const keys = [];
if (keys.push(navigator.userAgent), keys.push(new Date().getTime()), self.btoa) {
if (keys.push(navigator.userAgent), keys.push(new Date().getTime()), window.btoa) {
const result = replaceAll(btoa(keys.join('|')), '=', '1');
return Promise.resolve(result);
}
@ -404,9 +404,9 @@ document.addEventListener(visibilityChange, function () {
}
}, false);
if (self.addEventListener) {
self.addEventListener('focus', onAppVisible);
self.addEventListener('blur', onAppHidden);
if (window.addEventListener) {
window.addEventListener('focus', onAppVisible);
window.addEventListener('blur', onAppHidden);
}
export default appHost;

View file

@ -239,33 +239,13 @@ button::-moz-focus-inner {
border: none;
}
.cardImage-img {
max-height: 100%;
max-width: 100%;
/* This is simply for lazy image purposes, to ensure the image is visible sooner when scrolling */
min-height: 70%;
min-width: 70%;
margin: auto;
}
.coveredImage-img {
width: 100%;
height: 100%;
}
.coveredImage-noscale-img {
max-height: none;
max-width: none;
}
.coveredImage {
background-size: cover;
background-position: center center;
}
.coveredImage-noScale {
background-size: cover;
.coveredImage.coveredImage-contain {
background-size: contain;
}
.cardFooter {
@ -372,6 +352,8 @@ button::-moz-focus-inner {
.cardDefaultText {
white-space: normal;
text-align: center;
font-size: 2em;
font-weight: bold;
}
.cardImageContainer .cardImageIcon {

View file

@ -986,6 +986,10 @@ import 'programStyles';
lines = [];
}
if (overlayText && showTitle) {
lines = [item.Name];
}
const addRightTextMargin = isOuterFooter && options.cardLayout && !options.centerText && options.cardFooterAside !== 'none' && layoutManager.mobile;
html += getCardTextLines(lines, cssClass, !options.overlayText, isOuterFooter, options.cardLayout, addRightTextMargin, options.lines);
@ -1117,7 +1121,7 @@ import 'programStyles';
function importRefreshIndicator() {
if (!refreshIndicatorLoaded) {
refreshIndicatorLoaded = true;
/* eslint-disable-next-line no-unused-expressions */
/* eslint-disable-next-line @babel/no-unused-expressions */
import('emby-itemrefreshindicator');
}
}
@ -1212,8 +1216,8 @@ import 'programStyles';
if (coveredImage) {
cardImageContainerClass += ' coveredImage';
if (item.MediaType === 'Photo' || item.Type === 'PhotoAlbum' || item.Type === 'Folder' || item.ProgramInfo || item.Type === 'Program' || item.Type === 'Recording') {
cardImageContainerClass += ' coveredImage-noScale';
if (item.Type === 'TvChannel') {
cardImageContainerClass += ' coveredImage-contain';
}
}
@ -1449,7 +1453,7 @@ import 'programStyles';
const userData = item.UserData || {};
if (itemHelper.canMarkPlayed(item)) {
/* eslint-disable-next-line no-unused-expressions */
/* eslint-disable-next-line @babel/no-unused-expressions */
import('emby-playstatebutton');
html += '<button is="emby-playstatebutton" type="button" data-action="none" class="' + btnCssClass + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-played="' + (userData.Played) + '"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover check"></span></button>';
}
@ -1457,7 +1461,7 @@ import 'programStyles';
if (itemHelper.canRate(item)) {
const likes = userData.Likes == null ? '' : userData.Likes;
/* eslint-disable-next-line no-unused-expressions */
/* eslint-disable-next-line @babel/no-unused-expressions */
import('emby-ratingbutton');
html += '<button is="emby-ratingbutton" type="button" data-action="none" class="' + btnCssClass + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-likes="' + likes + '" data-isfavorite="' + (userData.IsFavorite) + '"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover favorite"></span></button>';
}

View file

@ -19,7 +19,7 @@ export default (() => {
}
const text = replaceAll(options.text || '', '<br/>', '\n');
const result = confirm(text);
const result = window.confirm(text);
if (result) {
return Promise.resolve();

View file

@ -85,9 +85,9 @@ import 'scrollStyles';
}
if (!self.closedByBack && isHistoryEnabled(dlg)) {
const state = history.state || {};
const state = window.history.state || {};
if (state.dialogId === hash) {
history.back();
window.history.back();
}
}
@ -213,7 +213,7 @@ import 'scrollStyles';
export function close(dlg) {
if (isOpened(dlg)) {
if (isHistoryEnabled(dlg)) {
history.back();
window.history.back();
} else {
closeDialog(dlg);
}
@ -375,7 +375,7 @@ import 'scrollStyles';
dlg.setAttribute('data-lockscroll', 'true');
}
if (options.enableHistory !== false && appRouter.enableNativeHistory()) {
if (options.enableHistory !== false) {
dlg.setAttribute('data-history', 'true');
}

View file

@ -125,7 +125,7 @@ import 'emby-button';
html += `<input is="emby-input" id="txtDirectoryPickerPath" type="text" required="required" ${readOnlyAttribute} label="${globalize.translate(labelKey)}"/>`;
html += '</div>';
if (!readOnlyAttribute) {
html += `<button type="button" is="paper-icon-button-light" class="btnRefreshDirectories emby-input-iconbutton" title="${globalize.translate('ButtonRefresh')}"><span class="material-icons search"></span></button>`;
html += `<button type="button" is="paper-icon-button-light" class="btnRefreshDirectories emby-input-iconbutton" title="${globalize.translate('Refresh')}"><span class="material-icons search"></span></button>`;
}
html += '</div>';
if (!readOnlyAttribute) {

View file

@ -170,7 +170,7 @@
<div class="checkboxContainer checkboxContainer-withDescription fldThemeSong hide">
<label>
<input type="checkbox" is="emby-checkbox" id="chkThemeSong" />
<span>${EnableThemeSongs}</span>
<span>${ThemeSongs}</span>
</label>
<div class="fieldDescription checkboxFieldDescription">${EnableThemeSongsHelp}</div>
</div>
@ -178,7 +178,7 @@
<div class="checkboxContainer checkboxContainer-withDescription fldThemeVideo hide">
<label>
<input type="checkbox" is="emby-checkbox" id="chkThemeVideo" />
<span>${EnableThemeVideos}</span>
<span>${ThemeVideos}</span>
</label>
<div class="fieldDescription checkboxFieldDescription">${EnableThemeVideosHelp}</div>
</div>

View file

@ -70,6 +70,10 @@
contain: strict;
}
.programContainer.emby-scroller {
margin: 0;
}
.channelPrograms {
height: 4.42em;
contain: strict;

View file

@ -1,6 +1,6 @@
<form style="margin:0 auto;">
<div class="verticalSection verticalSection-extrabottompadding">
<h2 class="sectionTitle">${HeaderHome}</h2>
<h2 class="sectionTitle">${Home}</h2>
<div class="selectContainer hide selectTVHomeScreenContainer">
<select is="emby-select" class="selectTVHomeScreen" label="${LabelTVHomeScreen}">

View file

@ -87,6 +87,9 @@ import 'css!./style';
requestAnimationFrame(() => {
if (elem.tagName !== 'IMG') {
elem.style.backgroundImage = "url('" + url + "')";
if (elem.classList.contains('blurhashed')) {
elem.style.backgroundColor = '#fff';
}
} else {
elem.setAttribute('src', url);
}
@ -108,6 +111,7 @@ import 'css!./style';
if (elem.tagName !== 'IMG') {
url = elem.style.backgroundImage.slice(4, -1).replace(/"/g, '');
elem.style.backgroundImage = 'none';
elem.style.backgroundColor = null;
} else {
url = elem.getAttribute('src');
elem.setAttribute('src', '');

View file

@ -8,7 +8,6 @@ import browser from 'browser';
import actionsheet from 'actionsheet';
/* eslint-disable indent */
export function getCommands(options) {
const item = options.item;
const user = options.user;

View file

@ -2,7 +2,7 @@
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1">
<span class="material-icons arrow_back"></span>
</button>
<h3 class="formDialogHeaderTitle">${HeaderMediaInfo}</h3>
<h3 class="formDialogHeaderTitle">${MoreMediaInfo}</h3>
</div>
<div class="formDialogContent smoothScrollY">

View file

@ -88,7 +88,7 @@
<div class="checkboxContainer checkboxContainer-withDescription hide chkImportMissingEpisodesContainer advanced">
<label>
<input is="emby-checkbox" type="checkbox" id="chkImportMissingEpisodes" />
<span>${LabelDisplayMissingEpisodesWithinSeasons}</span>
<span>${DisplayMissingEpisodesWithinSeasons}</span>
</label>
<div class="fieldDescription checkboxFieldDescription">${ImportMissingEpisodesHelp}</div>
</div>

View file

@ -9,7 +9,6 @@ import 'programStyles';
import 'emby-button';
/* eslint-disable indent */
function getTimerIndicator(item) {
let status;

View file

@ -1,134 +1,140 @@
define(['appSettings', 'pluginManager'], function (appSettings, pluginManager) {
'use strict';
import appSettings from 'appSettings';
import pluginManager from 'pluginManager';
/* eslint-disable indent */
var settingsKey = 'installedpackages1';
class PackageManager {
#packagesList = [];
#settingsKey = 'installedpackages1';
function addPackage(packageManager, pkg) {
packageManager.packagesList = packageManager.packagesList.filter(function (p) {
return p.name !== pkg.name;
});
init() {
console.groupCollapsed('loading packages');
var manifestUrls = JSON.parse(appSettings.get(this.#settingsKey) || '[]');
packageManager.packagesList.push(pkg);
}
return Promise.all(manifestUrls.map((url) => {
return this.loadPackage(url);
}))
.then(() => {
console.debug('finished loading packages');
return Promise.resolve();
})
.catch(() => {
return Promise.resolve();
}).finally(() => {
console.groupEnd('loading packages');
});
}
function removeUrl(url) {
var manifestUrls = JSON.parse(appSettings.get(settingsKey) || '[]');
get packages() {
return this.#packagesList.slice(0);
}
manifestUrls = manifestUrls.filter(function (i) {
return i !== url;
});
install(url) {
return this.loadPackage(url, true).then((pkg) => {
var manifestUrls = JSON.parse(appSettings.get(this.#settingsKey) || '[]');
appSettings.set(settingsKey, JSON.stringify(manifestUrls));
}
function loadPackage(packageManager, url, throwError) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
var originalUrl = url;
url += url.indexOf('?') === -1 ? '?' : '&';
url += 't=' + new Date().getTime();
xhr.open('GET', url, true);
var onError = function () {
if (throwError === true) {
reject();
} else {
removeUrl(originalUrl);
resolve();
if (!manifestUrls.includes(url)) {
manifestUrls.push(url);
appSettings.set(this.#settingsKey, JSON.stringify(manifestUrls));
}
};
xhr.onload = function (e) {
if (this.status < 400) {
var pkg = JSON.parse(this.response);
pkg.url = originalUrl;
return pkg;
});
}
addPackage(packageManager, pkg);
uninstall(name) {
var pkg = this.#packagesList.filter((p) => {
return p.name === name;
})[0];
var plugins = pkg.plugins || [];
if (pkg.plugin) {
plugins.push(pkg.plugin);
}
var promises = plugins.map(function (pluginUrl) {
return pluginManager.loadPlugin(packageManager.mapPath(pkg, pluginUrl));
});
Promise.all(promises).then(resolve, resolve);
} else {
onError();
}
};
if (pkg) {
this.#packagesList = this.#packagesList.filter((p) => {
return p.name !== name;
});
xhr.onerror = onError;
xhr.send();
});
}
function PackageManager() {
this.packagesList = [];
}
PackageManager.prototype.init = function () {
var manifestUrls = JSON.parse(appSettings.get(settingsKey) || '[]');
var instance = this;
return Promise.all(manifestUrls.map(function (u) {
return loadPackage(instance, u);
})).then(function () {
return Promise.resolve();
}, function () {
return Promise.resolve();
});
};
PackageManager.prototype.packages = function () {
return this.packagesList.slice(0);
};
PackageManager.prototype.install = function (url) {
return loadPackage(this, url, true).then(function (pkg) {
var manifestUrls = JSON.parse(appSettings.get(settingsKey) || '[]');
if (manifestUrls.indexOf(url) === -1) {
manifestUrls.push(url);
appSettings.set(settingsKey, JSON.stringify(manifestUrls));
this.removeUrl(pkg.url);
}
return pkg;
});
};
return Promise.resolve();
}
PackageManager.prototype.uninstall = function (name) {
var pkg = this.packagesList.filter(function (p) {
return p.name === name;
})[0];
mapPath(pkg, pluginUrl) {
var urlLower = pluginUrl.toLowerCase();
if (urlLower.startsWith('http:') || urlLower.startsWith('https:') || urlLower.startsWith('file:')) {
return pluginUrl;
}
if (pkg) {
this.packagesList = this.packagesList.filter(function (p) {
return p.name !== name;
var packageUrl = pkg.url;
packageUrl = packageUrl.substring(0, packageUrl.lastIndexOf('/'));
packageUrl += '/';
packageUrl += pluginUrl;
return packageUrl;
}
addPackage(pkg) {
this.#packagesList = this.#packagesList.filter((p) => {
return p.name !== pkg.name;
});
removeUrl(pkg.url);
this.#packagesList.push(pkg);
}
return Promise.resolve();
};
removeUrl(url) {
var manifestUrls = JSON.parse(appSettings.get(this.#settingsKey) || '[]');
PackageManager.prototype.mapPath = function (pkg, pluginUrl) {
var urlLower = pluginUrl.toLowerCase();
if (urlLower.indexOf('http:') === 0 || urlLower.indexOf('https:') === 0 || urlLower.indexOf('file:') === 0) {
return pluginUrl;
manifestUrls = manifestUrls.filter((i) => {
return i !== url;
});
appSettings.set(this.#settingsKey, JSON.stringify(manifestUrls));
}
var packageUrl = pkg.url;
packageUrl = packageUrl.substring(0, packageUrl.lastIndexOf('/'));
loadPackage(url, throwError = false) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
var originalUrl = url;
url += url.indexOf('?') === -1 ? '?' : '&';
url += 't=' + new Date().getTime();
packageUrl += '/';
packageUrl += pluginUrl;
xhr.open('GET', url, true);
return packageUrl;
};
var onError = () => {
if (throwError === true) {
reject();
} else {
this.removeUrl(originalUrl);
resolve();
}
};
return new PackageManager();
});
xhr.onload = () => {
if (this.status < 400) {
var pkg = JSON.parse(this.response);
pkg.url = originalUrl;
this.addPackage(pkg);
var plugins = pkg.plugins || [];
if (pkg.plugin) {
plugins.push(pkg.plugin);
}
var promises = plugins.map((pluginUrl) => {
return pluginManager.loadPlugin(this.mapPath(pkg, pluginUrl));
});
Promise.all(promises).then(resolve, resolve);
} else {
onError();
}
};
xhr.onerror = onError;
xhr.send();
});
}
}
/* eslint-enable indent */
export default new PackageManager();

View file

@ -1112,6 +1112,52 @@ class PlaybackManager {
}
};
self.increasePlaybackRate = function (player) {
player = player || self._currentPlayer;
if (player) {
let current = self.getPlaybackRate(player);
let supported = self.getSupportedPlaybackRates(player);
let index = -1;
for (let i = 0, length = supported.length; i < length; i++) {
if (supported[i].id === current) {
index = i;
break;
}
}
index = Math.min(index + 1, supported.length - 1);
self.setPlaybackRate(supported[index].id, player);
}
};
self.decreasePlaybackRate = function (player) {
player = player || self._currentPlayer;
if (player) {
let current = self.getPlaybackRate(player);
let supported = self.getSupportedPlaybackRates(player);
let index = -1;
for (let i = 0, length = supported.length; i < length; i++) {
if (supported[i].id === current) {
index = i;
break;
}
}
index = Math.max(index - 1, 0);
self.setPlaybackRate(supported[index].id, player);
}
};
self.getSupportedPlaybackRates = function (player) {
player = player || self._currentPlayer;
if (player && player.getSupportedPlaybackRates) {
return player.getSupportedPlaybackRates();
}
return [];
};
let brightnessOsdLoaded;
self.setBrightness = function (val, player) {
player = player || self._currentPlayer;
@ -1416,8 +1462,8 @@ class PlaybackManager {
self.toggleFullscreen = function (player) {
player = player || self._currentPlayer;
if (!player.isLocalPlayer || player.toggleFulscreen) {
return player.toggleFulscreen();
if (!player.isLocalPlayer || player.toggleFullscreen) {
return player.toggleFullscreen();
}
if (screenfull.isEnabled) {
@ -3697,6 +3743,9 @@ class PlaybackManager {
case 'SetAspectRatio':
this.setAspectRatio(cmd.Arguments.AspectRatio, player);
break;
case 'PlaybackRate':
this.setPlaybackRate(cmd.Arguments.PlaybackRate, player);
break;
case 'SetBrightness':
this.setBrightness(cmd.Arguments.Brightness, player);
break;

View file

@ -18,7 +18,7 @@ events.on(playbackManager, 'playbackstart', function (e, player, state) {
if (isLocalVideo && layoutManager.mobile) {
/* eslint-disable-next-line compat/compat */
var lockOrientation = screen.lockOrientation || screen.mozLockOrientation || screen.msLockOrientation || (screen.orientation && screen.orientation.lock);
var lockOrientation = window.screen.lockOrientation || window.screen.mozLockOrientation || window.screen.msLockOrientation || (window.screen.orientation && window.screen.orientation.lock);
if (lockOrientation) {
try {
@ -39,7 +39,7 @@ events.on(playbackManager, 'playbackstart', function (e, player, state) {
events.on(playbackManager, 'playbackstop', function (e, playbackStopInfo) {
if (orientationLocked && !playbackStopInfo.nextMediaType) {
/* eslint-disable-next-line compat/compat */
var unlockOrientation = screen.unlockOrientation || screen.mozUnlockOrientation || screen.msUnlockOrientation || (screen.orientation && screen.orientation.unlock);
var unlockOrientation = window.screen.unlockOrientation || window.screen.mozUnlockOrientation || window.screen.msUnlockOrientation || (window.screen.orientation && window.screen.orientation.unlock);
if (unlockOrientation) {
try {

View file

@ -149,6 +149,28 @@ function showAspectRatioMenu(player, btn) {
});
}
function showPlaybackRateMenu(player, btn) {
// each has a name and id
const currentId = playbackManager.getPlaybackRate(player);
const menuItems = playbackManager.getSupportedPlaybackRates(player).map(i => ({
id: i.id,
name: i.name,
selected: i.id === currentId
}));
return actionsheet.show({
items: menuItems,
positionTo: btn
}).then(function (id) {
if (id) {
playbackManager.setPlaybackRate(id, player);
return Promise.resolve();
}
return Promise.reject();
});
}
function showWithUser(options, player, user) {
var supportedCommands = playbackManager.getSupportedCommands(player);
@ -166,6 +188,17 @@ function showWithUser(options, player, user) {
});
}
if (supportedCommands.indexOf('PlaybackRate') !== -1) {
const currentPlaybackRateId = playbackManager.getPlaybackRate(player);
const currentPlaybackRate = playbackManager.getSupportedPlaybackRates(player).filter(i => i.id === currentPlaybackRateId)[0];
menuItems.push({
name: globalize.translate('PlaybackRate'),
id: 'playbackrate',
asideText: currentPlaybackRate ? currentPlaybackRate.name : null
});
}
if (user && user.Policy.EnableVideoPlaybackTranscoding) {
var secondaryQualityText = getQualitySecondaryText(player);
@ -230,6 +263,8 @@ function handleSelectedOption(id, options, player) {
return showQualityMenu(player, options.positionTo);
case 'aspectratio':
return showAspectRatioMenu(player, options.positionTo);
case 'playbackrate':
return showPlaybackRateMenu(player, options.positionTo);
case 'repeatmode':
return showRepeatModeMenu(player, options.positionTo);
case 'stats':

View file

@ -1,37 +1,38 @@
define(['events', 'globalize'], function (events, globalize) {
'use strict';
import events from 'events';
import globalize from 'globalize';
/* eslint-disable indent */
// TODO: replace with each plugin version
var cacheParam = new Date().getTime();
function loadStrings(plugin) {
var strings = plugin.getTranslations ? plugin.getTranslations() : [];
return globalize.loadStrings({
name: plugin.id || plugin.packageName,
strings: strings
});
}
class PluginManager {
pluginsList = [];
function definePluginRoute(pluginManager, route, plugin) {
route.contentPath = pluginManager.mapPath(plugin, route.path);
route.path = pluginManager.mapRoute(plugin, route);
get plugins() {
return this.pluginsList;
}
Emby.App.defineRoute(route, plugin.id);
}
#loadStrings(plugin) {
var strings = plugin.getTranslations ? plugin.getTranslations() : [];
return globalize.loadStrings({
name: plugin.id || plugin.packageName,
strings: strings
});
}
function PluginManager() {
this.pluginsList = [];
}
#definePluginRoute(route, plugin) {
route.contentPath = this.mapPath(plugin, route.path);
route.path = this.#mapRoute(plugin, route);
PluginManager.prototype.loadPlugin = function(pluginSpec) {
var instance = this;
Emby.App.defineRoute(route, plugin.id);
}
function registerPlugin(plugin) {
instance.register(plugin);
#registerPlugin(plugin) {
this.#register(plugin);
if (plugin.getRoutes) {
plugin.getRoutes().forEach(function (route) {
definePluginRoute(instance, route, plugin);
plugin.getRoutes().forEach((route) => {
this.#definePluginRoute(route, plugin);
});
}
@ -40,7 +41,7 @@ define(['events', 'globalize'], function (events, globalize) {
return Promise.resolve(plugin);
} else {
return new Promise((resolve, reject) => {
loadStrings(plugin)
this.#loadStrings(plugin)
.then(function () {
resolve(plugin);
})
@ -49,103 +50,102 @@ define(['events', 'globalize'], function (events, globalize) {
}
}
if (typeof pluginSpec === 'string') {
console.debug('Loading plugin (via deprecated requirejs method): ' + pluginSpec);
loadPlugin(pluginSpec) {
if (typeof pluginSpec === 'string') {
console.debug('Loading plugin (via deprecated requirejs method): ' + pluginSpec);
return new Promise(function (resolve, reject) {
require([pluginSpec], (pluginFactory) => {
var plugin = pluginFactory.default ? new pluginFactory.default() : new pluginFactory();
return new Promise((resolve, reject) => {
require([pluginSpec], (pluginFactory) => {
var plugin = pluginFactory.default ? new pluginFactory.default() : new pluginFactory();
// See if it's already installed
var existing = instance.pluginsList.filter(function (p) {
return p.id === plugin.id;
})[0];
// See if it's already installed
var existing = this.pluginsList.filter(function (p) {
return p.id === plugin.id;
})[0];
if (existing) {
resolve(pluginSpec);
}
if (existing) {
resolve(pluginSpec);
}
plugin.installUrl = pluginSpec;
plugin.installUrl = pluginSpec;
var separatorIndex = Math.max(pluginSpec.lastIndexOf('/'), pluginSpec.lastIndexOf('\\'));
plugin.baseUrl = pluginSpec.substring(0, separatorIndex);
var separatorIndex = Math.max(pluginSpec.lastIndexOf('/'), pluginSpec.lastIndexOf('\\'));
plugin.baseUrl = pluginSpec.substring(0, separatorIndex);
var paths = {};
paths[plugin.id] = plugin.baseUrl;
var paths = {};
paths[plugin.id] = plugin.baseUrl;
requirejs.config({
waitSeconds: 0,
paths: paths
requirejs.config({
waitSeconds: 0,
paths: paths
});
this.#registerPlugin(plugin).then(resolve).catch(reject);
});
registerPlugin(plugin).then(resolve).catch(reject);
});
} else if (pluginSpec.then) {
return pluginSpec.then(pluginBuilder => {
return pluginBuilder();
}).then((plugin) => {
console.debug(`Plugin loaded: ${plugin.id}`);
return this.#registerPlugin(plugin);
});
} else {
const err = new TypeError('Plugins have to be a Promise that resolves to a plugin builder function or a RequireJS url (deprecated)');
console.error(err);
return Promise.reject(err);
}
}
// In lieu of automatic discovery, plugins will register dynamic objects
// Each object will have the following properties:
// name
// type (skin, screensaver, etc)
#register(obj) {
this.pluginsList.push(obj);
events.trigger(this, 'registered', [obj]);
}
ofType(type) {
return this.pluginsList.filter((o) => {
return o.type === type;
});
} else if (pluginSpec.then) {
return pluginSpec.then(pluginBuilder => {
return pluginBuilder();
}).then(plugin => {
console.debug(`Plugin loaded: ${plugin.id}`);
return registerPlugin(plugin);
});
} else {
const err = new Error('Plugins have to be a Promise that resolves to a plugin builder function or a requirejs urls (deprecated)');
console.error(err);
return Promise.reject(err);
}
};
// In lieu of automatic discovery, plugins will register dynamic objects
// Each object will have the following properties:
// name
// type (skin, screensaver, etc)
PluginManager.prototype.register = function (obj) {
this.pluginsList.push(obj);
events.trigger(this, 'registered', [obj]);
};
PluginManager.prototype.ofType = function (type) {
return this.pluginsList.filter(function (o) {
return o.type === type;
});
};
PluginManager.prototype.plugins = function () {
return this.pluginsList;
};
PluginManager.prototype.mapRoute = function (plugin, route) {
if (typeof plugin === 'string') {
plugin = this.pluginsList.filter(function (p) {
return (p.id || p.packageName) === plugin;
})[0];
}
route = route.path || route;
#mapRoute(plugin, route) {
if (typeof plugin === 'string') {
plugin = this.pluginsList.filter((p) => {
return (p.id || p.packageName) === plugin;
})[0];
}
if (route.toLowerCase().indexOf('http') === 0) {
return route;
route = route.path || route;
if (route.toLowerCase().startsWith('http')) {
return route;
}
return '/plugins/' + plugin.id + '/' + route;
}
return '/plugins/' + plugin.id + '/' + route;
};
mapPath(plugin, path, addCacheParam) {
if (typeof plugin === 'string') {
plugin = this.pluginsList.filter((p) => {
return (p.id || p.packageName) === plugin;
})[0];
}
PluginManager.prototype.mapPath = function (plugin, path, addCacheParam) {
if (typeof plugin === 'string') {
plugin = this.pluginsList.filter(function (p) {
return (p.id || p.packageName) === plugin;
})[0];
var url = plugin.baseUrl + '/' + path;
if (addCacheParam) {
url += url.includes('?') ? '&' : '?';
url += 'v=' + cacheParam;
}
return url;
}
}
var url = plugin.baseUrl + '/' + path;
/* eslint-enable indent */
if (addCacheParam) {
url += url.indexOf('?') === -1 ? '?' : '&';
url += 'v=' + cacheParam;
}
return url;
};
return new PluginManager();
});
export default new PluginManager();

View file

@ -118,7 +118,7 @@ function reload(context, programId, serverId, refreshRecordingStateOnly) {
function executeCloseAction(action, programId, serverId) {
if (action === 'play') {
import('playbackManager').then(({default: playbackManager}) => {
import('playbackManager').then(({ default: playbackManager }) => {
const apiClient = connectionManager.getApiClient(serverId);
apiClient.getLiveTvProgram(programId, apiClient.getCurrentUserId()).then(function (item) {
@ -138,7 +138,7 @@ function showEditor(itemId, serverId) {
loading.show();
import('text!./recordingcreator.template.html').then(({default: template}) => {
import('text!./recordingcreator.template.html').then(({ default: template }) => {
const dialogOptions = {
removeOnClose: true,
scrollY: false

View file

@ -1,151 +1,155 @@
define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'connectionManager', 'require', 'loading', 'scrollHelper', 'imageLoader', 'scrollStyles', 'emby-button', 'emby-collapse', 'emby-input', 'paper-icon-button-light', 'css!./../formdialog', 'css!./recordingcreator', 'material-icons', 'flexStyles'], function (dialogHelper, globalize, layoutManager, mediaInfo, appHost, connectionManager, require, loading, scrollHelper, imageLoader) {
'use strict';
import dialogHelper from 'dialogHelper';
import globalize from 'globalize';
import layoutManager from 'layoutManager';
import connectionManager from 'connectionManager';
import loading from 'loading';
import scrollHelper from 'scrollHelper';
import 'scrollStyles';
import 'emby-button';
import 'emby-collapse';
import 'emby-input';
import 'paper-icon-button-light';
import 'css!./../formdialog';
import 'css!./recordingcreator';
import 'material-icons';
import 'flexStyles';
scrollHelper = scrollHelper.default || scrollHelper;
loading = loading.default || loading;
layoutManager = layoutManager.default || layoutManager;
let currentDialog;
let recordingDeleted = false;
let currentItemId;
let currentServerId;
let currentResolve;
var currentDialog;
var recordingDeleted = false;
var currentItemId;
var currentServerId;
var currentResolve;
function deleteTimer(apiClient, timerId) {
return import('recordingHelper').then(({ default: recordingHelper }) => {
recordingHelper.cancelTimerWithConfirmation(timerId, apiClient.serverId());
});
}
function deleteTimer(apiClient, timerId) {
return new Promise(function (resolve, reject) {
require(['recordingHelper'], function (recordingHelper) {
recordingHelper = recordingHelper.default || recordingHelper;
function renderTimer(context, item, apiClient) {
context.querySelector('#txtPrePaddingMinutes').value = item.PrePaddingSeconds / 60;
context.querySelector('#txtPostPaddingMinutes').value = item.PostPaddingSeconds / 60;
recordingHelper.cancelTimerWithConfirmation(timerId, apiClient.serverId()).then(resolve, reject);
});
loading.hide();
}
function closeDialog(isDeleted) {
recordingDeleted = isDeleted;
dialogHelper.close(currentDialog);
}
function onSubmit(e) {
const form = this;
const apiClient = connectionManager.getApiClient(currentServerId);
apiClient.getLiveTvTimer(currentItemId).then(function (item) {
item.PrePaddingSeconds = form.querySelector('#txtPrePaddingMinutes').value * 60;
item.PostPaddingSeconds = form.querySelector('#txtPostPaddingMinutes').value * 60;
apiClient.updateLiveTvTimer(item).then(currentResolve);
});
e.preventDefault();
// Disable default form submission
return false;
}
function init(context) {
context.querySelector('.btnCancel').addEventListener('click', function () {
closeDialog(false);
});
context.querySelector('.btnCancelRecording').addEventListener('click', function () {
const apiClient = connectionManager.getApiClient(currentServerId);
deleteTimer(apiClient, currentItemId).then(function () {
closeDialog(true);
});
}
});
function renderTimer(context, item, apiClient) {
context.querySelector('#txtPrePaddingMinutes').value = item.PrePaddingSeconds / 60;
context.querySelector('#txtPostPaddingMinutes').value = item.PostPaddingSeconds / 60;
context.querySelector('form').addEventListener('submit', onSubmit);
}
function reload(context, id) {
loading.show();
currentItemId = id;
const apiClient = connectionManager.getApiClient(currentServerId);
apiClient.getLiveTvTimer(id).then(function (result) {
renderTimer(context, result, apiClient);
loading.hide();
}
});
}
function closeDialog(isDeleted) {
recordingDeleted = isDeleted;
dialogHelper.close(currentDialog);
}
function onSubmit(e) {
var form = this;
var apiClient = connectionManager.getApiClient(currentServerId);
apiClient.getLiveTvTimer(currentItemId).then(function (item) {
item.PrePaddingSeconds = form.querySelector('#txtPrePaddingMinutes').value * 60;
item.PostPaddingSeconds = form.querySelector('#txtPostPaddingMinutes').value * 60;
apiClient.updateLiveTvTimer(item).then(currentResolve);
});
e.preventDefault();
// Disable default form submission
return false;
}
function init(context) {
context.querySelector('.btnCancel').addEventListener('click', function () {
closeDialog(false);
});
context.querySelector('.btnCancelRecording').addEventListener('click', function () {
var apiClient = connectionManager.getApiClient(currentServerId);
deleteTimer(apiClient, currentItemId).then(function () {
closeDialog(true);
});
});
context.querySelector('form').addEventListener('submit', onSubmit);
}
function reload(context, id) {
function showEditor(itemId, serverId, options) {
return new Promise(function (resolve, reject) {
recordingDeleted = false;
currentServerId = serverId;
loading.show();
currentItemId = id;
options = options || {};
currentResolve = resolve;
var apiClient = connectionManager.getApiClient(currentServerId);
apiClient.getLiveTvTimer(id).then(function (result) {
renderTimer(context, result, apiClient);
loading.hide();
});
}
import('text!./recordingeditor.template.html').then(({default: template}) => {
const dialogOptions = {
removeOnClose: true,
scrollY: false
};
function showEditor(itemId, serverId, options) {
return new Promise(function (resolve, reject) {
recordingDeleted = false;
currentServerId = serverId;
loading.show();
options = options || {};
currentResolve = resolve;
if (layoutManager.tv) {
dialogOptions.size = 'fullscreen';
}
require(['text!./recordingeditor.template.html'], function (template) {
var dialogOptions = {
removeOnClose: true,
scrollY: false
};
const dlg = dialogHelper.createDialog(dialogOptions);
if (layoutManager.tv) {
dialogOptions.size = 'fullscreen';
dlg.classList.add('formDialog');
dlg.classList.add('recordingDialog');
if (!layoutManager.tv) {
dlg.style['min-width'] = '20%';
dlg.classList.add('dialog-fullscreen-lowres');
}
let html = '';
html += globalize.translateHtml(template, 'core');
dlg.innerHTML = html;
if (options.enableCancel === false) {
dlg.querySelector('.formDialogFooter').classList.add('hide');
}
currentDialog = dlg;
dlg.addEventListener('closing', function () {
if (!recordingDeleted) {
dlg.querySelector('.btnSubmit').click();
}
var dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog');
dlg.classList.add('recordingDialog');
if (!layoutManager.tv) {
dlg.style['min-width'] = '20%';
dlg.classList.add('dialog-fullscreen-lowres');
}
var html = '';
html += globalize.translateHtml(template, 'core');
dlg.innerHTML = html;
if (options.enableCancel === false) {
dlg.querySelector('.formDialogFooter').classList.add('hide');
}
currentDialog = dlg;
dlg.addEventListener('closing', function () {
if (!recordingDeleted) {
dlg.querySelector('.btnSubmit').click();
}
});
dlg.addEventListener('close', function () {
if (recordingDeleted) {
resolve({
updated: true,
deleted: true
});
}
});
if (layoutManager.tv) {
scrollHelper.centerFocus.on(dlg.querySelector('.formDialogContent'), false);
}
init(dlg);
reload(dlg, itemId);
dialogHelper.open(dlg);
});
});
}
return {
show: showEditor
};
});
dlg.addEventListener('close', function () {
if (recordingDeleted) {
resolve({
updated: true,
deleted: true
});
}
});
if (layoutManager.tv) {
scrollHelper.centerFocus.on(dlg.querySelector('.formDialogContent'), false);
}
init(dlg);
reload(dlg, itemId);
dialogHelper.open(dlg);
});
});
}
export default {
show: showEditor
};

View file

@ -1,223 +1,126 @@
define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loading', 'apphost', 'dom', 'recordingHelper', 'events', 'paper-icon-button-light', 'emby-button', 'css!./recordingfields', 'flexStyles'], function (globalize, connectionManager, serverNotifications, require, loading, appHost, dom, recordingHelper, events) {
'use strict';
import globalize from 'globalize';
import connectionManager from 'connectionManager';
import serverNotifications from 'serverNotifications';
import loading from 'loading';
import dom from 'dom';
import recordingHelper from 'recordingHelper';
import events from 'events';
import 'paper-icon-button-light';
import 'emby-button';
import 'css!./recordingfields';
import 'flexStyles';
serverNotifications = serverNotifications.default || serverNotifications;
recordingHelper = recordingHelper.default || recordingHelper;
loading = loading.default || loading;
/*eslint prefer-const: "error"*/
function loadData(parent, program, apiClient) {
if (program.IsSeries) {
parent.querySelector('.recordSeriesContainer').classList.remove('hide');
function loadData(parent, program, apiClient) {
if (program.IsSeries) {
parent.querySelector('.recordSeriesContainer').classList.remove('hide');
} else {
parent.querySelector('.recordSeriesContainer').classList.add('hide');
}
if (program.SeriesTimerId) {
parent.querySelector('.btnManageSeriesRecording').classList.remove('hide');
parent.querySelector('.seriesRecordingButton .recordingIcon').classList.add('recordingIcon-active');
parent.querySelector('.seriesRecordingButton .buttonText').innerHTML = globalize.translate('CancelSeries');
} else {
parent.querySelector('.btnManageSeriesRecording').classList.add('hide');
parent.querySelector('.seriesRecordingButton .recordingIcon').classList.remove('recordingIcon-active');
parent.querySelector('.seriesRecordingButton .buttonText').innerHTML = globalize.translate('RecordSeries');
}
if (program.TimerId && program.Status !== 'Cancelled') {
parent.querySelector('.btnManageRecording').classList.remove('hide');
parent.querySelector('.singleRecordingButton .recordingIcon').classList.add('recordingIcon-active');
if (program.Status === 'InProgress') {
parent.querySelector('.singleRecordingButton .buttonText').innerHTML = globalize.translate('StopRecording');
} else {
parent.querySelector('.recordSeriesContainer').classList.add('hide');
parent.querySelector('.singleRecordingButton .buttonText').innerHTML = globalize.translate('DoNotRecord');
}
} else {
parent.querySelector('.btnManageRecording').classList.add('hide');
parent.querySelector('.singleRecordingButton .recordingIcon').classList.remove('recordingIcon-active');
parent.querySelector('.singleRecordingButton .buttonText').innerHTML = globalize.translate('Record');
}
}
if (program.SeriesTimerId) {
parent.querySelector('.btnManageSeriesRecording').classList.remove('hide');
parent.querySelector('.seriesRecordingButton .recordingIcon').classList.add('recordingIcon-active');
parent.querySelector('.seriesRecordingButton .buttonText').innerHTML = globalize.translate('CancelSeries');
} else {
parent.querySelector('.btnManageSeriesRecording').classList.add('hide');
parent.querySelector('.seriesRecordingButton .recordingIcon').classList.remove('recordingIcon-active');
parent.querySelector('.seriesRecordingButton .buttonText').innerHTML = globalize.translate('RecordSeries');
function fetchData(instance) {
const options = instance.options;
const apiClient = connectionManager.getApiClient(options.serverId);
options.parent.querySelector('.recordingFields').classList.remove('hide');
return apiClient.getLiveTvProgram(options.programId, apiClient.getCurrentUserId()).then(function (program) {
instance.TimerId = program.TimerId;
instance.Status = program.Status;
instance.SeriesTimerId = program.SeriesTimerId;
loadData(options.parent, program, apiClient);
});
}
function onTimerChangedExternally(e, apiClient, data) {
const options = this.options;
let refresh = false;
if (data.Id) {
if (this.TimerId === data.Id) {
refresh = true;
}
if (program.TimerId && program.Status !== 'Cancelled') {
parent.querySelector('.btnManageRecording').classList.remove('hide');
parent.querySelector('.singleRecordingButton .recordingIcon').classList.add('recordingIcon-active');
if (program.Status === 'InProgress') {
parent.querySelector('.singleRecordingButton .buttonText').innerHTML = globalize.translate('StopRecording');
} else {
parent.querySelector('.singleRecordingButton .buttonText').innerHTML = globalize.translate('DoNotRecord');
}
} else {
parent.querySelector('.btnManageRecording').classList.add('hide');
parent.querySelector('.singleRecordingButton .recordingIcon').classList.remove('recordingIcon-active');
parent.querySelector('.singleRecordingButton .buttonText').innerHTML = globalize.translate('Record');
}
if (data.ProgramId && options) {
if (options.programId === data.ProgramId) {
refresh = true;
}
}
function fetchData(instance) {
var options = instance.options;
var apiClient = connectionManager.getApiClient(options.serverId);
options.parent.querySelector('.recordingFields').classList.remove('hide');
return apiClient.getLiveTvProgram(options.programId, apiClient.getCurrentUserId()).then(function (program) {
instance.TimerId = program.TimerId;
instance.Status = program.Status;
instance.SeriesTimerId = program.SeriesTimerId;
loadData(options.parent, program, apiClient);
});
if (refresh) {
this.refresh();
}
}
function onTimerChangedExternally(e, apiClient, data) {
var options = this.options;
var refresh = false;
function onSeriesTimerChangedExternally(e, apiClient, data) {
const options = this.options;
let refresh = false;
if (data.Id) {
if (this.TimerId === data.Id) {
refresh = true;
}
if (data.Id) {
if (this.SeriesTimerId === data.Id) {
refresh = true;
}
if (data.ProgramId && options) {
if (options.programId === data.ProgramId) {
refresh = true;
}
}
if (refresh) {
this.refresh();
}
if (data.ProgramId && options) {
if (options.programId === data.ProgramId) {
refresh = true;
}
}
function onSeriesTimerChangedExternally(e, apiClient, data) {
var options = this.options;
var refresh = false;
if (data.Id) {
if (this.SeriesTimerId === data.Id) {
refresh = true;
}
}
if (data.ProgramId && options) {
if (options.programId === data.ProgramId) {
refresh = true;
}
}
if (refresh) {
this.refresh();
}
if (refresh) {
this.refresh();
}
}
function RecordingEditor(options) {
class RecordingEditor {
constructor(options) {
this.options = options;
this.embed();
var timerChangedHandler = onTimerChangedExternally.bind(this);
const timerChangedHandler = onTimerChangedExternally.bind(this);
this.timerChangedHandler = timerChangedHandler;
events.on(serverNotifications, 'TimerCreated', timerChangedHandler);
events.on(serverNotifications, 'TimerCancelled', timerChangedHandler);
var seriesTimerChangedHandler = onSeriesTimerChangedExternally.bind(this);
const seriesTimerChangedHandler = onSeriesTimerChangedExternally.bind(this);
this.seriesTimerChangedHandler = seriesTimerChangedHandler;
events.on(serverNotifications, 'SeriesTimerCreated', seriesTimerChangedHandler);
events.on(serverNotifications, 'SeriesTimerCancelled', seriesTimerChangedHandler);
}
function onManageRecordingClick(e) {
var options = this.options;
if (!this.TimerId || this.Status === 'Cancelled') {
return;
}
var self = this;
require(['recordingEditor'], function (recordingEditor) {
recordingEditor.show(self.TimerId, options.serverId, {
enableCancel: false
}).then(function () {
self.changed = true;
});
});
}
function onManageSeriesRecordingClick(e) {
var options = this.options;
if (!this.SeriesTimerId) {
return;
}
var self = this;
require(['seriesRecordingEditor'], function (seriesRecordingEditor) {
seriesRecordingEditor.show(self.SeriesTimerId, options.serverId, {
enableCancel: false
}).then(function () {
self.changed = true;
});
});
}
function onRecordChange(e) {
this.changed = true;
var self = this;
var options = this.options;
var apiClient = connectionManager.getApiClient(options.serverId);
var button = dom.parentWithTag(e.target, 'BUTTON');
var isChecked = !button.querySelector('.material-icons').classList.contains('recordingIcon-active');
var hasEnabledTimer = this.TimerId && this.Status !== 'Cancelled';
if (isChecked) {
if (!hasEnabledTimer) {
loading.show();
recordingHelper.createRecording(apiClient, options.programId, false).then(function () {
events.trigger(self, 'recordingchanged');
fetchData(self);
loading.hide();
});
}
} else {
if (hasEnabledTimer) {
loading.show();
recordingHelper.cancelTimer(apiClient, this.TimerId, true).then(function () {
events.trigger(self, 'recordingchanged');
fetchData(self);
loading.hide();
});
}
}
}
function sendToast(msg) {
require(['toast'], function (toast) {
toast(msg);
});
}
function onRecordSeriesChange(e) {
this.changed = true;
var self = this;
var options = this.options;
var apiClient = connectionManager.getApiClient(options.serverId);
var button = dom.parentWithTag(e.target, 'BUTTON');
var isChecked = !button.querySelector('.material-icons').classList.contains('recordingIcon-active');
if (isChecked) {
options.parent.querySelector('.recordSeriesContainer').classList.remove('hide');
if (!this.SeriesTimerId) {
var promise = this.TimerId ?
recordingHelper.changeRecordingToSeries(apiClient, this.TimerId, options.programId) :
recordingHelper.createRecording(apiClient, options.programId, true);
promise.then(function () {
fetchData(self);
});
}
} else {
if (this.SeriesTimerId) {
apiClient.cancelLiveTvSeriesTimer(this.SeriesTimerId).then(function () {
sendToast(globalize.translate('RecordingCancelled'));
fetchData(self);
});
}
}
}
RecordingEditor.prototype.embed = function () {
var self = this;
embed() {
const self = this;
return new Promise(function (resolve, reject) {
require(['text!./recordingfields.template.html'], function (template) {
var options = self.options;
var context = options.parent;
import('text!./recordingfields.template.html').then(({default: template}) => {
const options = self.options;
const context = options.parent;
context.innerHTML = globalize.translateHtml(template, 'core');
context.querySelector('.singleRecordingButton').addEventListener('click', onRecordChange.bind(self));
@ -228,29 +131,134 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa
fetchData(self).then(resolve);
});
});
};
}
RecordingEditor.prototype.hasChanged = function () {
hasChanged() {
return this.changed;
};
}
RecordingEditor.prototype.refresh = function () {
refresh() {
fetchData(this);
};
}
RecordingEditor.prototype.destroy = function () {
var timerChangedHandler = this.timerChangedHandler;
destroy() {
const timerChangedHandler = this.timerChangedHandler;
this.timerChangedHandler = null;
events.off(serverNotifications, 'TimerCreated', timerChangedHandler);
events.off(serverNotifications, 'TimerCancelled', timerChangedHandler);
var seriesTimerChangedHandler = this.seriesTimerChangedHandler;
const seriesTimerChangedHandler = this.seriesTimerChangedHandler;
this.seriesTimerChangedHandler = null;
events.off(serverNotifications, 'SeriesTimerCreated', seriesTimerChangedHandler);
events.off(serverNotifications, 'SeriesTimerCancelled', seriesTimerChangedHandler);
};
}
}
return RecordingEditor;
});
function onManageRecordingClick(e) {
const options = this.options;
if (!this.TimerId || this.Status === 'Cancelled') {
return;
}
const self = this;
import('recordingEditor').then(({default: recordingEditor}) => {
recordingEditor.show(self.TimerId, options.serverId, {
enableCancel: false
}).then(function () {
self.changed = true;
});
});
}
function onManageSeriesRecordingClick(e) {
const options = this.options;
if (!this.SeriesTimerId) {
return;
}
const self = this;
import('seriesRecordingEditor').then(({default: seriesRecordingEditor}) => {
seriesRecordingEditor.show(self.SeriesTimerId, options.serverId, {
enableCancel: false
}).then(function () {
self.changed = true;
});
});
}
function onRecordChange(e) {
this.changed = true;
const self = this;
const options = this.options;
const apiClient = connectionManager.getApiClient(options.serverId);
const button = dom.parentWithTag(e.target, 'BUTTON');
const isChecked = !button.querySelector('.material-icons').classList.contains('recordingIcon-active');
const hasEnabledTimer = this.TimerId && this.Status !== 'Cancelled';
if (isChecked) {
if (!hasEnabledTimer) {
loading.show();
recordingHelper.createRecording(apiClient, options.programId, false).then(function () {
events.trigger(self, 'recordingchanged');
fetchData(self);
loading.hide();
});
}
} else {
if (hasEnabledTimer) {
loading.show();
recordingHelper.cancelTimer(apiClient, this.TimerId, true).then(function () {
events.trigger(self, 'recordingchanged');
fetchData(self);
loading.hide();
});
}
}
}
function sendToast(msg) {
import('toast').then(({default: toast}) => {
toast(msg);
});
}
function onRecordSeriesChange(e) {
this.changed = true;
const self = this;
const options = this.options;
const apiClient = connectionManager.getApiClient(options.serverId);
const button = dom.parentWithTag(e.target, 'BUTTON');
const isChecked = !button.querySelector('.material-icons').classList.contains('recordingIcon-active');
if (isChecked) {
options.parent.querySelector('.recordSeriesContainer').classList.remove('hide');
if (!this.SeriesTimerId) {
const promise = this.TimerId ?
recordingHelper.changeRecordingToSeries(apiClient, this.TimerId, options.programId) :
recordingHelper.createRecording(apiClient, options.programId, true);
promise.then(function () {
fetchData(self);
});
}
} else {
if (this.SeriesTimerId) {
apiClient.cancelLiveTvSeriesTimer(this.SeriesTimerId).then(function () {
sendToast(globalize.translate('RecordingCancelled'));
fetchData(self);
});
}
}
}
export default RecordingEditor;

View file

@ -66,7 +66,7 @@ function showSubtitleMenu(context, player, button, item) {
});
menuItems.unshift({
id: -1,
name: globalize.translate('ButtonOff'),
name: globalize.translate('Off'),
selected: currentIndex == null
});

View file

@ -2,7 +2,7 @@ define(function () {
'use strict';
// hack to work around the server's auto-redirection feature
var addRedirectPrevention = self.dashboardVersion != null && self.Dashboard && !self.AppInfo.isNativeApp;
var addRedirectPrevention = window.dashboardVersion != null && window.Dashboard && !window.AppInfo.isNativeApp;
return {

View file

@ -26,7 +26,7 @@
});
}
self.addEventListener('notificationclick', function (event) {
window.addEventListener('notificationclick', function (event) {
var notification = event.notification;
notification.close();