-
${HeadersFolders}
+
${Folders}
diff --git a/src/components/mediainfo/mediainfo.js b/src/components/mediainfo/mediainfo.js
index 53982040b8..1d78d490a2 100644
--- a/src/components/mediainfo/mediainfo.js
+++ b/src/components/mediainfo/mediainfo.js
@@ -9,7 +9,6 @@ import 'programStyles';
import 'emby-button';
/* eslint-disable indent */
-
function getTimerIndicator(item) {
let status;
@@ -208,7 +207,7 @@ import 'emby-button';
});
} else if (item.IsSeries && !item.IsRepeat) {
miscInfo.push({
- html: `
${globalize.translate('AttributeNew')}
`
+ html: `
${globalize.translate('New')}
`
});
} else if (item.IsSeries && item.IsRepeat) {
miscInfo.push({
diff --git a/src/components/multiSelect/multiSelect.js b/src/components/multiSelect/multiSelect.js
index d922aee84a..fdce40ab86 100644
--- a/src/components/multiSelect/multiSelect.js
+++ b/src/components/multiSelect/multiSelect.js
@@ -198,7 +198,7 @@ import 'css!./multiSelect';
if (user.Policy.EnableContentDownloading && appHost.supports('filedownload')) {
menuItems.push({
- name: globalize.translate('ButtonDownload'),
+ name: globalize.translate('Download'),
id: 'download',
icon: 'file_download'
});
diff --git a/src/components/packageManager.js b/src/components/packageManager.js
index 936f5a4029..2a15a14f34 100644
--- a/src/components/packageManager.js
+++ b/src/components/packageManager.js
@@ -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();
diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js
index 8502b551af..3b4099d540 100644
--- a/src/components/playback/playbackmanager.js
+++ b/src/components/playback/playbackmanager.js
@@ -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;
diff --git a/src/components/playback/playersettingsmenu.js b/src/components/playback/playersettingsmenu.js
index 71dd7a86ff..cd227afcb4 100644
--- a/src/components/playback/playersettingsmenu.js
+++ b/src/components/playback/playersettingsmenu.js
@@ -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':
diff --git a/src/components/pluginManager.js b/src/components/pluginManager.js
index df4a0c42b7..55a5c230ff 100644
--- a/src/components/pluginManager.js
+++ b/src/components/pluginManager.js
@@ -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();
diff --git a/src/components/recordingcreator/recordingcreator.js b/src/components/recordingcreator/recordingcreator.js
index f4ae64977d..9cb4e41d2e 100644
--- a/src/components/recordingcreator/recordingcreator.js
+++ b/src/components/recordingcreator/recordingcreator.js
@@ -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
diff --git a/src/components/recordingcreator/recordingeditor.js b/src/components/recordingcreator/recordingeditor.js
index e9aca85347..096ea3b62c 100644
--- a/src/components/recordingcreator/recordingeditor.js
+++ b/src/components/recordingcreator/recordingeditor.js
@@ -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
+};
diff --git a/src/components/recordingcreator/recordingfields.js b/src/components/recordingcreator/recordingfields.js
index c93200d053..d9d7c0098c 100644
--- a/src/components/recordingcreator/recordingfields.js
+++ b/src/components/recordingcreator/recordingfields.js
@@ -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;
diff --git a/src/components/remotecontrol/remotecontrol.js b/src/components/remotecontrol/remotecontrol.js
index 6048c918c7..3216241e7a 100644
--- a/src/components/remotecontrol/remotecontrol.js
+++ b/src/components/remotecontrol/remotecontrol.js
@@ -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
});
diff --git a/src/components/subtitlesettings/subtitlesettings.template.html b/src/components/subtitlesettings/subtitlesettings.template.html
index af9139188c..2884b26efd 100644
--- a/src/components/subtitlesettings/subtitlesettings.template.html
+++ b/src/components/subtitlesettings/subtitlesettings.template.html
@@ -14,7 +14,7 @@
-
+
${DefaultSubtitlesHelp}
${SmartSubtitlesHelp}
diff --git a/src/controllers/dashboard/dashboard.js b/src/controllers/dashboard/dashboard.js
index a36aa3ce68..a1ce7f489e 100644
--- a/src/controllers/dashboard/dashboard.js
+++ b/src/controllers/dashboard/dashboard.js
@@ -737,7 +737,7 @@ import 'emby-itemscontainer';
shutdown: function (btn) {
import('confirm').then(({default: confirm}) => {
confirm({
- title: globalize.translate('HeaderShutdown'),
+ title: globalize.translate('ButtonShutdown'),
text: globalize.translate('MessageConfirmShutdown'),
confirmText: globalize.translate('ButtonShutdown'),
primary: 'delete'
diff --git a/src/controllers/dashboard/devices/device.html b/src/controllers/dashboard/devices/device.html
index 4d8fb86537..aec73db008 100644
--- a/src/controllers/dashboard/devices/device.html
+++ b/src/controllers/dashboard/devices/device.html
@@ -9,7 +9,7 @@