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

Merge remote-tracking branch 'upstream/master' into webpack

This commit is contained in:
Bill Thornton 2019-08-06 11:16:32 -04:00
commit 4b5aec42f7
134 changed files with 4360 additions and 3712 deletions

9
.editorconfig Normal file
View file

@ -0,0 +1,9 @@
root = true
[*]
indent_style = space
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf

View file

@ -1,20 +0,0 @@
---
name: Enhancement request
about: Suggest an modification to an existing feature
title: ''
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
**Describe the solution you'd like**
<!-- A clear and concise description of what you want to happen. -->
**Describe alternatives you've considered**
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
**Additional context**
<!-- Add any other context or screenshots about the feature request here. -->

View file

@ -1,14 +0,0 @@
---
name: Feature request
about: Suggest a new feature
title: ''
labels: feature
assignees: ''
---
**Describe the feature you'd like**
<!-- A clear and concise description of what you want to happen. -->
**Additional context**
<!-- Add any other context or screenshots about the feature request here. -->

19
.github/stale.yml vendored Normal file
View file

@ -0,0 +1,19 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- regression
- future
- feature
- enhancement
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
Issues go stale after 60d of inactivity. Mark the issue as fresh by adding a comment or commit. Stale issues close after an additional 7d of inactivity.
If this issue is safe to close now please do so.
If you have any questions you can reach us on [Matrix or Social Media](https://jellyfin.readthedocs.io/en/latest/getting-help/).
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

View file

@ -23,6 +23,8 @@
- [thornbill](https://github.com/thornbill)
- [redSpoutnik](https://github.com/redSpoutnik)
- [DrPandemic](https://github.com/drpandemic)
- [Oddstr13](https://github.com/oddstr13)
- [petermcneil](https://github.com/petermcneil)
# Emby Contributors

View file

@ -1,4 +1,4 @@
<div id="serverSecurityPage" data-role="page" class="page type-interior advancedConfigurationPage withTabs fullWidthContent">
<div id="apiKeysPage" data-role="page" class="page type-interior advancedConfigurationPage fullWidthContent">
<div>
<div class="content-primary">
<div class="detailSectionHeader">

View file

@ -1190,15 +1190,13 @@ define(["events", "appStorage"], function(events, appStorage) {
data: JSON.stringify(info),
contentType: "application/json"
})
}, ApiClient.prototype.createUser = function(name) {
}, ApiClient.prototype.createUser = function(user) {
var url = this.getUrl("Users/New");
return this.ajax({
type: "POST",
url: url,
data: {
Name: name
},
dataType: "json"
data: JSON.stringify(user),
contentType: "application/json"
})
}, ApiClient.prototype.updateUser = function(user) {
if (!user) throw new Error("null user");

View file

@ -13,7 +13,7 @@ define(["events", "appStorage"], function(events, appStorage) {
}
function Credentials(key) {
this.key = key || "servercredentials3"
this.key = key || "jellyfin_credentials"
}
return Credentials.prototype.clear = function() {
this._credentials = null, appStorage.removeItem(this.key)

View file

@ -41,10 +41,6 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'browser', 'dom', 'emby-bu
var windowHeight = windowSize.innerHeight;
var windowWidth = windowSize.innerWidth;
if (windowWidth < 600 || windowHeight < 600) {
return null;
}
var pos = getOffsets([options.positionTo])[0];
if (options.positionY !== 'top') {

View file

@ -4,14 +4,21 @@ define(["events", "globalize", "dom", "datetime", "userSettings", "serverNotific
function getEntryHtml(entry, apiClient) {
var html = "";
html += '<div class="listItem listItem-border">';
var color = "Error" == entry.Severity || "Fatal" == entry.Severity || "Warn" == entry.Severity ? "#cc0000" : "#00a4dc";
var color = "#00a4dc";
var icon = "notifications";
if ("Error" == entry.Severity || "Fatal" == entry.Severity || "Warn" == entry.Severity) {
color = "#cc0000";
icon = "notification_important";
}
if (entry.UserId && entry.UserPrimaryImageTag) {
html += '<i class="listItemIcon md-icon" style="width:2em!important;height:2em!important;padding:0;color:transparent;background-color:' + color + ";background-image:url('" + apiClient.getUserImageUrl(entry.UserId, {
type: "Primary",
tag: entry.UserPrimaryImageTag,
height: 40
}) + "');background-repeat:no-repeat;background-position:center center;background-size: cover;\">dvr</i>"
} else html += '<i class="listItemIcon md-icon" style="background-color:' + color + '">dvr</i>';
} else {
html += '<i class="listItemIcon md-icon" style="background-color:' + color + '">' + icon + '</i>';
}
html += '<div class="listItemBody three-line">', html += '<div class="listItemBodyText">', html += entry.Name, html += "</div>", html += '<div class="listItemBodyText secondary">';
var date = datetime.parseISO8601Date(entry.Date, !0);
return html += datetime.toLocaleString(date).toLowerCase(), html += "</div>", html += '<div class="listItemBodyText secondary listItemBodyText-nowrap">', html += entry.ShortOverview || "", html += "</div>", html += "</div>", entry.Overview && (html += '<button type="button" is="paper-icon-button-light" class="btnEntryInfo" data-id="' + entry.Id + '" title="' + globalize.translate("Info") + '"><i class="md-icon">info</i></button>'), html += "</div>"

View file

@ -274,7 +274,9 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
features.push("displaylanguage");
features.push("otherapppromotions");
features.push("targetblank"); // allows users to connect to more than one server
features.push("displaymode");
features.push("targetblank");
// allows users to connect to more than one server
//features.push("multiserver");
if (!browser.orsay && !browser.tizen && !browser.msie && (browser.firefox || browser.ps4 || browser.edge || cueSupported())) {
@ -310,9 +312,11 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
var deviceId;
var deviceName;
var appName = "Jellyfin Web";
var appVersion = "10.3.6";
var visibilityChange;
var visibilityState;
var appVersion = window.dashboardVersion || "3.0";
var appHost = {
getWindowState: function () {
return document.windowState || "Normal";
@ -357,9 +361,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
}
deviceName = getDeviceName();
return getDeviceId().then(function (resolvedDeviceId) {
deviceId = resolvedDeviceId;
});
deviceId = getDeviceId();
},
deviceName: function () {
return window.NativeShell ? window.NativeShell.AppHost.deviceName() : deviceName;
@ -368,7 +370,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
return window.NativeShell ? window.NativeShell.AppHost.deviceId() : deviceId;
},
appName: function () {
return window.NativeShell ? window.NativeShell.AppHost.appName() : "Jellyfin Web";
return window.NativeShell ? window.NativeShell.AppHost.appName() : appName;
},
appVersion: function () {
return window.NativeShell ? window.NativeShell.AppHost.appVersion() : appVersion;
@ -388,53 +390,6 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
var att = scalable ? "width=device-width, initial-scale=1, minimum-scale=1, user-scalable=yes" : "width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no";
document.querySelector("meta[name=viewport]").setAttribute("content", att);
}
},
deviceIconUrl: function () {
if (browser.edgeUwp) {
return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/windowsrt.png";
}
if (browser.opera || browser.operaTv) {
return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/opera.png";
}
if (browser.orsay || browser.tizen) {
return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/samsungtv.png";
}
if (browser.web0s) {
return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/lgtv.png";
}
if (browser.ps4) {
return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/ps4.png";
}
if (browser.chromecast) {
return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/chromecast.png";
}
if (browser.chrome) {
return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/chrome.png";
}
if (browser.edge) {
return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/edge.png";
}
if (browser.firefox) {
return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/firefox.png";
}
if (browser.msie) {
return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/internetexplorer.png";
}
if (browser.safari) {
return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/safari.png";
}
return "https://github.com/MediaBrowser/Emby.Resources/raw/master/images/devices/html5.png";
}
};
var doc = self.document;

View file

@ -32,6 +32,18 @@ button {
.itemsContainer {
display: flex;
margin-left: -0.6em;
margin-right: -0.6em;
}
/* TODO replace this with a proper fix */
/* doesnt work on mobile devices */
/* negative margin fixes annoying misalignment with cards and title */
@media all and (max-width:50em) {
.itemsContainer {
margin-left: 0;
margin-right: 0;
}
}
.vertical-list {
@ -77,7 +89,7 @@ button {
.cardBox {
padding: 0 !important;
margin: .42em;
margin: 0.6em;
transition: none;
border: 0 solid transparent;
/* These both are needed in case cardBox is a button */
@ -86,25 +98,10 @@ button {
contain: layout style;
}
/*.cardBox-withfocuscontent {
margin: .68em;
}*/
@media (min-width: 50em) {
.cardBox {
margin: .9em;
}
}
.cardBox-withfocuscontent-large {
margin: .4em;
}
/*.card-focuscontent {
border: .12em solid transparent;
}*/
.card-focuscontent-large {
border: .5em solid transparent;
}
@ -123,7 +120,6 @@ button {
}
@media (max-width: 50em) {
.cardBox-bottompadded {
margin-bottom: 1.2em !important;
}
@ -213,9 +209,9 @@ button {
font-size: inherit;
}
.cardContent-button:not(.defaultCardBackground) {
.cardContent-button:not(.defaultCardBackground) {
background-color: transparent;
}
}
.visualCardBox .cardContent {
border-bottom-left-radius: 0;
@ -371,9 +367,9 @@ button {
justify-content: center;*/
}
.textActionButton:hover {
.textActionButton:hover {
text-decoration: underline;
}
}
.cardImageIcon {
font-size: 5em;

View file

@ -1,5 +1,5 @@
define(['datetime', 'imageLoader', 'connectionManager', 'itemHelper', 'focusManager', 'indicators', 'globalize', 'layoutManager', 'apphost', 'dom', 'browser', 'playbackManager', 'itemShortcuts', 'css!./card', 'paper-icon-button-light', 'programStyles'],
function (datetime, imageLoader, connectionManager, itemHelper, focusManager, indicators, globalize, layoutManager, appHost, dom, browser, playbackManager, itemShortcuts) {
define(['datetime', 'imageLoader', 'connectionManager', 'itemHelper', 'focusManager', 'indicators', 'globalize', 'layoutManager', 'apphost', 'dom', 'browser', 'playbackManager', 'itemShortcuts', 'scripts/imagehelper', 'css!./card', 'paper-icon-button-light', 'programStyles'],
function (datetime, imageLoader, connectionManager, itemHelper, focusManager, indicators, globalize, layoutManager, appHost, dom, browser, playbackManager, itemShortcuts, imageHelper) {
'use strict';
var devicePixelRatio = window.devicePixelRatio || 1;
@ -1546,16 +1546,8 @@ define(['datetime', 'imageLoader', 'connectionManager', 'itemHelper', 'focusMana
}
function getCardDefaultText(item, options) {
var collectionType = item.CollectionType;
if (collectionType === 'livetv') {
return '<i class="cardImageIcon md-icon">&#xE1B2;</i>';
}
if (collectionType === 'homevideos' || collectionType === 'photos') {
return '<i class="cardImageIcon md-icon">&#xE412;</i>';
}
if (collectionType === 'music') {
return '<i class="cardImageIcon md-icon">&#xE310;</i>';
if (item.CollectionType) {
return '<i class="cardImageIcon md-icon">' + imageHelper.getLibraryIcon(item.CollectionType) + '</i>'
}
if (item.Type === 'MusicAlbum') {
return '<i class="cardImageIcon md-icon">&#xE019;</i>';

View file

@ -28,15 +28,18 @@ define(["dialogHelper", "loading", "connectionManager", "globalize", "actionshee
function onChannelsElementClick(e) {
var btnMap = parentWithClass(e.target, "btnMap");
if (btnMap) {
var channelId = btnMap.getAttribute("data-id"),
providerChannelId = btnMap.getAttribute("data-providerid"),
menuItems = currentMappingOptions.ProviderChannels.map(function(m) {
var channelId = btnMap.getAttribute("data-id");
var providerChannelId = btnMap.getAttribute("data-providerid");
var menuItems = currentMappingOptions.ProviderChannels.map(function(m) {
return {
name: m.Name,
id: m.Id,
selected: m.Id.toLowerCase() === providerChannelId.toLowerCase()
}
}).sort(function (a, b) {
return a.name.localeCompare(b.name);
});
actionsheet.show({
positionTo: btnMap,
items: menuItems

View file

@ -52,12 +52,10 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
'ERROR': 'ERROR'
};
// production version registered with google
// replace this value if you want to test changes on another instance
var applicationID = "F007D354";
// This is the beta version used for testing new changes
//applicationID = '27C4EB5B';
var messageNamespace = 'urn:x-cast:com.connectsdk';
var CastPlayer = function () {
@ -91,15 +89,12 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
* receiverListener may be invoked at any time afterwards, and possibly more than once.
*/
CastPlayer.prototype.initializeCastPlayer = function () {
var chrome = window.chrome;
if (!chrome) {
return;
}
if (!chrome.cast || !chrome.cast.isAvailable) {
setTimeout(this.initializeCastPlayer.bind(this), 1000);
return;
}
@ -108,13 +103,10 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
var sessionRequest = new chrome.cast.SessionRequest(applicationID);
var apiConfig = new chrome.cast.ApiConfig(sessionRequest,
this.sessionListener.bind(this),
this.receiverListener.bind(this),
"origin_scoped");
this.receiverListener.bind(this));
console.log('chromecast.initialize');
chrome.cast.initialize(apiConfig, this.onInitSuccess.bind(this), this.errorHandler);
};
/**
@ -140,12 +132,8 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
* status gets synced up with current media of the session
*/
CastPlayer.prototype.sessionListener = function (e) {
this.session = e;
if (this.session) {
//console.log('sessionListener ' + JSON.stringify(e));
if (this.session.media[0]) {
this.onMediaDiscovered('activeSession', this.session.media[0]);
}
@ -164,28 +152,20 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
}
CastPlayer.prototype.messageListener = function (namespace, message) {
if (typeof (message) === 'string') {
message = JSON.parse(message);
}
if (message.type === 'playbackerror') {
var errorCode = message.data;
setTimeout(function () {
alertText(globalize.translate('MessagePlaybackError' + errorCode), globalize.translate('HeaderPlaybackError'));
}, 300);
}
else if (message.type === 'connectionerror') {
} else if (message.type === 'connectionerror') {
setTimeout(function () {
alertText(globalize.translate('MessageChromecastConnectionError'), globalize.translate('HeaderError'));
}, 300);
}
else if (message.type) {
} else if (message.type) {
events.trigger(this, message.type, [message.data]);
}
};
@ -196,13 +176,11 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
* does not provide a list of device IDs
*/
CastPlayer.prototype.receiverListener = function (e) {
if (e === 'available') {
//console.log("chromecast receiver found");
console.log("chromecast receiver found");
this.hasReceivers = true;
}
else {
//console.log("chromecast receiver list empty");
} else {
console.log("chromecast receiver list empty");
this.hasReceivers = false;
}
};
@ -211,19 +189,16 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
* session update listener
*/
CastPlayer.prototype.sessionUpdateListener = function (isAlive) {
//console.log('sessionUpdateListener alive: ' + isAlive);
if (isAlive) {
}
else {
console.log('sessionUpdateListener: already alive');
} else {
this.session = null;
this.deviceState = DEVICE_STATE.IDLE;
this.castPlayerState = PLAYER_STATE.IDLE;
document.removeEventListener("volumeupbutton", onVolumeUpKeyDown, false);
document.removeEventListener("volumedownbutton", onVolumeDownKeyDown, false);
//console.log('sessionUpdateListener: setting currentMediaSession to null');
console.log('sessionUpdateListener: setting currentMediaSession to null');
this.currentMediaSession = null;
sendConnectionResult(false);
@ -236,7 +211,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
* session request in opt_sessionRequest.
*/
CastPlayer.prototype.launchApp = function () {
//console.log("chromecast launching app...");
console.log("chromecast launching app...");
chrome.cast.requestSession(this.onRequestSessionSuccess.bind(this), this.onLaunchError.bind(this));
};
@ -245,15 +220,12 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
* @param {Object} e A chrome.cast.Session object
*/
CastPlayer.prototype.onRequestSessionSuccess = function (e) {
//console.log("chromecast session success: " + e.sessionId);
console.log("chromecast session success: " + e.sessionId);
this.onSessionConnected(e);
};
CastPlayer.prototype.onSessionConnected = function (session) {
this.session = session;
this.deviceState = DEVICE_STATE.ACTIVE;
this.session.addMessageListener(messageNamespace, this.messageListener.bind(this));
@ -264,7 +236,6 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
document.addEventListener("volumedownbutton", onVolumeDownKeyDown, false);
events.trigger(this, 'connect');
this.sendMessage({
options: {},
command: 'Identify'
@ -283,8 +254,6 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
* session update listener
*/
CastPlayer.prototype.sessionMediaListener = function (e) {
//console.log('sessionMediaListener');
this.currentMediaSession = e;
this.currentMediaSession.addUpdateListener(this.mediaStatusUpdateHandler);
};
@ -293,9 +262,8 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
* Callback function for launch error
*/
CastPlayer.prototype.onLaunchError = function () {
//console.log("chromecast launch error");
console.log("chromecast launch error");
this.deviceState = DEVICE_STATE.ERROR;
sendConnectionResult(false);
};
@ -303,25 +271,22 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
* Stops the running receiver application associated with the session.
*/
CastPlayer.prototype.stopApp = function () {
if (this.session) {
this.session.stop(this.onStopAppSuccess.bind(this, 'Session stopped'),
this.errorHandler);
this.session.stop(this.onStopAppSuccess.bind(this, 'Session stopped'), this.errorHandler);
}
};
/**
* Callback function for stop app success
*/
CastPlayer.prototype.onStopAppSuccess = function (message) {
//console.log(message);
console.log(message);
this.deviceState = DEVICE_STATE.IDLE;
this.castPlayerState = PLAYER_STATE.IDLE;
document.removeEventListener("volumeupbutton", onVolumeUpKeyDown, false);
document.removeEventListener("volumedownbutton", onVolumeDownKeyDown, false);
//console.log('onStopAppSuccess: setting currentMediaSession to null');
this.currentMediaSession = null;
};
@ -330,15 +295,13 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
* @param {Number} mediaIndex An index number to indicate current media content
*/
CastPlayer.prototype.loadMedia = function (options, command) {
if (!this.session) {
//console.log("no session");
console.log("no session");
return Promise.reject();
}
// Convert the items to smaller stubs to send the minimal amount of information
// convert items to smaller stubs to send minimal amount of information
options.items = options.items.map(function (i) {
return {
Id: i.Id,
ServerId: i.ServerId,
@ -397,22 +360,17 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
}
return new Promise(function (resolve, reject) {
require(['chromecastHelper'], function (chromecastHelper) {
chromecastHelper.getServerAddress(apiClient).then(function (serverAddress) {
message.serverAddress = serverAddress;
player.sendMessageInternal(message).then(resolve, reject);
}, reject);
});
});
};
CastPlayer.prototype.sendMessageInternal = function (message) {
message = JSON.stringify(message);
//console.log(message);
this.session.sendMessage(messageNamespace, message, this.onPlayCommandSuccess.bind(this), this.errorHandler);
return Promise.resolve();
@ -447,11 +405,10 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
* @param {!Boolean} e true/false
*/
CastPlayer.prototype.onMediaStatusUpdate = function (e) {
//console.log("chromecast updating media: " + e);
if (e === false) {
this.castPlayerState = PLAYER_STATE.IDLE;
}
//console.log("chromecast updating media: " + e);
};
/**
@ -459,19 +416,16 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
* @param {Boolean} mute A boolean
*/
CastPlayer.prototype.setReceiverVolume = function (mute, vol) {
if (!this.currentMediaSession) {
//console.log('this.currentMediaSession is null');
return;
}
if (!mute) {
this.session.setReceiverVolumeLevel((vol || 1),
this.mediaCommandSuccessCallback.bind(this),
this.errorHandler);
}
else {
} else {
this.session.setReceiverMuted(true,
this.mediaCommandSuccessCallback.bind(this),
this.errorHandler);
@ -636,19 +590,15 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
}
ChromecastPlayer.prototype.tryPair = function (target) {
var castPlayer = this._castPlayer;
if (castPlayer.deviceState !== DEVICE_STATE.ACTIVE && castPlayer.isInitialized) {
return new Promise(function (resolve, reject) {
currentResolve = resolve;
currentReject = reject;
castPlayer.launchApp();
});
} else {
currentResolve = null;
currentReject = null;
@ -657,7 +607,6 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
};
ChromecastPlayer.prototype.getTargets = function () {
var targets = [];
if (this._castPlayer && this._castPlayer.hasReceivers) {

View file

@ -50,10 +50,6 @@
vertical-align: initial;
}
.button-link-inline {
display: inline;
}
.button-link:hover {
text-decoration: underline;
}

View file

@ -28,11 +28,6 @@ define(['browser', 'dom', 'layoutManager', 'shell', 'appRouter', 'apphost', 'css
this.classList.add('emby-button');
if (browser.firefox) {
// a ff hack is needed for vertical alignment
this.classList.add('button-link-inline');
}
if (layoutManager.tv) {
if (this.getAttribute('data-focusscale') !== 'false') {
this.classList.add('emby-button-focusscale');

View file

@ -1,13 +1,11 @@
define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager', 'imageLoader', 'layoutManager', 'browser', 'dom', 'loading', 'focusManager', 'serverNotifications', 'events', 'registerElement'], function (itemShortcuts, inputManager, connectionManager, playbackManager, imageLoader, layoutManager, browser, dom, loading, focusManager, serverNotifications, events) {
'use strict';
var ItemsContainerProtoType = Object.create(HTMLDivElement.prototype);
var ItemsContainerPrototype = Object.create(HTMLDivElement.prototype);
function onClick(e) {
var itemsContainer = this;
var target = e.target;
var multiSelect = itemsContainer.multiSelect;
if (multiSelect) {
@ -20,22 +18,18 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
}
function disableEvent(e) {
e.preventDefault();
e.stopPropagation();
return false;
}
function onContextMenu(e) {
var itemsContainer = this;
var target = e.target;
var card = dom.parentWithAttribute(target, 'data-id');
// check for serverId, it won't be present on selectserver
if (card && card.getAttribute('data-serverid')) {
inputManager.trigger('menu', {
sourceElement: card
});
@ -52,8 +46,7 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
};
}
ItemsContainerProtoType.enableMultiSelect = function (enabled) {
ItemsContainerPrototype.enableMultiSelect = function (enabled) {
var current = this.multiSelect;
if (!enabled) {
@ -78,7 +71,6 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
};
function onDrop(evt, itemsContainer) {
var el = evt.item;
var newIndex = evt.newIndex;
@ -86,9 +78,7 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
var playlistId = el.getAttribute('data-playlistid');
if (!playlistId) {
var oldIndex = evt.oldIndex;
el.dispatchEvent(new CustomEvent('itemdrop', {
detail: {
oldIndex: oldIndex,
@ -107,27 +97,18 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
loading.show();
apiClient.ajax({
url: apiClient.getUrl('Playlists/' + playlistId + '/Items/' + itemId + '/Move/' + newIndex),
type: 'POST'
}).then(function () {
loading.hide();
}, function () {
loading.hide();
itemsContainer.refreshItems();
});
}
ItemsContainerProtoType.enableDragReordering = function (enabled) {
ItemsContainerPrototype.enableDragReordering = function (enabled) {
var current = this.sortable;
if (!enabled) {
if (current) {
current.destroy();
@ -142,15 +123,12 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
var self = this;
require(['sortable'], function (Sortable) {
self.sortable = new Sortable(self, {
draggable: ".listItem",
handle: '.listViewDragHandle',
// dragging ended
onEnd: function (/**Event*/evt) {
onEnd: function (evt) {
return onDrop(evt, self);
}
});
@ -169,17 +147,13 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
// TODO: Check user data change reason?
if (eventsToMonitor.indexOf('markfavorite') !== -1) {
itemsContainer.notifyRefreshNeeded();
}
else if (eventsToMonitor.indexOf('markplayed') !== -1) {
} else if (eventsToMonitor.indexOf('markplayed') !== -1) {
itemsContainer.notifyRefreshNeeded();
}
}
function getEventsToMonitor(itemsContainer) {
var monitor = itemsContainer.getAttribute('data-monitor');
if (monitor) {
return monitor.split(',');
@ -193,7 +167,6 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
var itemsContainer = this;
if (getEventsToMonitor(itemsContainer).indexOf('timers') !== -1) {
itemsContainer.notifyRefreshNeeded();
return;
}
@ -208,10 +181,8 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
}
function onSeriesTimerCreated(e, apiClient, data) {
var itemsContainer = this;
if (getEventsToMonitor(itemsContainer).indexOf('seriestimers') !== -1) {
itemsContainer.notifyRefreshNeeded();
return;
}
@ -219,42 +190,33 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
function onTimerCancelled(e, apiClient, data) {
var itemsContainer = this;
if (getEventsToMonitor(itemsContainer).indexOf('timers') !== -1) {
itemsContainer.notifyRefreshNeeded();
return;
}
var id = data.Id;
require(['cardBuilder'], function (cardBuilder) {
cardBuilder.onTimerCancelled(id, itemsContainer);
cardBuilder.onTimerCancelled(data.Id, itemsContainer);
});
}
function onSeriesTimerCancelled(e, apiClient, data) {
var itemsContainer = this;
if (getEventsToMonitor(itemsContainer).indexOf('seriestimers') !== -1) {
itemsContainer.notifyRefreshNeeded();
return;
}
var id = data.Id;
require(['cardBuilder'], function (cardBuilder) {
cardBuilder.onSeriesTimerCancelled(id, itemsContainer);
cardBuilder.onSeriesTimerCancelled(data.Id, itemsContainer);
});
}
function onLibraryChanged(e, apiClient, data) {
var itemsContainer = this;
var eventsToMonitor = getEventsToMonitor(itemsContainer);
if (eventsToMonitor.indexOf('seriestimers') !== -1 || eventsToMonitor.indexOf('timers') !== -1) {
// yes this is an assumption
return;
}
@ -280,25 +242,17 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
}
function onPlaybackStopped(e, stopInfo) {
var itemsContainer = this;
var state = stopInfo.state;
var eventsToMonitor = getEventsToMonitor(itemsContainer);
if (state.NowPlayingItem && state.NowPlayingItem.MediaType === 'Video') {
if (eventsToMonitor.indexOf('videoplayback') !== -1) {
itemsContainer.notifyRefreshNeeded(true);
return;
}
}
else if (state.NowPlayingItem && state.NowPlayingItem.MediaType === 'Audio') {
} else if (state.NowPlayingItem && state.NowPlayingItem.MediaType === 'Audio') {
if (eventsToMonitor.indexOf('audioplayback') !== -1) {
itemsContainer.notifyRefreshNeeded(true);
return;
}
@ -306,7 +260,6 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
}
function addNotificationEvent(instance, name, handler, owner) {
var localHandler = handler.bind(instance);
owner = owner || serverNotifications;
events.on(owner, name, localHandler);
@ -314,7 +267,6 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
}
function removeNotificationEvent(instance, name, owner) {
var handler = instance['event_' + name];
if (handler) {
owner = owner || serverNotifications;
@ -323,13 +275,11 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
}
}
ItemsContainerProtoType.createdCallback = function () {
ItemsContainerPrototype.createdCallback = function () {
this.classList.add('itemsContainer');
};
ItemsContainerProtoType.attachedCallback = function () {
ItemsContainerPrototype.attachedCallback = function () {
this.addEventListener('click', onClick);
if (browser.touch) {
@ -365,8 +315,7 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
}
};
ItemsContainerProtoType.detachedCallback = function () {
ItemsContainerPrototype.detachedCallback = function () {
clearRefreshInterval(this);
this.enableMultiSelect(false);
@ -374,6 +323,7 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
this.removeEventListener('click', onClick);
this.removeEventListener('contextmenu', onContextMenu);
this.removeEventListener('contextmenu', disableEvent);
itemShortcuts.off(this, getShortcutOptions());
removeNotificationEvent(this, 'UserDataChanged');
@ -389,15 +339,12 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
this.parentContainer = null;
};
ItemsContainerProtoType.pause = function () {
ItemsContainerPrototype.pause = function () {
clearRefreshInterval(this, true);
this.paused = true;
};
ItemsContainerProtoType.resume = function (options) {
ItemsContainerPrototype.resume = function (options) {
this.paused = false;
var refreshIntervalEndTime = this.refreshIntervalEndTime;
@ -405,9 +352,7 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
var remainingMs = refreshIntervalEndTime - new Date().getTime();
if (remainingMs > 0 && !this.needsRefresh) {
resetRefreshInterval(this, remainingMs);
} else {
this.needsRefresh = true;
this.refreshIntervalEndTime = null;
@ -421,8 +366,7 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
return Promise.resolve();
};
ItemsContainerProtoType.refreshItems = function () {
ItemsContainerPrototype.refreshItems = function () {
if (!this.fetchData) {
return Promise.resolve();
}
@ -437,8 +381,7 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
return this.fetchData().then(onDataFetched.bind(this));
};
ItemsContainerProtoType.notifyRefreshNeeded = function (isInForeground) {
ItemsContainerPrototype.notifyRefreshNeeded = function (isInForeground) {
if (this.paused) {
this.needsRefresh = true;
return;
@ -457,9 +400,7 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
};
function clearRefreshInterval(itemsContainer, isPausing) {
if (itemsContainer.refreshInterval) {
clearInterval(itemsContainer.refreshInterval);
itemsContainer.refreshInterval = null;
@ -470,7 +411,6 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
}
function resetRefreshInterval(itemsContainer, intervalMs) {
clearRefreshInterval(itemsContainer);
if (!intervalMs) {
@ -484,7 +424,6 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
}
function onDataFetched(result) {
var items = result.Items || result;
var parentContainer = this.parentContainer;
@ -496,10 +435,6 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
}
}
// Scroll back up so they can see the results from the beginning
// TODO: Find scroller
//window.scrollTo(0, 0);
var activeElement = document.activeElement;
var focusId;
var hasActiveElement;
@ -528,12 +463,11 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
if (focusId) {
var newElement = itemsContainer.querySelector('[data-id="' + focusId + '"]');
if (newElement) {
try {
focusManager.focus(newElement);
return;
}
catch (err) {
} catch (err) {
console.log(err);
}
}
}
@ -542,7 +476,7 @@ define(['itemShortcuts', 'inputManager', 'connectionManager', 'playbackManager',
}
document.registerElement('emby-itemscontainer', {
prototype: ItemsContainerProtoType,
prototype: ItemsContainerPrototype,
extends: 'div'
});
});

View file

@ -1,60 +1,11 @@
.emby-scrollbuttons-scroller {
position: relative;
}
.scrollbuttoncontainer {
.emby-scrollbuttons {
position: absolute;
top: 10%;
bottom: 35%;
top: 0;
right: 0;
align-items: center;
justify-content: center;
z-index: 1;
font-size: 3em;
color: #fff;
display: none;
color: #ffffff;
display: flex;
overflow: hidden;
}
.scrollbuttoncontainer-left {
background: rgba(20, 20, 20, .5);
background: -moz-linear-gradient(left,#000 0,rgba(0,0,0,0) 100%);
background: -webkit-linear-gradient(left,#000 0,rgba(0,0,0,0) 100%);
background: linear-gradient(to right,#000,rgba(0,0,0,0));
}
.scrollbuttoncontainer-right {
background: rgba(20, 20, 20, .5);
background: -moz-linear-gradient(right,#000 0,rgba(0,0,0,0) 100%);
background: -webkit-linear-gradient(right,#000 0,rgba(0,0,0,0) 100%);
background: linear-gradient(to left,#000,rgba(0,0,0,0));
}
.emby-scrollbuttons-scroller:hover .scrollbuttoncontainer {
display: flex;
}
.scrollbuttoncontainer-left {
left: 0;
}
.scrollbuttoncontainer-right {
right: 0;
}
.emby-scrollbuttons-scrollbutton {
margin: 0 -.2em;
transition: transform 160ms ease-out;
}
.scrollbuttoncontainer:hover > .emby-scrollbuttons-scrollbutton {
transform: scale(1.3, 1.3);
}
.emby-scrollbuttons-scrollbutton:after {
content: '';
display: none !important;
}
.emby-scrollbuttons-scrollbutton:focus {
color: inherit !important;
}

View file

@ -3,30 +3,20 @@ define(['layoutManager', 'dom', 'css!./emby-scrollbuttons', 'registerElement', '
var EmbyScrollButtonsPrototype = Object.create(HTMLDivElement.prototype);
EmbyScrollButtonsPrototype.createdCallback = function () {
};
function getScrollButtonContainerHtml(direction) {
EmbyScrollButtonsPrototype.createdCallback = function () {};
function getScrollButtonHtml(direction) {
var html = '';
var hide = direction === 'left' ? ' hide' : '';
html += '<div class="scrollbuttoncontainer scrollbuttoncontainer-' + direction + hide + '">';
var icon = direction === 'left' ? '&#xE5CB;' : '&#xE5CC;';
html += '<button type="button" is="paper-icon-button-light" data-ripple="false" data-direction="' + direction + '" class="emby-scrollbuttons-scrollbutton">';
html += '<button type="button" is="paper-icon-button-light" data-ripple="false" data-direction="' + direction + '" class="emby-scrollbuttons-button">';
html += '<i class="md-icon">' + icon + '</i>';
html += '</button>';
html += '</div>';
return html;
}
function getScrollPosition(parent) {
if (parent.getScrollPosition) {
return parent.getScrollPosition();
}
@ -35,7 +25,6 @@ define(['layoutManager', 'dom', 'css!./emby-scrollbuttons', 'registerElement', '
}
function getScrollWidth(parent) {
if (parent.getScrollSize) {
return parent.getScrollSize();
}
@ -43,46 +32,45 @@ define(['layoutManager', 'dom', 'css!./emby-scrollbuttons', 'registerElement', '
return 0;
}
function onScrolledToPosition(scrollButtons, pos, scrollWidth) {
if (pos > 0) {
scrollButtons.scrollButtonsLeft.classList.remove('hide');
} else {
function updateScrollButtons(scrollButtons, scrollSize, scrollPos, scrollWidth) {
// hack alert add twenty for rounding errors
if (scrollWidth <= scrollSize + 20) {
scrollButtons.scrollButtonsLeft.classList.add('hide');
}
if (scrollWidth > 0) {
pos += scrollButtons.offsetWidth;
if (pos >= scrollWidth) {
scrollButtons.scrollButtonsRight.classList.add('hide');
} else {
scrollButtons.scrollButtonsRight.classList.remove('hide');
}
if (scrollPos > 0) {
scrollButtons.scrollButtonsLeft.disabled = false;
} else {
scrollButtons.scrollButtonsLeft.disabled = true;
}
var scrollPosEnd = scrollPos + scrollSize;
if (scrollWidth > 0 && scrollPosEnd >= scrollWidth) {
scrollButtons.scrollButtonsRight.disabled = true;
} else {
scrollButtons.scrollButtonsRight.disabled = false;
}
}
function onScroll(e) {
var scrollButtons = this;
var scroller = this.scroller;
var pos = getScrollPosition(scroller);
var scrollSize = getScrollSize(scroller);
var scrollPos = getScrollPosition(scroller);
var scrollWidth = getScrollWidth(scroller);
onScrolledToPosition(scrollButtons, pos, scrollWidth);
updateScrollButtons(scrollButtons, scrollSize, scrollPos, scrollWidth);
}
function getStyleValue(style, name) {
var value = style.getPropertyValue(name);
if (!value) {
return 0;
}
value = value.replace('px', '');
if (!value) {
return 0;
}
@ -96,18 +84,15 @@ define(['layoutManager', 'dom', 'css!./emby-scrollbuttons', 'registerElement', '
}
function getScrollSize(elem) {
var scrollSize = elem.offsetWidth;
var style = window.getComputedStyle(elem, null);
var paddingLeft = getStyleValue(style, 'padding-left');
if (paddingLeft) {
scrollSize -= paddingLeft;
}
var paddingRight = getStyleValue(style, 'padding-right');
var paddingRight = getStyleValue(style, 'padding-right');
if (paddingRight) {
scrollSize -= paddingRight;
}
@ -116,12 +101,11 @@ define(['layoutManager', 'dom', 'css!./emby-scrollbuttons', 'registerElement', '
style = window.getComputedStyle(slider, null);
paddingLeft = getStyleValue(style, 'padding-left');
if (paddingLeft) {
scrollSize -= paddingLeft;
}
paddingRight = getStyleValue(style, 'padding-right');
paddingRight = getStyleValue(style, 'padding-right');
if (paddingRight) {
scrollSize -= paddingRight;
}
@ -130,58 +114,52 @@ define(['layoutManager', 'dom', 'css!./emby-scrollbuttons', 'registerElement', '
}
function onScrollButtonClick(e) {
var parent = dom.parentWithAttribute(this, 'is', 'emby-scroller');
var scroller = this.parentNode.nextSibling;
var direction = this.getAttribute('data-direction');
var scrollSize = getScrollSize(scroller);
var scrollPos = getScrollPosition(scroller);
var scrollWidth = getScrollWidth(scroller);
var scrollSize = getScrollSize(parent);
var pos = getScrollPosition(parent);
var newPos;
if (direction === 'left') {
newPos = Math.max(0, pos - scrollSize);
newPos = Math.max(0, scrollPos - scrollSize);
} else {
newPos = pos + scrollSize;
newPos = scrollPos + scrollSize;
}
parent.scrollToPosition(newPos, false);
scroller.scrollToPosition(newPos, false);
}
EmbyScrollButtonsPrototype.attachedCallback = function () {
var scroller = this.nextSibling;
var parent = this.parentNode;
this.scroller = scroller;
var parent = dom.parentWithAttribute(this, 'is', 'emby-scroller');
this.scroller = parent;
parent.classList.add('emby-scroller-container');
parent.classList.add('emby-scrollbuttons-scroller');
this.innerHTML = getScrollButtonContainerHtml('left') + getScrollButtonContainerHtml('right');
this.innerHTML = getScrollButtonHtml('left') + getScrollButtonHtml('right');
var scrollHandler = onScroll.bind(this);
this.scrollHandler = scrollHandler;
var buttons = this.querySelectorAll('.emby-scrollbuttons-scrollbutton');
var buttons = this.querySelectorAll('.emby-scrollbuttons-button');
buttons[0].addEventListener('click', onScrollButtonClick);
buttons[1].addEventListener('click', onScrollButtonClick);
buttons = this.querySelectorAll('.scrollbuttoncontainer');
this.scrollButtonsLeft = buttons[0];
this.scrollButtonsRight = buttons[1];
parent.addScrollEventListener(scrollHandler, {
scroller.addScrollEventListener(scrollHandler, {
capture: false,
passive: true
});
};
EmbyScrollButtonsPrototype.detachedCallback = function () {
var parent = this.scroller;
this.scroller = null;
var scrollHandler = this.scrollHandler;
if (parent && scrollHandler) {
parent.removeScrollEventListener(scrollHandler, {
capture: false,

View file

@ -0,0 +1,17 @@
.emby-scroller-container {
position: relative;
}
.emby-scroller {
margin-left: 3.3%;
margin-right: 3.3%;
}
@media all and (max-width:50em) {
.emby-scroller {
padding-left: 3.3%;
padding-right: 3.3%;
margin-left: 0;
margin-right: 0;
}
}

View file

@ -1,101 +1,95 @@
define(['scroller', 'dom', 'layoutManager', 'inputManager', 'focusManager', 'browser', 'registerElement'], function (scroller, dom, layoutManager, inputManager, focusManager, browser) {
define(['scroller', 'dom', 'layoutManager', 'inputManager', 'focusManager', 'browser', 'registerElement', 'css!./emby-scroller'], function (scroller, dom, layoutManager, inputManager, focusManager, browser) {
'use strict';
var ScrollerProtoType = Object.create(HTMLDivElement.prototype);
var ScrollerPrototype = Object.create(HTMLDivElement.prototype);
ScrollerProtoType.createdCallback = function () {
ScrollerPrototype.createdCallback = function () {
this.classList.add('emby-scroller');
};
function initCenterFocus(elem, scrollerInstance) {
dom.addEventListener(elem, 'focus', function (e) {
var focused = focusManager.focusableParent(e.target);
if (focused) {
scrollerInstance.toCenter(focused);
}
}, {
capture: true,
passive: true
});
}
ScrollerProtoType.scrollToBeginning = function () {
ScrollerPrototype.scrollToBeginning = function () {
if (this.scroller) {
this.scroller.slideTo(0, true);
}
};
ScrollerProtoType.toStart = function (elem, immediate) {
ScrollerPrototype.toStart = function (elem, immediate) {
if (this.scroller) {
this.scroller.toStart(elem, immediate);
}
};
ScrollerProtoType.toCenter = function (elem, immediate) {
ScrollerPrototype.toCenter = function (elem, immediate) {
if (this.scroller) {
this.scroller.toCenter(elem, immediate);
}
};
ScrollerProtoType.scrollToPosition = function (pos, immediate) {
ScrollerPrototype.scrollToPosition = function (pos, immediate) {
if (this.scroller) {
this.scroller.slideTo(pos, immediate);
}
};
ScrollerProtoType.getScrollPosition = function () {
ScrollerPrototype.getScrollPosition = function () {
if (this.scroller) {
return this.scroller.getScrollPosition();
}
};
ScrollerProtoType.getScrollSize = function () {
ScrollerPrototype.getScrollSize = function () {
if (this.scroller) {
return this.scroller.getScrollSize();
}
};
ScrollerProtoType.getScrollEventName = function () {
ScrollerPrototype.getScrollEventName = function () {
if (this.scroller) {
return this.scroller.getScrollEventName();
}
};
ScrollerProtoType.getScrollSlider = function () {
ScrollerPrototype.getScrollSlider = function () {
if (this.scroller) {
return this.scroller.getScrollSlider();
}
};
ScrollerProtoType.addScrollEventListener = function (fn, options) {
ScrollerPrototype.addScrollEventListener = function (fn, options) {
if (this.scroller) {
dom.addEventListener(this.scroller.getScrollFrame(), this.scroller.getScrollEventName(), fn, options);
}
};
ScrollerProtoType.removeScrollEventListener = function (fn, options) {
ScrollerPrototype.removeScrollEventListener = function (fn, options) {
if (this.scroller) {
dom.removeEventListener(this.scroller.getScrollFrame(), this.scroller.getScrollEventName(), fn, options);
}
};
function onInputCommand(e) {
var cmd = e.detail.command;
if (cmd === 'end') {
focusManager.focusLast(this, '.' + this.getAttribute('data-navcommands'));
e.preventDefault();
e.stopPropagation();
}
else if (cmd === 'pageup') {
} else if (cmd === 'pageup') {
focusManager.moveFocus(e.target, this, '.' + this.getAttribute('data-navcommands'), -12);
e.preventDefault();
e.stopPropagation();
}
else if (cmd === 'pagedown') {
} else if (cmd === 'pagedown') {
focusManager.moveFocus(e.target, this, '.' + this.getAttribute('data-navcommands'), 12);
e.preventDefault();
e.stopPropagation();
@ -104,7 +98,6 @@ define(['scroller', 'dom', 'layoutManager', 'inputManager', 'focusManager', 'bro
function initHeadroom(elem) {
require(['headroom'], function (Headroom) {
var headroom = new Headroom([], {
scroller: elem
});
@ -114,8 +107,7 @@ define(['scroller', 'dom', 'layoutManager', 'inputManager', 'focusManager', 'bro
});
}
ScrollerProtoType.attachedCallback = function () {
ScrollerPrototype.attachedCallback = function () {
if (this.getAttribute('data-navcommands')) {
inputManager.on(this, onInputCommand);
}
@ -141,10 +133,8 @@ define(['scroller', 'dom', 'layoutManager', 'inputManager', 'focusManager', 'bro
slidee: slider,
scrollBy: 200,
speed: horizontal ? 270 : 240,
//immediateSpeed: pageOptions.immediateSpeed,
elasticBounds: 1,
dragHandle: 1,
scrollWidth: this.getAttribute('data-scrollsize') === 'auto' ? null : 5000000,
autoImmediate: true,
skipSlideToWhenVisible: this.getAttribute('data-skipfocuswhenvisible') === 'true',
dispatchScrollEvent: enableScrollButtons || bindHeader || this.getAttribute('data-scrollevent') === 'true',
@ -152,7 +142,6 @@ define(['scroller', 'dom', 'layoutManager', 'inputManager', 'focusManager', 'bro
allowNativeSmoothScroll: this.getAttribute('data-allownativesmoothscroll') === 'true' && !enableScrollButtons,
allowNativeScroll: !enableScrollButtons,
forceHideScrollbars: enableScrollButtons,
// In edge, with the native scroll, the content jumps around when hovering over the buttons
requireAnimation: enableScrollButtons && browser.edge
};
@ -160,6 +149,7 @@ define(['scroller', 'dom', 'layoutManager', 'inputManager', 'focusManager', 'bro
// If just inserted it might not have any height yet - yes this is a hack
this.scroller = new scroller(scrollFrame, options);
this.scroller.init();
this.scroller.reload();
if (layoutManager.tv && this.getAttribute('data-centerfocus')) {
initCenterFocus(this, this.scroller);
@ -175,30 +165,26 @@ define(['scroller', 'dom', 'layoutManager', 'inputManager', 'focusManager', 'bro
};
function loadScrollButtons(scroller) {
require(['emby-scrollbuttons'], function () {
scroller.insertAdjacentHTML('beforeend', '<div is="emby-scrollbuttons"></div>');
scroller.insertAdjacentHTML('beforebegin', '<div is="emby-scrollbuttons" class="emby-scrollbuttons padded-right"></div>');
});
}
ScrollerProtoType.pause = function () {
ScrollerPrototype.pause = function () {
var headroom = this.headroom;
if (headroom) {
headroom.pause();
}
};
ScrollerProtoType.resume = function () {
ScrollerPrototype.resume = function () {
var headroom = this.headroom;
if (headroom) {
headroom.resume();
}
};
ScrollerProtoType.detachedCallback = function () {
ScrollerPrototype.detachedCallback = function () {
if (this.getAttribute('data-navcommands')) {
inputManager.off(this, onInputCommand);
}
@ -217,7 +203,7 @@ define(['scroller', 'dom', 'layoutManager', 'inputManager', 'focusManager', 'bro
};
document.registerElement('emby-scroller', {
prototype: ScrollerProtoType,
prototype: ScrollerPrototype,
extends: 'div'
});
});

View file

@ -116,14 +116,8 @@ define(['layoutManager', 'browser', 'actionsheet', 'css!./emby-select', 'registe
inputId++;
}
if (!browser.firefox) {
this.classList.add('emby-select-withcolor');
if (layoutManager.tv) {
this.classList.add('emby-select-tv-withcolor');
}
}
if (layoutManager.tv) {
this.classList.add('emby-select-focusscale');
}

View file

@ -27,10 +27,6 @@ _:-ms-input-placeholder {
/* Disable webkit tap highlighting */
-webkit-tap-highlight-color: rgba(0,0,0,0);
display: block;
/**************************** Tracks ****************************/
/**************************** Thumbs ****************************/
/**************************** 0-value ****************************/
/**************************** Disabled ****************************/
}
.mdl-slider::-moz-focus-outer {

View file

@ -40,7 +40,7 @@ define(['dom'], function (dom) {
try {
element.focus({
preventScroll: true
preventScroll: false
});
} catch (err) {
console.log('Error in focusManager.autoFocus: ' + err);

View file

@ -18,7 +18,6 @@
</div>
<div is="emby-scroller" class="guideVerticalScroller flex flex-grow programContainer guideScroller" data-skipfocuswhenvisible="true" data-horizontal="false">
<div class="scrollSlider flex flex-grow flex-direction-row" style="overflow:hidden;contain: layout style paint;">
<div class="channelsContainer">
<div class="channelList"></div>

View file

@ -9,3 +9,17 @@
width: 46% !important;
}
}
.homeLibraryIcon {
margin-left: .5em;
margin-right: .5em;
-webkit-flex-shrink: 0;
flex-shrink: 0
}
.homeLibraryText {
white-space: nowrap;
-o-text-overflow: ellipsis;
text-overflow: ellipsis;
overflow: hidden
}

View file

@ -1,10 +1,8 @@
define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'layoutManager', 'imageLoader', 'globalize', 'itemShortcuts', 'itemHelper', 'appRouter', 'paper-icon-button-light', 'emby-itemscontainer', 'emby-scroller', 'emby-button', 'css!./homesections'], function (connectionManager, cardBuilder, appSettings, dom, appHost, layoutManager, imageLoader, globalize, itemShortcuts, itemHelper, appRouter) {
define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'layoutManager', 'imageLoader', 'globalize', 'itemShortcuts', 'itemHelper', 'appRouter', 'scripts/imagehelper','paper-icon-button-light', 'emby-itemscontainer', 'emby-scroller', 'emby-button', 'css!./homesections'], function (connectionManager, cardBuilder, appSettings, dom, appHost, layoutManager, imageLoader, globalize, itemShortcuts, itemHelper, appRouter, imageHelper) {
'use strict';
function getDefaultSection(index) {
switch (index) {
case 0:
return 'smalllibrarytiles';
case 1:
@ -25,13 +23,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function getAllSectionsToShow(userSettings, sectionCount) {
var sections = [];
for (var i = 0, length = sectionCount; i < length; i++) {
var section = userSettings.get('homesection' + i) || getDefaultSection(i);
if (section === 'folders') {
section = getDefaultSection(0);
}
@ -43,15 +37,11 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function loadSections(elem, apiClient, user, userSettings) {
return getUserViews(apiClient, user.Id).then(function (userViews) {
var i, length;
var sectionCount = 7;
var html = '';
for (i = 0, length = sectionCount; i < length; i++) {
var sectionCount = 7;
for (var i = 0; i < sectionCount; i++) {
html += '<div class="verticalSection section' + i + '"></div>';
}
@ -60,14 +50,11 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
var promises = [];
var sections = getAllSectionsToShow(userSettings, sectionCount);
for (i = 0, length = sections.length; i < length; i++) {
for (var i = 0; i < sections.length; i++) {
promises.push(loadSection(elem, apiClient, user, userSettings, userViews, sections, i));
}
return Promise.all(promises).then(function () {
return resume(elem, {
refresh: true,
returnPromise: false
@ -77,12 +64,8 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function destroySections(elem) {
var elems = elem.querySelectorAll('.itemsContainer');
var i, length;
for (i = 0, length = elems.length; i < length; i++) {
for (var i = 0; i < elems.length; i++) {
elems[i].fetchData = null;
elems[i].parentContainer = null;
elems[i].getItemsHtml = null;
@ -92,17 +75,13 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function pause(elem) {
var elems = elem.querySelectorAll('.itemsContainer');
var i, length;
for (i = 0, length = elems.length; i < length; i++) {
for (var i = 0; i < elems.length; i++) {
elems[i].pause();
}
}
function resume(elem, options) {
var elems = elem.querySelectorAll('.itemsContainer');
var i, length;
var promises = [];
@ -112,7 +91,6 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
var promise = Promise.all(promises);
if (!options || options.returnPromise !== false) {
return promise;
}
@ -127,41 +105,29 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
if (section === 'latestmedia') {
loadRecentlyAdded(elem, apiClient, user, userViews);
}
else if (section === 'librarytiles' || section === 'smalllibrarytiles' || section === 'smalllibrarytiles-automobile' || section === 'librarytiles-automobile') {
} else if (section === 'librarytiles' || section === 'smalllibrarytiles' || section === 'smalllibrarytiles-automobile' || section === 'librarytiles-automobile') {
loadLibraryTiles(elem, apiClient, user, userSettings, 'smallBackdrop', userViews, allSections);
}
else if (section === 'librarybuttons') {
} else if (section === 'librarybuttons') {
loadlibraryButtons(elem, apiClient, user, userSettings, userViews, allSections);
}
else if (section === 'resume') {
} else if (section === 'resume') {
loadResumeVideo(elem, apiClient, userId);
}
else if (section === 'resumeaudio') {
} else if (section === 'resumeaudio') {
loadResumeAudio(elem, apiClient, userId);
}
else if (section === 'activerecordings') {
} else if (section === 'activerecordings') {
loadLatestLiveTvRecordings(elem, true, apiClient, userId);
}
else if (section === 'nextup') {
} else if (section === 'nextup') {
loadNextUp(elem, apiClient, userId);
}
else if (section === 'onnow' || section === 'livetv') {
} else if (section === 'onnow' || section === 'livetv') {
return loadOnNow(elem, apiClient, user);
}
else {
} else {
elem.innerHTML = '';
return Promise.resolve();
}
return Promise.resolve();
}
function getUserViews(apiClient, userId) {
return apiClient.getUserViews({}, userId || apiClient.getCurrentUserId()).then(function (result) {
return result.Items;
});
}
@ -186,56 +152,15 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
var html = "";
html += '<div class="verticalSection verticalSection-extrabottompadding">';
html += '<div class="sectionTitleContainer sectionTitleContainer-cards">';
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderMyMedia') + '</h2>';
html += '</div>';
html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right vertical-wrap focuscontainer-x" data-multiselect="false">';
// "My Library" backgrounds
// library card background images
for (var i = 0, length = items.length; i < length; i++) {
var item = items[i];
var icon;
switch (item.CollectionType) {
case "movies":
icon = "local_movies";
break;
case "music":
icon = "library_music";
break;
case "photos":
icon = "photo";
break;
case "livetv":
icon = "live_tv";
break;
case "tvshows":
icon = "live_tv";
break;
case "trailers":
icon = "local_movies";
break;
case "homevideos":
icon = "video_library";
break;
case "musicvideos":
icon = "video_library";
break;
case "books":
icon = "folder";
break;
case "channels":
icon = "folder";
break;
case "playlists":
icon = "folder";
break;
default:
icon = "folder";
break;
}
html += '<a is="emby-linkbutton" href="' + appRouter.getRouteUrl(item) + '" class="raised homeLibraryButton"><i class="md-icon">' + icon + '</i><span>' + item.Name + '</span></a>';
var icon = imageHelper.getLibraryIcon(item.CollectionType);
html += '<a is="emby-linkbutton" href="' + appRouter.getRouteUrl(item) + '" class="raised homeLibraryButton"><i class="md-icon homeLibraryIcon">' + icon + '</i><span class="homeLibraryText">' + item.Name + '</span></a>';
}
html += '</div>';
@ -261,21 +186,15 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function getFetchLatestItemsFn(serverId, parentId, collectionType) {
return function () {
var apiClient = connectionManager.getApiClient(serverId);
var limit = 16;
if (enableScrollX()) {
if (collectionType === 'music') {
limit = 30;
}
}
else {
} else {
if (collectionType === 'tvshows') {
limit = 5;
} else if (collectionType === 'music') {
@ -286,7 +205,6 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
var options = {
Limit: limit,
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
ImageTypeLimit: 1,
@ -299,9 +217,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function getLatestItemsHtmlFn(itemType, viewType) {
return function (items) {
var shape = itemType === 'Channel' || viewType === 'movies' ?
getPortraitShape() :
viewType === 'music' ?
@ -331,31 +247,28 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function renderLatestSection(elem, apiClient, user, parent) {
var html = '';
html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">';
if (!layoutManager.tv) {
html += '<a is="emby-linkbutton" href="' + appRouter.getRouteUrl(parent, {
section: 'latest'
}) + '" class="more button-flat button-flat-mini sectionTitleTextButton">';
html += '<h2 class="sectionTitle sectionTitle-cards">';
html += globalize.translate('LatestFromLibrary', parent.Name);
html += '</h2>';
html += '<i class="md-icon">&#xE5CC;</i>';
html += '</a>';
} else {
html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate('LatestFromLibrary', parent.Name) + '</h2>';
}
html += '</div>';
if (enableScrollX()) {
html += '<div is="emby-scroller" data-mousewheel="false" data-centerfocus="true" class="padded-top-focusscale padded-bottom-focusscale"><div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x padded-left padded-right">';
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-mousewheel="false" data-centerfocus="true">';
html += '<div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x">';
} else {
html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right vertical-wrap focuscontainer-x">';
html += '<div is="emby-itemscontainer" class="itemsContainer focuscontainer-x padded-left padded-right vertical-wrap">';
}
if (enableScrollX()) {
@ -369,19 +282,14 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
itemsContainer.fetchData = getFetchLatestItemsFn(apiClient.serverId(), parent.Id, parent.CollectionType);
itemsContainer.getItemsHtml = getLatestItemsHtmlFn(parent.Type, parent.CollectionType);
itemsContainer.parentContainer = elem;
}
function loadRecentlyAdded(elem, apiClient, user, userViews) {
elem.classList.remove('verticalSection');
var excludeViewTypes = ['playlists', 'livetv', 'boxsets', 'channels'];
for (var i = 0, length = userViews.length; i < length; i++) {
var item = userViews[i];
if (user.Configuration.LatestItemsExcludes.indexOf(item.Id) !== -1) {
continue;
}
@ -406,43 +314,31 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function loadLibraryTiles(elem, apiClient, user, userSettings, shape, userViews, allSections) {
elem.classList.remove('verticalSection');
var html = '';
var scrollX = !layoutManager.desktop;
if (userViews.length) {
html += '<div class="verticalSection">';
html += '<div class="sectionTitleContainer sectionTitleContainer-cards">';
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderMyMedia') + '</h2>';
html += '</div>';
if (scrollX) {
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-mousewheel="false" data-centerfocus="true"><div is="emby-itemscontainer" class="scrollSlider focuscontainer-x padded-left padded-right">';
if (enableScrollX()) {
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-mousewheel="false" data-centerfocus="true">';
html += '<div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x">';
} else {
html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right vertical-wrap focuscontainer-x">';
html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right focuscontainer-x vertical-wrap">';
}
html += cardBuilder.getCardsHtml({
items: userViews,
shape: scrollX ? 'overflowSmallBackdrop' : shape,
shape: enableScrollX() ? 'overflowSmallBackdrop' : shape,
showTitle: true,
centerText: true,
overlayText: false,
lazy: true,
transition: false,
allowBottomPadding: !scrollX
allowBottomPadding: !enableScrollX()
});
if (scrollX) {
if (enableScrollX()) {
html += '</div>';
}
html += '</div>';
html += '</div>';
}
elem.innerHTML = html;
@ -450,27 +346,19 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function getContinueWatchingFetchFn(serverId) {
return function () {
var apiClient = connectionManager.getApiClient(serverId);
var screenWidth = dom.getWindowSize().innerWidth;
var limit;
if (enableScrollX()) {
limit = 12;
} else {
limit = screenWidth >= 1920 ? 8 : (screenWidth >= 1600 ? 8 : (screenWidth >= 1200 ? 9 : 6));
limit = Math.min(limit, 5);
}
var options = {
Limit: limit,
Recursive: true,
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
@ -485,9 +373,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function getContinueWatchingItemsHtml(items) {
var cardLayout = false;
return cardBuilder.getCardsHtml({
items: items,
preferThumb: true,
@ -508,12 +394,12 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function loadResumeVideo(elem, apiClient, userId) {
var html = '';
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderContinueWatching') + '</h2>';
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderContinueWatching') + '</h2>';
if (enableScrollX()) {
html += '<div is="emby-scroller" data-mousewheel="false" data-centerfocus="true" class="padded-top-focusscale padded-bottom-focusscale"><div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x padded-left padded-right" data-monitor="videoplayback,markplayed">';
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-mousewheel="false" data-centerfocus="true">';
html += '<div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x" data-monitor="videoplayback,markplayed">';
} else {
html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right vertical-wrap focuscontainer-x" data-monitor="videoplayback,markplayed">';
}
@ -533,27 +419,19 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function getContinueListeningFetchFn(serverId) {
return function () {
var apiClient = connectionManager.getApiClient(serverId);
var screenWidth = dom.getWindowSize().innerWidth;
var limit;
if (enableScrollX()) {
limit = 12;
} else {
limit = screenWidth >= 1920 ? 8 : (screenWidth >= 1600 ? 8 : (screenWidth >= 1200 ? 9 : 6));
limit = Math.min(limit, 5);
}
var options = {
Limit: limit,
Recursive: true,
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
@ -568,9 +446,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function getContinueListeningItemsHtml(items) {
var cardLayout = false;
return cardBuilder.getCardsHtml({
items: items,
preferThumb: true,
@ -591,12 +467,12 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function loadResumeAudio(elem, apiClient, userId) {
var html = '';
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderContinueWatching') + '</h2>';
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderContinueWatching') + '</h2>';
if (enableScrollX()) {
html += '<div is="emby-scroller" data-mousewheel="false" data-centerfocus="true" class="padded-top-focusscale padded-bottom-focusscale"><div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x padded-left padded-right" data-monitor="audioplayback,markplayed">';
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-mousewheel="false" data-centerfocus="true">';
html += '<div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x" data-monitor="audioplayback,markplayed">';
} else {
html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right vertical-wrap focuscontainer-x" data-monitor="audioplayback,markplayed">';
}
@ -659,7 +535,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
var userId = user.Id;
apiClient.getLiveTvRecommendedPrograms({
return apiClient.getLiveTvRecommendedPrograms({
userId: apiClient.getCurrentUserId(),
IsAiring: true,
limit: 1,
@ -682,13 +558,14 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
if (enableScrollX()) {
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-mousewheel="false" data-centerfocus="true" data-scrollbuttons="false">';
html += '<div class="scrollSlider padded-left padded-right padded-top padded-bottom focuscontainer-x">';
html += '<div class="padded-left padded-right padded-top padded-bottom scrollSlider focuscontainer-x">';
} else {
html += '<div class="padded-left padded-right padded-top focuscontainer-x">';
html += '<div class="padded-left padded-right padded-top padded-bottom focuscontainer-x">';
}
html += '<a style="margin-left:.8em;margin-right:0;" is="emby-linkbutton" href="' + appRouter.getRouteUrl('livetv', {
serverId: apiClient.serverId()
serverId: apiClient.serverId(),
section: 'programs'
}) + '" class="raised"><span>' + globalize.translate('Programs') + '</span></a>';
html += '<a style="margin-left:.5em;margin-right:0;" is="emby-linkbutton" href="' + appRouter.getRouteUrl('livetv', {
@ -705,6 +582,11 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
section: 'dvrschedule'
}) + '" class="raised"><span>' + globalize.translate('Schedule') + '</span></a>';
html += '<a style="margin-left:.5em;margin-right:0;" is="emby-linkbutton" href="' + appRouter.getRouteUrl('livetv', {
serverId: apiClient.serverId(),
section: 'seriesrecording'
}) + '" class="raised"><span>' + globalize.translate('Series') + '</span></a>';
html += '</div>';
if (enableScrollX()) {
html += '</div>';
@ -732,9 +614,10 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
html += '</div>';
if (enableScrollX()) {
html += '<div is="emby-scroller" data-mousewheel="false" data-centerfocus="true" class="padded-top-focusscale padded-bottom-focusscale"><div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x padded-left padded-right" data-refreshinterval="300000">';
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-mousewheel="false" data-centerfocus="true">';
html += '<div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x">'
} else {
html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right vertical-wrap focuscontainer-x" data-refreshinterval="300000">';
html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right vertical-wrap focuscontainer-x">';
}
if (enableScrollX()) {
@ -755,13 +638,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function getNextUpFetchFn(serverId) {
return function () {
var apiClient = connectionManager.getApiClient(serverId);
return apiClient.getNextUpEpisodes({
Limit: enableScrollX() ? 24 : 15,
Fields: "PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo",
UserId: apiClient.getCurrentUserId(),
@ -773,9 +652,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function getNextUpItemsHtml(items) {
var cardLayout = false;
return cardBuilder.getCardsHtml({
items: items,
preferThumb: true,
@ -793,29 +670,26 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function loadNextUp(elem, apiClient, userId) {
var html = '';
html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">';
if (!layoutManager.tv) {
html += '<a is="emby-linkbutton" href="' + appRouter.getRouteUrl('nextup', {
serverId: apiClient.serverId()
}) + '" class="button-flat button-flat-mini sectionTitleTextButton">';
html += '<h2 class="sectionTitle sectionTitle-cards">';
html += globalize.translate('HeaderNextUp');
html += '</h2>';
html += '<i class="md-icon">&#xE5CC;</i>';
html += '</a>';
} else {
html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate('HeaderNextUp') + '</h2>';
}
html += '</div>';
if (enableScrollX()) {
html += '<div is="emby-scroller" data-mousewheel="false" data-centerfocus="true" class="padded-top-focusscale padded-bottom-focusscale"><div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x padded-left padded-right" data-monitor="videoplayback,markplayed">';
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-mousewheel="false" data-centerfocus="true">';
html += '<div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x" data-monitor="videoplayback,markplayed">'
} else {
html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right vertical-wrap focuscontainer-x" data-monitor="videoplayback,markplayed">';
}
@ -823,7 +697,6 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
if (enableScrollX()) {
html += '</div>';
}
html += '</div>';
elem.classList.add('hide');
@ -836,29 +709,22 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function getLatestRecordingsFetchFn(serverId, activeRecordingsOnly) {
return function () {
var apiClient = connectionManager.getApiClient(serverId);
return apiClient.getLiveTvRecordings({
userId: apiClient.getCurrentUserId(),
Limit: enableScrollX() ? 12 : 5,
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
EnableTotalRecordCount: false,
IsLibraryItem: activeRecordingsOnly ? null : false,
IsInProgress: activeRecordingsOnly ? true : null
});
};
}
function getLatestRecordingItemsHtml(activeRecordingsOnly) {
return function (items) {
var cardLayout = false;
return cardBuilder.getCardsHtml({
items: items,
shape: enableScrollX() ? 'autooverflow' : 'auto',
@ -883,7 +749,6 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function loadLatestLiveTvRecordings(elem, activeRecordingsOnly, apiClient, userId) {
var title = activeRecordingsOnly ?
globalize.translate('HeaderActiveRecordings') :
globalize.translate('HeaderLatestRecordings');
@ -892,16 +757,11 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
html += '<div class="sectionTitleContainer sectionTitleContainer-cards">';
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + title + '</h2>';
if (!layoutManager.tv) {
//html += '<a href="livetv.html?tab=3" class="clearLink" style="margin-left:2em;"><button is="emby-button" type="button" class="raised more mini"><span>' + globalize.translate('More') + '</span></button></a>';
//html += '<button data-href="" type="button" is="emby-button" class="raised raised-mini sectionTitleButton btnMore">';
//html += '<span>' + globalize.translate('More') + '</span>';
//html += '</button>';
}
html += '</div>';
if (enableScrollX()) {
html += '<div is="emby-scroller" data-mousewheel="false" data-centerfocus="true" class="padded-top-focusscale padded-bottom-focusscale"><div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x padded-left padded-right">';
html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-mousewheel="false" data-centerfocus="true">';
html += '<div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x">'
} else {
html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right vertical-wrap focuscontainer-x">';
}
@ -909,7 +769,6 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
if (enableScrollX()) {
html += '</div>';
}
html += '</div>';
elem.classList.add('hide');

View file

@ -714,12 +714,10 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
};
self.stop = function (destroyPlayer) {
var elem = self._mediaElement;
var src = self._currentSrc;
if (elem) {
if (src) {
elem.pause();
}
@ -737,7 +735,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
};
self.destroy = function () {
htmlMediaHelper.destroyHlsPlayer(self);
htmlMediaHelper.destroyFlvPlayer(self);
@ -746,11 +743,9 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
var videoElement = self._mediaElement;
if (videoElement) {
self._mediaElement = null;
destroyCustomTrack(videoElement);
videoElement.removeEventListener('timeupdate', onTimeUpdate);
videoElement.removeEventListener('ended', onEnded);
videoElement.removeEventListener('volumechange', onVolumeChange);
@ -765,9 +760,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
var dlg = videoDialog;
if (dlg) {
videoDialog = null;
dlg.parentNode.removeChild(dlg);
}
@ -781,8 +774,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
}
function onTimeUpdate(e) {
// Get the player position + the transcoding offset
// get the player position and the transcoding offset
var time = this.currentTime;
if (time && !self._timeUpdated) {
@ -804,13 +796,11 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
}
function onVolumeChange() {
htmlMediaHelper.saveVolume(this.volume);
events.trigger(self, 'volumechange');
}
function onNavigatedToOsd() {
var dlg = videoDialog;
if (dlg) {
dlg.classList.remove('videoPlayerContainer-withBackdrop');
@ -819,8 +809,8 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
onStartedAndNavigatedToOsd();
}
}
function onStartedAndNavigatedToOsd() {
function onStartedAndNavigatedToOsd() {
// If this causes a failure during navigation we end up in an awkward UI state
setCurrentTrackElement(subtitleTrackIndexToSetOnPlaying);
@ -830,7 +820,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
}
function onPlaying(e) {
if (!self._started) {
self._started = true;
this.removeAttribute('controls');
@ -855,7 +844,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
}
function onPlay(e) {
events.trigger(self, 'unpause');
}
@ -865,7 +853,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
}
if (elem.videoWidth === 0 && elem.videoHeight === 0) {
var mediaSource = (self._currentPlayOptions || {}).mediaSource;
// Only trigger this if there is media info
@ -875,10 +862,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
return;
}
}
//if (elem.audioTracks && !elem.audioTracks.length) {
// htmlMediaHelper.onErrorInternal(self, 'mediadecodeerror');
//}
}
function onClick() {
@ -894,7 +877,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
}
function onError() {
var errorCode = this.error ? (this.error.code || 0) : 0;
var errorMessage = this.error ? (this.error.message || '') : '';
console.log('Media element error: ' + errorCode.toString() + ' ' + errorMessage);
@ -933,7 +915,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
}
function destroyCustomTrack(videoElement) {
if (self._resizeObserver) {
self._resizeObserver.disconnect();
self._resizeObserver = null;
@ -975,18 +956,14 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
self.destroyCustomTrack = destroyCustomTrack;
function fetchSubtitlesUwp(track, item) {
return Windows.Storage.StorageFile.getFileFromPathAsync(track.Path).then(function (storageFile) {
return Windows.Storage.FileIO.readTextAsync(storageFile).then(function (text) {
return JSON.parse(text);
});
});
}
function fetchSubtitles(track, item) {
if (window.Windows && itemHelper.isLocalItem(item)) {
return fetchSubtitlesUwp(track, item);
}
@ -1016,7 +993,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
return;
}
// if already playing thids track, skip
// skip if already playing this track
if (customTrackIndex === track.Index) {
return;
}
@ -1077,10 +1054,8 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
}
function onVideoResize() {
if (browser.iOS) {
// with wkwebview, the new sizes will be delayed for about 500ms
// the new sizes will be delayed for about 500ms with wkwebview
setTimeout(resetVideoRendererSize, 500);
} else {
resetVideoRendererSize();
@ -1127,7 +1102,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
}
function renderSubtitlesWithCustomElement(videoElement, track, item) {
fetchSubtitles(track, item).then(function (data) {
if (!videoSubtitlesElem) {
var subtitlesContainer = document.createElement('div');
@ -1142,14 +1116,10 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
}
function setSubtitleAppearance(elem, innerElem) {
require(['userSettings', 'subtitleAppearanceHelper'], function (userSettings, subtitleAppearanceHelper) {
subtitleAppearanceHelper.applyStyles({
text: innerElem,
window: elem
}, userSettings.getSubtitleAppearanceSettings());
});
}
@ -1206,7 +1176,8 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
var trackElement = null;
var expectedId = 'manualTrack' + track.Index;
var allTracks = videoElement.textTracks; // get list of tracks
// get list of tracks
var allTracks = videoElement.textTracks;
for (var i = 0; i < allTracks.length; i++) {
var currentTrack = allTracks[i];
@ -1379,9 +1350,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
var tracks = self._mediaElement.querySelectorAll('track');
for (i = 0; i < tracks.length; i++) {
track = tracks[i];
track.src = replaceQueryString(track.src, 'startPositionTicks', startPositionTicks);
}
}
@ -1478,9 +1447,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
});
} else {
if (options.backdropUrl) {
dlg.classList.add('videoPlayerContainer-withBackdrop');
dlg.style.backgroundImage = "url('" + options.backdropUrl + "')";
}
@ -1492,12 +1459,10 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
}
HtmlVideoPlayer.prototype.canPlayMediaType = function (mediaType) {
return (mediaType || '').toLowerCase() === 'video';
};
HtmlVideoPlayer.prototype.supportsPlayMethod = function (playMethod, item) {
if (appHost.supportsPlayMethod) {
return appHost.supportsPlayMethod(playMethod, item);
}
@ -1506,7 +1471,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
};
HtmlVideoPlayer.prototype.getDeviceProfile = function (item, options) {
var instance = this;
return getDeviceProfileInternal(item, options).then(function (profile) {
instance._lastProfile = profile;
@ -1523,6 +1487,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
}
var supportedFeatures;
function getSupportedFeatures() {
var list = [];
@ -1530,9 +1495,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
var video = document.createElement('video');
if (video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === "function" || document.pictureInPictureEnabled) {
list.push('PictureInPicture');
}
else if (browser.ipad) {
} else if (browser.ipad) {
// Unfortunately this creates a false positive on devices where its' not actually supported
if (navigator.userAgent.toLowerCase().indexOf('os 9') === -1) {
if (video.webkitSupportsPresentationMode && video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === "function") {
@ -1540,7 +1503,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
}
}
} else if (window.Windows) {
if (Windows.UI.ViewManagement.ApplicationView.getForCurrentView().isViewModeSupported(Windows.UI.ViewManagement.ApplicationViewMode.compactOverlay)) {
list.push('PictureInPicture');
}
@ -1552,7 +1514,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
}
HtmlVideoPlayer.prototype.supports = function (feature) {
if (!supportedFeatures) {
supportedFeatures = getSupportedFeatures();
}
@ -1593,7 +1554,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
};
HtmlVideoPlayer.prototype.canSetAudioStreamIndex = function (index) {
if (browser.tizen || browser.orsay) {
return true;
}
@ -1624,8 +1584,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
document.exitPictureInPicture().catch(onPictureInPictureError);
}
}
}
else if (window.Windows) {
} else if (window.Windows) {
this.isPip = isEnabled;
if (isEnabled) {
@ -1634,25 +1593,20 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
else {
Windows.UI.ViewManagement.ApplicationView.getForCurrentView().tryEnterViewModeAsync(Windows.UI.ViewManagement.ApplicationViewMode.default);
}
}
else {
if (video) {
if (video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === "function") {
} else {
if (video && video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === "function") {
video.webkitSetPresentationMode(isEnabled ? "picture-in-picture" : "inline");
}
}
}
};
HtmlVideoPlayer.prototype.isPictureInPictureEnabled = function () {
if (document.pictureInPictureEnabled) {
return document.pictureInPictureElement ? true : false;
}
else if (window.Windows) {
} else if (window.Windows) {
return this.isPip || false;
}
else {
} else {
var video = this._mediaElement;
if (video) {
return video.webkitPresentationMode === "picture-in-picture";
@ -1667,7 +1621,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
var elem = this._mediaElement;
if (elem) {
val = Math.max(0, val);
val = Math.min(100, val);
@ -1683,9 +1636,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
};
HtmlVideoPlayer.prototype.getBrightness = function () {
var elem = this._mediaElement;
if (elem) {
var val = elem.brightnessValue;
return val == null ? 100 : val;
@ -1758,7 +1709,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
HtmlVideoPlayer.prototype.getVolume = function () {
var mediaElement = this._mediaElement;
if (mediaElement) {
return Math.min(Math.round(mediaElement.volume * 100), 100);
}
};
@ -1772,7 +1722,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
};
HtmlVideoPlayer.prototype.setMute = function (mute) {
var mediaElement = this._mediaElement;
if (mediaElement) {
mediaElement.muted = mute;
@ -1792,12 +1741,10 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
};
HtmlVideoPlayer.prototype.getAspectRatio = function () {
return this._currentAspectRatio;
};
HtmlVideoPlayer.prototype.getSupportedAspectRatios = function () {
return [];
};
@ -1808,7 +1755,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
HtmlVideoPlayer.prototype.getBufferedRanges = function () {
var mediaElement = this._mediaElement;
if (mediaElement) {
return htmlMediaHelper.getBufferedRanges(this, mediaElement);
}

View file

@ -10,15 +10,16 @@
<div class="flex align-items-center justify-content-center flex-wrap-wrap" style="margin: 2em 0;">
<div style="margin: 0;">
<label for="selectImageProvider" style="display: inline-block;">${LabelSource}</label>
<select id="selectImageProvider" style="padding-left:.5em;padding-right:0;display: inline-block;width:auto!important;">
<div class="selectContainer">
<select id="selectImageProvider" name="selectImageProvider" is="emby-select" label="${LabelSource}">
<option value="">${All}</option>
</select>
</div>
</div>
<div style="margin-left:1em;">
<label for="selectBrowsableImageType" style="display: inline-block;">${LabelType}</label>
<select id="selectBrowsableImageType" style="padding-left:.5em;padding-right:0;display: inline-block;width:auto!important;">
<div class="selectContainer">
<select id="selectBrowsableImageType" name="selectBrowsableImageType" is="emby-select" label="${LabelType}">
<option value="Primary">${Primary}</option>
<option value="Art">${Art}</option>
<option value="Backdrop">${Backdrop}</option>
@ -32,6 +33,7 @@
<option value="Thumb">${Thumb}</option>
</select>
</div>
</div>
<div class="availableImagesPaging" style="margin-left:1em;"></div>
<label style="margin: 0 0 0 1em;width:auto;">
<input id="chkAllLanguages" type="checkbox" is="emby-checkbox" />

View file

@ -0,0 +1,36 @@
define(['inputmanager', 'focusManager'], function(inputmanager, focusManager) {
'use strict';
console.log("keyboardnavigation");
function enable() {
document.addEventListener('keydown', function(e) {
var capture = true;
switch (e.keyCode) {
case 37: // ArrowLeft
inputmanager.handle('left');
break;
case 38: // ArrowUp
inputmanager.handle('up');
break;
case 39: // ArrowRight
inputmanager.handle('right');
break;
case 40: // ArrowDown
inputmanager.handle('down');
break;
default:
capture = false;
}
if (capture) {
console.log("Disabling default event handling");
e.preventDefault();
}
});
}
return {
enable: enable,
};
});

View file

@ -160,9 +160,7 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir
}
function getIconUrl(name) {
name = name || 'notificationicon.png';
return require.toUrl('.').split('?')[0] + '/' + name;
}

View file

@ -919,14 +919,10 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla
events.trigger(self, 'pairing');
promise.then(function () {
events.trigger(self, 'paired');
setCurrentPlayerInternal(player, targetInfo);
}, function () {
events.trigger(self, 'pairerror');
if (currentPairingId === targetInfo.id) {
currentPairingId = null;
}

View file

@ -136,8 +136,7 @@ define(['connectionManager', 'actionsheet', 'datetime', 'playbackManager', 'glob
}
function showAspectRatioMenu(player, btn) {
// Each has name/id
// each has a name and id
var currentId = playbackManager.getAspectRatio(player);
var menuItems = playbackManager.getSupportedAspectRatios(player).map(function (i) {
return {
@ -148,12 +147,9 @@ define(['connectionManager', 'actionsheet', 'datetime', 'playbackManager', 'glob
});
return actionsheet.show({
items: menuItems,
positionTo: btn
}).then(function (id) {
if (id) {
playbackManager.setAspectRatio(id, player);
return Promise.resolve();
@ -164,15 +160,11 @@ define(['connectionManager', 'actionsheet', 'datetime', 'playbackManager', 'glob
}
function showWithUser(options, player, user) {
var supportedCommands = playbackManager.getSupportedCommands(player);
var mediaType = options.mediaType;
var menuItems = [];
if (supportedCommands.indexOf('SetAspectRatio') !== -1) {
var currentAspectRatioId = playbackManager.getAspectRatio(player);
var currentAspectRatio = playbackManager.getSupportedAspectRatios(player).filter(function (i) {
return i.id === currentAspectRatioId;
@ -205,19 +197,18 @@ define(['connectionManager', 'actionsheet', 'datetime', 'playbackManager', 'glob
});
}
if (options.stats) {
if (options.suboffset) {
menuItems.push({
name: globalize.translate('PlaybackData'),
id: 'stats',
name: globalize.translate('SubtitleOffset'),
id: 'suboffset',
asideText: null
});
}
if (options.suboffset) {
if (options.stats) {
menuItems.push({
name: globalize.translate('SubtitleOffset'),
id: 'suboffset',
name: globalize.translate('PlaybackData'),
id: 'stats',
asideText: null
});
}

View file

@ -41,7 +41,7 @@
<div class="verticalSection verticalSection-extrabottompadding">
<h2 class="sectionTitle">
${Advanced}
${TabAdvanced}
</h2>
<div class="checkboxContainer checkboxContainer-withDescription cinemaModeOptions">
<label>

View file

@ -194,7 +194,7 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa
var isChecked = !button.querySelector('i').classList.contains('recordingIcon-active');
if (isChecked) {
context.querySelector('.recordSeriesContainer').classList.remove('hide');
options.parent.querySelector('.recordSeriesContainer').classList.remove('hide');
if (!this.SeriesTimerId) {
var promise = this.TimerId ?
recordingHelper.changeRecordingToSeries(apiClient, this.TimerId, options.programId) :

View file

@ -299,13 +299,10 @@ define(['browser', 'layoutManager', 'dom', 'focusManager', 'ResizeObserver', 'sc
}
// Start animation rendering
if (newPos !== pos.dest) {
// NOTE the dependency was modified here to fix a scrollbutton issue
pos.dest = newPos;
renderAnimateWithTransform(from, newPos, immediate);
lastAnimate = now;
}
};
function setStyleProperty(elem, name, value, speed, resetTransition) {

View file

@ -5,7 +5,6 @@
</div>
<div class="searchSuggestionsList padded-left padded-right">
</div>
</div>
@ -13,7 +12,7 @@
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Movies}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
<div is="emby-itemscontainer" class="focuscontainer-x itemsContainer scrollSlider"></div>
</div>
</div>
@ -21,7 +20,7 @@
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Shows}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
<div is="emby-itemscontainer" class="focuscontainer-x itemsContainer scrollSlider"></div>
</div>
</div>
@ -29,7 +28,7 @@
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Episodes}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
<div is="emby-itemscontainer" class="focuscontainer-x itemsContainer scrollSlider"></div>
</div>
</div>
@ -37,7 +36,7 @@
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Sports}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
<div is="emby-itemscontainer" class="focuscontainer-x itemsContainer scrollSlider"></div>
</div>
</div>
@ -45,7 +44,7 @@
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Kids}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
<div is="emby-itemscontainer" class="focuscontainer-x itemsContainer scrollSlider"></div>
</div>
</div>
@ -53,7 +52,7 @@
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${News}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
<div is="emby-itemscontainer" class="focuscontainer-x itemsContainer scrollSlider"></div>
</div>
</div>
@ -61,7 +60,7 @@
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Programs}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
<div is="emby-itemscontainer" class="focuscontainer-x itemsContainer scrollSlider"></div>
</div>
</div>
@ -69,7 +68,7 @@
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Videos}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
<div is="emby-itemscontainer" class="focuscontainer-x itemsContainer scrollSlider"></div>
</div>
</div>
@ -77,7 +76,7 @@
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Playlists}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
<div is="emby-itemscontainer" class="focuscontainer-x itemsContainer scrollSlider"></div>
</div>
</div>
@ -85,7 +84,7 @@
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Artists}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
<div is="emby-itemscontainer" class="focuscontainer-x itemsContainer scrollSlider"></div>
</div>
</div>
@ -93,7 +92,7 @@
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Albums}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
<div is="emby-itemscontainer" class="focuscontainer-x itemsContainer scrollSlider"></div>
</div>
</div>
@ -101,7 +100,7 @@
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Songs}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
<div is="emby-itemscontainer" class="focuscontainer-x itemsContainer scrollSlider"></div>
</div>
</div>
@ -109,7 +108,7 @@
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${HeaderPhotoAlbums}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
<div is="emby-itemscontainer" class="focuscontainer-x itemsContainer scrollSlider"></div>
</div>
</div>
@ -117,7 +116,7 @@
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Photos}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
<div is="emby-itemscontainer" class="focuscontainer-x itemsContainer scrollSlider"></div>
</div>
</div>
@ -125,7 +124,7 @@
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${HeaderAudioBooks}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
<div is="emby-itemscontainer" class="focuscontainer-x itemsContainer scrollSlider"></div>
</div>
</div>
@ -133,7 +132,7 @@
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${Books}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
<div is="emby-itemscontainer" class="focuscontainer-x itemsContainer scrollSlider"></div>
</div>
</div>
@ -141,6 +140,6 @@
<h2 class="sectionTitle sectionTitle-cards focuscontainer-x padded-left padded-right">${People}</h2>
<div is="emby-scroller" data-horizontal="true" data-centerfocus="card" data-mousewheel="false" class="padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="focuscontainer-x padded-left padded-right itemsContainer scrollSlider"></div>
<div is="emby-itemscontainer" class="focuscontainer-x itemsContainer scrollSlider"></div>
</div>
</div>

View file

@ -22,11 +22,7 @@ html {
.skinHeader.semiTransparent {
-webkit-backdrop-filter: none !important;
backdrop-filter: none !important;
background-color: rgba(0, 0, 0, .3);
background: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, .6)), to(rgba(0, 0, 0, 0)));
background: -webkit-linear-gradient(rgba(0, 0, 0, .6), rgba(0, 0, 0, 0));
background: -o-linear-gradient(rgba(0, 0, 0, .6), rgba(0, 0, 0, 0));
background: linear-gradient(rgba(0, 0, 0, .6), rgba(0, 0, 0, 0))
background-color: rgba(0, 0, 0, 0.4);
}
.pageTitleWithDefaultLogo {

View file

@ -22,11 +22,7 @@ html {
.skinHeader.semiTransparent {
-webkit-backdrop-filter: none !important;
backdrop-filter: none !important;
background-color: rgba(0, 0, 0, .3);
background: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, .6)), to(rgba(0, 0, 0, 0)));
background: -webkit-linear-gradient(rgba(0, 0, 0, .6), rgba(0, 0, 0, 0));
background: -o-linear-gradient(rgba(0, 0, 0, .6), rgba(0, 0, 0, 0));
background: linear-gradient(rgba(0, 0, 0, .6), rgba(0, 0, 0, 0))
background-color: rgba(0, 0, 0, 0.4);
}
.pageTitleWithDefaultLogo {

View file

@ -35,11 +35,7 @@ html {
.skinHeader.semiTransparent {
-webkit-backdrop-filter: none !important;
backdrop-filter: none !important;
background-color: rgba(0, 0, 0, .3);
background: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, .6)), to(rgba(0, 0, 0, 0)));
background: -webkit-linear-gradient(rgba(0, 0, 0, .6), rgba(0, 0, 0, 0));
background: -o-linear-gradient(rgba(0, 0, 0, .6), rgba(0, 0, 0, 0));
background: linear-gradient(rgba(0, 0, 0, .6), rgba(0, 0, 0, 0))
background-color: rgba(0, 0, 0, 0.4);
}
.pageTitleWithDefaultLogo {

View file

@ -39,7 +39,7 @@ html {
.dialog,
html {
background-color: #0e0f2d
background-color: #230c33
}
.backgroundContainer {
@ -59,13 +59,13 @@ html {
}
.paper-icon-button-light:hover {
color: #48C3C8;
color: rgb(12, 232, 214);
background-color: rgba(0,164,220, .2);
transition: 0.2s;
}
.paper-icon-button-light:focus {
color: #48C3C8;
color: #ff77f1;
}
progress {
@ -87,41 +87,100 @@ progress::-webkit-progress-value {
.fab,
.raised {
background: rgba(0, 0, 0, .5);
color: rgba(255, 255, 255, .87)
color: rgba(255, 255, 255, .87);
}
.fab:focus,
.raised:focus {
background: rgba(0, 0, 0, .7)
background: #ff77f1
}
.button-submit {
background: #48C3C8;
color: #f8f8fe
div[data-role=controlgroup] a.ui-btn-active {
background: #55828b !important;
color: #e1e5f2 !important
}
.button-submit:hover {
background: #0ce8d6;
color: #f8f8fe
a[data-role=button] {
background: rgba(2, 43, 58, 0.521) !important;
}
#btnDeleteImage,
.submit,
.btnBrowse,
.mini,
.btnRefresh,
.btnManual,
.button-submit,
.viewTabButton,
.button-alt,
.btnOption {
background: rgb(72, 195, 200);
color: rgb(225, 229, 242)
}
#btnResetPassword:hover,
#btnRestart:hover,
#btnDeleteImage:hover,
#btnShutdown:hover,
.button-cancel:hover,
.fab:hover,
.raised:hover,
.alphaPickerButton:hover,
.submit:hover,
.btnBrowse:hover,
.mini:hover,
.btnRefresh:hover,
.button-submit:hover,
.viewTabButton:hover,
.button-alt:hover,
.btnOption:hover,
.btnManual:hover,
.block:hover {
background: rgb(12, 232, 214);
color: rgba(255, 255, 255, .87)
}
.button-submit:focus {
background: #ff77f1
}
#btnResetPassword,
.btnForgotPassword,
.btnCancel,
.button-cancel {
background: rgba(0, 0, 0, .5);
color: rgba(255, 255, 255, .87);
}
.itemName {
color: #f1f7ee
}
.textareaLabel,
.sectionTitle,
.fieldDescription,
.checkboxLabel {
color: #f1f7ee
}
.checkboxLabel {
color: inherit
}
.selectLabel,
.checkboxLabel,
.checkboxListLabel,
.inputLabel,
.inputLabelUnfocused,
.paperListLabel,
.textareaLabelUnfocused {
color: #bbb;
color: rgba(255, 255, 255, .7)
color: rgb(191, 219, 247);
}
.inputLabelFocused,
.selectLabelFocused,
.textareaLabelFocused {
color: #48C3C8
color: #ff77f1
}
.checkboxOutline {
@ -238,7 +297,7 @@ progress::-webkit-progress-value {
}
.alphaPickerButton-tv:focus {
background: #0ce8d6;
background: #ff77f1;
color: #f8f8fe !important
}
@ -285,7 +344,7 @@ progress::-webkit-progress-value {
.emby-input:focus,
.emby-textarea:focus {
border-color: #48C3C8
border-color: #ff77f1
}
.emby-select-withcolor {
@ -300,29 +359,33 @@ progress::-webkit-progress-value {
}
.emby-select-withcolor:focus {
border-color: #48C3C8 !important
border-color: #ff77f1 !important
}
.emby-select-tv-withcolor:focus {
background-color: #48C3C8 !important;
background-color: #ff77f1 !important;
color: #fff !important
}
.emby-checkbox:checked+span+.checkboxOutline {
border-color: #48C3C8
background-color: #030322;
border:2px solid rgb(72, 195, 200);
}
.emby-checkbox:focus+span+.checkboxOutline {
border-color: #fff;
.emby-checkbox:checked + span + .checkboxOutline > .checkboxIcon-checked {
color: rgb(12, 232, 214);
}
.emby-checkbox:focus:not(:checked)+span+.checkboxOutline {
border-color: #48C3C8;
border:2px solid #ff77f1;
}
.emby-checkbox:focus+span+.checkboxOutline {
border-color: #ff77f1;
}
.emby-checkbox:checked+span+.checkboxOutline,
.itemProgressBarForeground {
background-color: #48C3C8
background-color: rgb(12, 232, 214);
}
.itemProgressBarForeground-recording {
@ -332,7 +395,7 @@ progress::-webkit-progress-value {
.countIndicator,
.fullSyncIndicator,
.playedIndicator {
background: #48C3C8
background: rgb(12, 232, 214);
}
.fullSyncIndicator {
@ -341,12 +404,11 @@ progress::-webkit-progress-value {
.mainDrawer {
color: #f8f8fe;
background: rgba(0, 0, 0, .5);
background: rgba(0, 0, 0, .5)
}
.drawer-open {
background-color: #030322
}
.navMenuOption:hover {
@ -359,7 +421,7 @@ progress::-webkit-progress-value {
}
.emby-button-focusscale:focus {
background: #48C3C8;
background: #8ae9c1;
color: #f8f8fe
}
@ -377,7 +439,7 @@ progress::-webkit-progress-value {
}
.emby-tab-button.emby-button-tv:focus {
color: #48C3C8;
color: #ff77f1;
background: 0 0
}
@ -429,7 +491,7 @@ progress::-webkit-progress-value {
.guide-date-tab-button.emby-tab-button-active,
.guide-date-tab-button:focus {
color: #48C3C8
color: #ff77f1
}
.guide-date-tab-button.emby-button-tv:focus {
@ -470,11 +532,17 @@ progress::-webkit-progress-value {
}
.card:focus .card-focuscontent {
border-color: #48C3C8
border-color: #ff77f1
}
.layout-desktop,
.scrollY {
scrollbar-width: thin;
scrollbar-color: #888 rgba(59, 59, 59, 0.5)
}
.layout-desktop ::-webkit-scrollbar {
width: 1em;
width: .4em;
height: 1em
}
@ -483,7 +551,7 @@ progress::-webkit-progress-value {
}
::-webkit-scrollbar-track-piece {
background-color: #3b3b3b
background-color: rgba(59, 59, 59, 0.5)
}
::-webkit-scrollbar-thumb:horizontal,

View file

@ -8,8 +8,7 @@
flex-direction: column;
will-change: transform, opacity;
transition: opacity 300ms ease-out;
background-color: rgba(0, 0, 0, .7);
background: linear-gradient(rgba(0, 0, 0, .5), rgba(0, 0, 0, .9));
background-color: rgba(0, 0, 0, 0.7);
color: #fff;
user-select: none;
-webkit-touch-callout: none;

View file

@ -4,14 +4,15 @@ define(["datetime", "loading", "libraryMenu", "dom", "globalize", "emby-button"]
function revoke(page, key) {
require(["confirm"], function(confirm) {
confirm(globalize.translate("MessageConfirmRevokeApiKey"), globalize.translate("HeaderConfirmRevokeApiKey")).then(function() {
loading.show(), ApiClient.ajax({
loading.show();
ApiClient.ajax({
type: "DELETE",
url: ApiClient.getUrl("Auth/Keys/" + key)
}).then(function() {
loadData(page)
})
})
})
loadData(page);
});
});
});
}
function renderKeys(page, keys) {
@ -21,13 +22,15 @@ define(["datetime", "loading", "libraryMenu", "dom", "globalize", "emby-button"]
var date = datetime.parseISO8601Date(item.DateCreated, !0);
return html += datetime.toLocaleDateString(date) + " " + datetime.getDisplayTime(date), html += "</td>", html += "</tr>"
}).join("");
page.querySelector(".resultBody").innerHTML = rows, loading.hide()
page.querySelector(".resultBody").innerHTML = rows;
loading.hide();
}
function loadData(page) {
loading.show(), ApiClient.getJSON(ApiClient.getUrl("Auth/Keys")).then(function(result) {
renderKeys(page, result.Items)
})
loading.show();
ApiClient.getJSON(ApiClient.getUrl("Auth/Keys")).then(function(result) {
renderKeys(page, result.Items);
});
}
function showNewKeyPrompt(page) {
@ -49,24 +52,18 @@ define(["datetime", "loading", "libraryMenu", "dom", "globalize", "emby-button"]
})
}
function getTabs() {
return [{
href: "dashboardhosting.html",
name: globalize.translate("TabHosting")
}, {
href: "serversecurity.html",
name: globalize.translate("TabSecurity")
}]
}
pageIdOn("pageinit", "serverSecurityPage", function() {
pageIdOn("pageinit", "apiKeysPage", function() {
var page = this;
page.querySelector(".btnNewKey").addEventListener("click", function() {
showNewKeyPrompt(page)
}), page.querySelector(".tblApiKeys").addEventListener("click", function(e) {
});
page.querySelector(".tblApiKeys").addEventListener("click", function(e) {
var btnRevoke = dom.parentWithClass(e.target, "btnRevoke");
btnRevoke && revoke(page, btnRevoke.getAttribute("data-token"))
})
}), pageIdOn("pagebeforeshow", "serverSecurityPage", function() {
libraryMenu.setTabs("adminadvanced", 1, getTabs), loadData(this)
});
});
pageIdOn("pagebeforeshow", "apiKeysPage", function() {
loadData(this);
})
});

View file

@ -1,4 +1,4 @@
define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globalize", "loading", "connectionManager", "playMethodHelper", "cardBuilder", "imageLoader", "components/activitylog", "humanedate", "listViewStyle", "emby-button", "flexStyles", "emby-button", "emby-itemscontainer"], function (datetime, events, itemHelper, serverNotifications, dom, globalize, loading, connectionManager, playMethodHelper, cardBuilder, imageLoader, ActivityLog) {
define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globalize", "loading", "connectionManager", "playMethodHelper", "cardBuilder", "imageLoader", "components/activitylog", "scripts/imagehelper", "humanedate", "listViewStyle", "emby-button", "flexStyles", "emby-button", "emby-itemscontainer"], function (datetime, events, itemHelper, serverNotifications, dom, globalize, loading, connectionManager, playMethodHelper, cardBuilder, imageLoader, ActivityLog, imageHelper) {
"use strict";
function buttonEnabled(elem, enabled) {
@ -622,17 +622,8 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
}
},
getClientImage: function (connection) {
var iconUrl = (connection.Client.toLowerCase(), connection.DeviceName.toLowerCase(), connection.AppIconUrl);
if (iconUrl) {
if (-1 === iconUrl.indexOf("://")) {
iconUrl = ApiClient.getUrl(iconUrl);
}
var iconUrl = imageHelper.getDeviceIcon(connection.DeviceName);
return "<img src='" + iconUrl + "' />";
}
return null;
},
getNowPlayingImageUrl: function (item) {
if (item && item.BackdropImageTags && item.BackdropImageTags.length) {

View file

@ -1,4 +1,4 @@
define(["loading", "dom", "libraryMenu", "globalize", "humanedate", "emby-button", "emby-itemscontainer", "cardStyle"], function(loading, dom, libraryMenu, globalize) {
define(["loading", "dom", "libraryMenu", "globalize", "scripts/imagehelper", "humanedate", "emby-button", "emby-itemscontainer", "cardStyle"], function(loading, dom, libraryMenu, globalize, imageHelper) {
"use strict";
function canDelete(deviceId) {
@ -57,10 +57,45 @@ define(["loading", "dom", "libraryMenu", "globalize", "humanedate", "emby-button
var html = "";
html += devices.map(function(device) {
var deviceHtml = "";
deviceHtml += "<div data-id='" + device.Id + "' class='card backdropCard'>", deviceHtml += '<div class="cardBox visualCardBox">', deviceHtml += '<div class="cardScalable">', deviceHtml += '<div class="cardPadder cardPadder-backdrop"></div>', deviceHtml += '<a is="emby-linkbutton" href="' + (canEdit ? "device.html?id=" + device.Id : "#") + '" class="cardContent cardImageContainer">';
var iconUrl = device.IconUrl;
return iconUrl && -1 === iconUrl.indexOf("://") && (iconUrl = ApiClient.getUrl(iconUrl)), iconUrl ? (deviceHtml += '<div class="cardImage" style="background-image:url(\'' + iconUrl + "');background-size: auto 64%;background-position:center center;\">", deviceHtml += "</div>") : deviceHtml += '<i class="cardImageIcon md-icon">tablet_android</i>', deviceHtml += "</a>", deviceHtml += "</div>", deviceHtml += '<div class="cardFooter">', (canEdit || canDelete(device.Id)) && (deviceHtml += '<div style="text-align:right; float:right;padding-top:5px;">', deviceHtml += '<button type="button" is="paper-icon-button-light" data-id="' + device.Id + '" title="' + globalize.translate("Menu") + '" class="btnDeviceMenu"><i class="md-icon">&#xE5D3;</i></button>', deviceHtml += "</div>"), deviceHtml += "<div class='cardText'>", deviceHtml += device.Name, deviceHtml += "</div>", deviceHtml += "<div class='cardText cardText-secondary'>", deviceHtml += device.AppName + " " + device.AppVersion, deviceHtml += "</div>", deviceHtml += "<div class='cardText cardText-secondary'>", device.LastUserName && (deviceHtml += device.LastUserName, deviceHtml += ", " + humane_date(device.DateLastActivity)), deviceHtml += "&nbsp;", deviceHtml += "</div>", deviceHtml += "</div>", deviceHtml += "</div>", deviceHtml += "</div>"
}).join(""), page.querySelector(".devicesList").innerHTML = html
deviceHtml += "<div data-id='" + device.Id + "' class='card backdropCard'>";
deviceHtml += '<div class="cardBox visualCardBox">';
deviceHtml += '<div class="cardScalable">';
deviceHtml += '<div class="cardPadder cardPadder-backdrop"></div>';
deviceHtml += '<a is="emby-linkbutton" href="' + (canEdit ? "device.html?id=" + device.Id : "#") + '" class="cardContent cardImageContainer">';
var iconUrl = imageHelper.getDeviceIcon(device.Name);
if (iconUrl) {
deviceHtml += '<div class="cardImage" style="background-image:url(\'' + iconUrl + "');background-size: auto 64%;background-position:center center;\">";
deviceHtml += "</div>";
} else {
deviceHtml += '<i class="cardImageIcon md-icon">tablet_android</i>';
}
deviceHtml += "</a>";
deviceHtml += "</div>";
deviceHtml += '<div class="cardFooter">';
if (canEdit || canDelete(device.Id)) {
deviceHtml += '<div style="text-align:right; float:right;padding-top:5px;">';
deviceHtml += '<button type="button" is="paper-icon-button-light" data-id="' + device.Id + '" title="' + globalize.translate("Menu") + '" class="btnDeviceMenu"><i class="md-icon">&#xE5D3;</i></button>';
deviceHtml += "</div>";
}
deviceHtml += "<div class='cardText'>";
deviceHtml += device.Name;
deviceHtml += "</div>";
deviceHtml += "<div class='cardText cardText-secondary'>";
deviceHtml += device.AppName + " " + device.AppVersion;
deviceHtml += "</div>";
deviceHtml += "<div class='cardText cardText-secondary'>";
if (device.LastUserName) {
deviceHtml += device.LastUserName;
deviceHtml += ", " + humane_date(device.DateLastActivity);
}
deviceHtml += "&nbsp;";
deviceHtml += "</div>";
deviceHtml += "</div>";
deviceHtml += "</div>";
deviceHtml += "</div>";
return deviceHtml;
}).join("");
page.querySelector(".devicesList").innerHTML = html;
}
function loadData(page) {

View file

@ -256,8 +256,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in
currentType = profile.Type;
}
html += "<li>";
html += '<a data-profileindex="' + i__y + '" class="lnkEditSubProfile" is="emby-linkbutton" href="#">';
html += "<div>";
html += '<a is="emby-linkbutton" href="#" class="lnkEditSubProfile" data-profileindex="' + i__y + '">';
html += "<p>" + Globalize.translate("ValueContainer").replace("{0}", profile.Container || allText) + "</p>";
if ("Video" == profile.Type) {
@ -270,8 +270,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in
}
html += "</a>";
html += '<a is="emby-linkbutton" href="#" data-icon="delete" class="btnDeleteProfile" data-profileindex="' + i__y + '">Delete</a>';
html += "</li>";
html += '<button type="button" is="paper-icon-button-light" class="btnDeleteProfile listItemButton" data-profileindex="' + i__y + '"><i class="md-icon">delete</i></button>';
html += "</div>";
}
html += "</ul>";
@ -316,8 +316,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in
currentType = profile.Type;
}
html += "<li>";
html += '<a data-profileindex="' + i__u + '" class="lnkEditSubProfile" is="emby-linkbutton" href="#">';
html += "<div>";
html += '<a is="emby-linkbutton" href="#" class="lnkEditSubProfile" data-profileindex="' + i__u + '">';
html += "<p>Protocol: " + (profile.Protocol || "Http") + "</p>";
html += "<p>" + Globalize.translate("ValueContainer").replace("{0}", profile.Container || allText) + "</p>";
@ -331,8 +331,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in
}
html += "</a>";
html += '<a is="emby-linkbutton" href="#" data-icon="delete" class="btnDeleteProfile" data-profileindex="' + i__u + '">Delete</a>';
html += "</li>";
html += '<button type="button" is="paper-icon-button-light" class="btnDeleteProfile listItemButton" data-profileindex="' + i__u + '"><i class="md-icon">delete</i></button>';
html += "</div>";
}
html += "</ul>";
@ -402,8 +402,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in
currentType = profile.Type;
}
html += "<li>";
html += '<a data-profileindex="' + i__i + '" class="lnkEditSubProfile" is="emby-linkbutton" href="#">';
html += "<div>";
html += '<a is="emby-linkbutton" href="#" class="lnkEditSubProfile" data-profileindex="' + i__i + '">';
html += "<p>" + Globalize.translate("ValueContainer").replace("{0}", profile.Container || allText) + "</p>";
if (profile.Conditions && profile.Conditions.length) {
@ -415,8 +415,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in
}
html += "</a>";
html += '<a is="emby-linkbutton" href="#" data-icon="delete" class="btnDeleteProfile" data-profileindex="' + i__i + '">Delete</a>';
html += "</li>";
html += '<button type="button" is="paper-icon-button-light" class="btnDeleteProfile listItemButton" data-profileindex="' + i__i + '"><i class="md-icon">delete</i></button>';
html += "</div>";
}
html += "</ul>";
@ -474,8 +474,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in
currentType = type;
}
html += "<li>";
html += '<a data-profileindex="' + i__p + '" class="lnkEditSubProfile" is="emby-linkbutton" href="#">';
html += "<div>";
html += '<a is="emby-linkbutton" href="#" class="lnkEditSubProfile" data-profileindex="' + i__p + '">';
html += "<p>" + Globalize.translate("ValueCodec").replace("{0}", profile.Codec || allText) + "</p>";
if (profile.Conditions && profile.Conditions.length) {
@ -487,8 +487,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in
}
html += "</a>";
html += '<a is="emby-linkbutton" href="#" data-icon="delete" class="btnDeleteProfile" data-profileindex="' + i__p + '">Delete</a>';
html += "</li>";
html += '<button type="button" is="paper-icon-button-light" class="btnDeleteProfile listItemButton" data-profileindex="' + i__p + '"><i class="md-icon">delete</i></button>';
html += "</div>";
}
html += "</ul>";
@ -545,8 +545,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in
currentType = profile.Type;
}
html += "<li>";
html += '<a data-profileindex="' + i__s + '" class="lnkEditSubProfile" is="emby-linkbutton" href="#">';
html += "<div>";
html += '<a is="emby-linkbutton" href="#" class="lnkEditSubProfile" data-profileindex="' + i__s + '">';
html += "<p>" + Globalize.translate("ValueContainer").replace("{0}", profile.Container || allText) + "</p>";
if ("Video" == profile.Type) {
@ -567,8 +567,8 @@ define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-in
}
html += "</a>";
html += '<a is="emby-linkbutton" href="#" data-icon="delete" class="btnDeleteProfile" data-profileindex="' + i__s + '">Delete</a>';
html += "</li>";
html += '<button type="button" is="paper-icon-button-light" class="btnDeleteProfile listItemButton" data-profileindex="' + i__s + '"><i class="md-icon">delete</i></button>';
html += "</div>";
}
html += "</ul>";

View file

@ -2,19 +2,19 @@ define(["appRouter", "cardBuilder", "dom", "globalize", "connectionManager", "ap
"use strict";
function enableScrollX() {
return !0
return true;
}
function getThumbShape() {
return enableScrollX() ? "overflowBackdrop" : "backdrop"
return enableScrollX() ? "overflowBackdrop" : "backdrop";
}
function getPosterShape() {
return enableScrollX() ? "overflowPortrait" : "portrait"
return enableScrollX() ? "overflowPortrait" : "portrait";
}
function getSquareShape() {
return enableScrollX() ? "overflowSquare" : "square"
return enableScrollX() ? "overflowSquare" : "square";
}
function getSections() {

View file

@ -322,6 +322,25 @@ define(["loading", "appRouter", "layoutManager", "connectionManager", "cardBuild
itemBirthLocation.classList.remove("hide"), itemBirthLocation.innerHTML = globalize.translate("BirthPlaceValue").replace("{0}", gmap)
} else itemBirthLocation.classList.add("hide");
setPeopleHeader(page, item), loading.hide()
try {
require(["focusManager"], function(focusManager) {
[".btnResume", ".btnPlay"].every(function (cls) {
var elems = page.querySelectorAll(cls);
for (var i = 0; i < elems.length; i++) {
if (focusManager.isCurrentlyFocusable(elems[i])) {
focusManager.focus(elems[i]);
return false;
}
}
return true;
});
});
} catch (e) {
console.log(e);
}
}
function logoImageUrl(item, apiClient, options) {

View file

@ -14,25 +14,58 @@ define(["globalize", "loading", "libraryMenu", "emby-checkbox", "emby-button", "
}, {
href: "metadatanfo.html",
name: Globalize.translate("TabNfoSettings")
}, {
href: "librarysettings.html",
name: Globalize.translate("TabAdvanced")
}]
}
return function(view, params) {
function loadData() {
ApiClient.getServerConfiguration().then(function(config) {
view.querySelector(".chkFolderView").checked = config.EnableFolderView, view.querySelector(".chkGroupMoviesIntoCollections").checked = config.EnableGroupingIntoCollections, view.querySelector(".chkDisplaySpecialsWithinSeasons").checked = config.DisplaySpecialsWithinSeasons, view.querySelector(".chkExternalContentInSuggestions").checked = config.EnableExternalContentInSuggestions
})
view.querySelector(".chkFolderView").checked = config.EnableFolderView;
view.querySelector(".chkGroupMoviesIntoCollections").checked = config.EnableGroupingIntoCollections;
view.querySelector(".chkDisplaySpecialsWithinSeasons").checked = config.DisplaySpecialsWithinSeasons;
view.querySelector(".chkExternalContentInSuggestions").checked = config.EnableExternalContentInSuggestions;
view.querySelector("#chkSaveMetadataHidden").checked = config.SaveMetadataHidden;
});
ApiClient.getNamedConfiguration("metadata").then(function(metadata) {
loadMetadataConfig(this, metadata)
});
}
function loadMetadataConfig(page, config) {
$("#selectDateAdded", page).val(config.UseFileCreationTimeForDateAdded ? "1" : "0");
}
view.querySelector("form").addEventListener("submit", function(e) {
loading.show();
var form = this;
return ApiClient.getServerConfiguration().then(function(config) {
config.EnableFolderView = form.querySelector(".chkFolderView").checked, config.EnableGroupingIntoCollections = form.querySelector(".chkGroupMoviesIntoCollections").checked, config.DisplaySpecialsWithinSeasons = form.querySelector(".chkDisplaySpecialsWithinSeasons").checked, config.EnableExternalContentInSuggestions = form.querySelector(".chkExternalContentInSuggestions").checked, ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult)
}), e.preventDefault(), !1
}), view.addEventListener("viewshow", function() {
libraryMenu.setTabs("librarysetup", 1, getTabs), loadData()
})
ApiClient.getServerConfiguration().then(function(config) {
config.EnableFolderView = form.querySelector(".chkFolderView").checked;
config.EnableGroupingIntoCollections = form.querySelector(".chkGroupMoviesIntoCollections").checked;
config.DisplaySpecialsWithinSeasons = form.querySelector(".chkDisplaySpecialsWithinSeasons").checked;
config.EnableExternalContentInSuggestions = form.querySelector(".chkExternalContentInSuggestions").checked;
config.SaveMetadataHidden = form.querySelector("#chkSaveMetadataHidden").checked;
ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult);
});
ApiClient.getNamedConfiguration("metadata").then(function(config) {
config.UseFileCreationTimeForDateAdded = "1" === $("#selectDateAdded", form).val();
ApiClient.updateNamedConfiguration("metadata", config);
});
e.preventDefault();
loading.hide();
return false;
});
view.addEventListener("viewshow", function() {
libraryMenu.setTabs("librarysetup", 1, getTabs);
loadData();
ApiClient.getSystemInfo().then(function(info) {
if ("Windows" === info.OperatingSystem) {
view.querySelector(".fldSaveMetadataHidden").classList.remove("hide");
} else {
view.querySelector(".fldSaveMetadataHidden").classList.add("hide");
}
});
});
}
});

View file

@ -1,91 +0,0 @@
define(["jQuery", "loading", "libraryMenu", "fnchecked", "emby-checkbox", "emby-button"], function($, loading, libraryMenu) {
"use strict";
function loadPage(page, config) {
$("#chkSaveMetadataHidden", page).checked(config.SaveMetadataHidden);
loading.hide();
}
function loadMetadataConfig(page, config) {
$("#selectDateAdded", page).val(config.UseFileCreationTimeForDateAdded ? "1" : "0");
}
function loadFanartConfig(page, config) {
$("#txtFanartApiKey", page).val(config.UserApiKey || "");
}
function saveFanart(form) {
ApiClient.getNamedConfiguration("fanart").then(function(config) {
config.UserApiKey = $("#txtFanartApiKey", form).val(), ApiClient.updateNamedConfiguration("fanart", config);
});
}
function saveMetadata(form) {
ApiClient.getNamedConfiguration("metadata").then(function(config) {
config.UseFileCreationTimeForDateAdded = "1" === $("#selectDateAdded", form).val(), ApiClient.updateNamedConfiguration("metadata", config);
})
}
function alertText(options) {
require(["alert"], function(alert) {
alert(options);
});
}
function onSubmit() {
loading.show();
var form = this;
ApiClient.getServerConfiguration().then(function(config) {
config.SaveMetadataHidden = $("#chkSaveMetadataHidden", form).checked();
config.FanartApiKey = $("#txtFanartApiKey", form).val();
ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult);
});
saveMetadata(form);
saveFanart(form);
return false;
}
function getTabs() {
return [{
href: "library.html",
name: Globalize.translate("HeaderLibraries")
}, {
href: "librarydisplay.html",
name: Globalize.translate("TabDisplay")
}, {
href: "metadataimages.html",
name: Globalize.translate("TabMetadata")
}, {
href: "metadatanfo.html",
name: Globalize.translate("TabNfoSettings")
}, {
href: "librarysettings.html",
name: Globalize.translate("TabAdvanced")
}]
}
return function(view, params) {
$(".librarySettingsForm").off("submit", onSubmit).on("submit", onSubmit);
view.addEventListener("viewshow", function() {
libraryMenu.setTabs("librarysetup", 4, getTabs);
loading.show();
var page = this;
ApiClient.getServerConfiguration().then(function(config) {
loadPage(page, config)
});
ApiClient.getNamedConfiguration("metadata").then(function(metadata) {
loadMetadataConfig(page, metadata)
});
ApiClient.getNamedConfiguration("fanart").then(function(metadata) {
loadFanartConfig(page, metadata)
});
ApiClient.getSystemInfo().then(function(info) {
if ("Windows" === info.OperatingSystem) {
page.querySelector(".fldSaveMetadataHidden").classList.remove("hide");
} else {
page.querySelector(".fldSaveMetadataHidden").classList.add("hide");
}
});
});
}
});

View file

@ -6,7 +6,7 @@ define(["globalize", "loading", "libraryMenu", "dom", "emby-input", "emby-button
}
function fillTypes(view, currentId) {
ApiClient.getJSON(ApiClient.getUrl("LiveTv/TunerHosts/Types")).then(function(types) {
return ApiClient.getJSON(ApiClient.getUrl("LiveTv/TunerHosts/Types")).then(function(types) {
var selectType = view.querySelector(".selectType");
var html = "";
html += types.map(function(tuner) {

View file

@ -1,4 +1,4 @@
define(["jQuery", "apphost", "scripts/taskbutton", "loading", "libraryMenu", "globalize", "dom", "indicators", "cardStyle", "emby-itemrefreshindicator"], function($, appHost, taskButton, loading, libraryMenu, globalize, dom, indicators) {
define(["jQuery", "apphost", "scripts/taskbutton", "loading", "libraryMenu", "globalize", "dom", "indicators", "scripts/imagehelper", "cardStyle", "emby-itemrefreshindicator"], function($, appHost, taskButton, loading, libraryMenu, globalize, dom, indicators, imageHelper) {
"use strict";
function addVirtualFolder(page) {
@ -217,30 +217,6 @@ define(["jQuery", "apphost", "scripts/taskbutton", "loading", "libraryMenu", "gl
}]
}
function getIcon(type) {
switch (type) {
case "movies":
return "local_movies";
case "music":
return "library_music";
case "photos":
return "photo";
case "livetv":
case "tvshows":
return "live_tv";
case "trailers":
return "local_movies";
case "homevideos":
case "musicvideos":
return "video_library";
case "books":
case "channels":
case "playlists":
default:
return "folder";
}
}
function getVirtualFolderHtml(page, virtualFolder, index) {
var html = "";
var style = "";
@ -262,7 +238,7 @@ define(["jQuery", "apphost", "scripts/taskbutton", "loading", "libraryMenu", "gl
hasCardImageContainer = true;
} else if (!virtualFolder.showNameWithIcon) {
html += '<div class="cardImageContainer editLibrary" style="cursor:pointer;">';
html += '<i class="cardImageIcon-small md-icon">' + (virtualFolder.icon || getIcon(virtualFolder.CollectionType)) + "</i>";
html += '<i class="cardImageIcon-small md-icon">' + (virtualFolder.icon || imageHelper.getLibraryIcon(virtualFolder.CollectionType)) + "</i>";
hasCardImageContainer = true;
}
if (hasCardImageContainer) {
@ -273,7 +249,7 @@ define(["jQuery", "apphost", "scripts/taskbutton", "loading", "libraryMenu", "gl
}
if (!imgUrl && virtualFolder.showNameWithIcon) {
html += '<h3 class="cardImageContainer addLibrary" style="position:absolute;top:0;left:0;right:0;bottom:0;cursor:pointer;flex-direction:column;">';
html += '<i class="cardImageIcon-small md-icon">' + (virtualFolder.icon || getIcon(virtualFolder.CollectionType)) + "</i>";
html += '<i class="cardImageIcon-small md-icon">' + (virtualFolder.icon || imageHelper.getLibraryIcon(virtualFolder.CollectionType)) + "</i>";
virtualFolder.showNameWithIcon && (html += '<div style="margin:1em 0;position:width:100%;">', html += virtualFolder.Name, html += "</div>");
html += "</h3>";
}
@ -329,11 +305,9 @@ define(["jQuery", "apphost", "scripts/taskbutton", "loading", "libraryMenu", "gl
}, {
href: "metadatanfo.html",
name: globalize.translate("TabNfoSettings")
}, {
href: "librarysettings.html",
name: globalize.translate("TabAdvanced")
}]
}
window.WizardLibraryPage = {
next: function() {
Dashboard.navigate("wizardsettings.html")

View file

@ -53,11 +53,9 @@ define(["jQuery", "dom", "loading", "libraryMenu", "listViewStyle"], function($,
}, {
href: "metadatanfo.html",
name: Globalize.translate("TabNfoSettings")
}, {
href: "librarysettings.html",
name: Globalize.translate("TabAdvanced")
}]
}
$(document).on("pageinit", "#metadataImagesConfigurationPage", function() {
$(".metadataImagesConfigurationForm").off("submit", onSubmit).on("submit", onSubmit)
}).on("pageshow", "#metadataImagesConfigurationPage", function() {

View file

@ -40,11 +40,9 @@ define(["jQuery", "loading", "libraryMenu"], function($, loading, libraryMenu) {
}, {
href: "metadatanfo.html",
name: Globalize.translate("TabNfoSettings")
}, {
href: "librarysettings.html",
name: Globalize.translate("TabAdvanced")
}]
}
var metadataKey = "xbmcmetadata";
$(document).on("pageinit", "#metadataNfoPage", function() {
$(".metadataNfoForm").off("submit", onSubmit).on("submit", onSubmit)

View file

@ -61,15 +61,6 @@ define(["loading", "libraryMenu", "globalize", "emby-checkbox", "emby-select"],
}).then(callback) : callback()
}
function getTabs() {
return [{
href: "dashboardhosting.html",
name: globalize.translate("TabHosting")
}, {
href: "serversecurity.html",
name: globalize.translate("TabSecurity")
}]
}
return function(view, params) {
function loadPage(page, config) {
page.querySelector("#txtPortNumber").value = config.HttpServerPortNumber, page.querySelector("#txtPublicPort").value = config.PublicPort, page.querySelector("#txtPublicHttpsPort").value = config.PublicHttpsPort, page.querySelector("#txtLocalAddress").value = config.LocalNetworkAddresses[0] || "", page.querySelector("#txtLanNetworks").value = (config.LocalNetworkSubnets || []).join(", "), page.querySelector("#txtExternalAddressFilter").value = (config.RemoteIPFilter || []).join(", "), page.querySelector("#selectExternalAddressFilterMode").value = config.IsRemoteIPFilterBlacklist ? "blacklist" : "whitelist", page.querySelector("#chkRemoteAccess").checked = null == config.EnableRemoteAccess || config.EnableRemoteAccess;
@ -96,10 +87,13 @@ define(["loading", "libraryMenu", "globalize", "emby-checkbox", "emby-select"],
header: globalize.translate("HeaderSelectCertificatePath")
})
})
}), view.querySelector(".dashboardHostingForm").addEventListener("submit", onSubmit), view.querySelector("#txtCertificatePath").addEventListener("change", onCertPathChange), view.addEventListener("viewshow", function(e) {
libraryMenu.setTabs("adminadvanced", 0, getTabs), loading.show(), ApiClient.getServerConfiguration().then(function(config) {
loadPage(view, config)
})
})
});
view.querySelector(".dashboardHostingForm").addEventListener("submit", onSubmit), view.querySelector("#txtCertificatePath").addEventListener("change", onCertPathChange), view.addEventListener("viewshow", function(e) {
loading.show();
ApiClient.getServerConfiguration().then(function(config) {
loadPage(view, config);
});
});
}
});

View file

@ -3,74 +3,113 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox"], function($, loading)
function loadMediaFolders(page, mediaFolders) {
var html = "";
html += '<h3 class="checkboxListLabel">' + Globalize.translate("HeaderLibraries") + "</h3>", html += '<div class="checkboxList paperList" style="padding:.5em 1em;">';
for (var i = 0, length = mediaFolders.length; i < length; i++) {
html += '<h3 class="checkboxListLabel">' + Globalize.translate("HeaderLibraries") + "</h3>";
html += '<div class="checkboxList paperList" style="padding:.5em 1em;">';
for (var i = 0; i < mediaFolders.length; i++) {
var folder = mediaFolders[i];
html += '<label><input type="checkbox" is="emby-checkbox" class="chkFolder" data-id="' + folder.Id + '" checked="checked"/><span>' + folder.Name + "</span></label>"
html += '<label><input type="checkbox" is="emby-checkbox" class="chkFolder" data-id="' + folder.Id + '" checked="checked"/><span>' + folder.Name + "</span></label>";
}
html += "</div>", $(".folderAccess", page).html(html).trigger("create"), $("#chkEnableAllFolders", page).checked(!0).trigger("change")
html += "</div>";
$(".folderAccess", page).html(html).trigger("create");
$("#chkEnableAllFolders", page).checked(true).trigger("change");
}
function loadChannels(page, channels) {
var html = "";
html += '<h3 class="checkboxListLabel">' + Globalize.translate("HeaderChannels") + "</h3>", html += '<div class="checkboxList paperList" style="padding:.5em 1em;">';
for (var i = 0, length = channels.length; i < length; i++) {
html += '<h3 class="checkboxListLabel">' + Globalize.translate("HeaderChannels") + "</h3>";
html += '<div class="checkboxList paperList" style="padding:.5em 1em;">';
for (var i = 0; i < channels.length; i++) {
var folder = channels[i];
html += '<label><input type="checkbox" is="emby-checkbox" class="chkChannel" data-id="' + folder.Id + '" checked="checked"/><span>' + folder.Name + "</span></label>"
html += '<label><input type="checkbox" is="emby-checkbox" class="chkChannel" data-id="' + folder.Id + '" checked="checked"/><span>' + folder.Name + "</span></label>";
}
html += "</div>", $(".channelAccess", page).show().html(html).trigger("create"), channels.length ? $(".channelAccessContainer", page).show() : $(".channelAccessContainer", page).hide(), $("#chkEnableAllChannels", page).checked(!0).trigger("change")
html += "</div>";
$(".channelAccess", page).show().html(html).trigger("create");
if (channels.length) {
$(".channelAccessContainer", page).show();
} else {
$(".channelAccessContainer", page).hide();
}
$("#chkEnableAllChannels", page).checked(true).trigger("change");
}
function loadUser(page) {
$("#txtUserName", page).val(""), loading.show();
var promise4 = ApiClient.getJSON(ApiClient.getUrl("Library/MediaFolders", {
IsHidden: !1
})),
promise5 = ApiClient.getJSON(ApiClient.getUrl("Channels"));
Promise.all([promise4, promise5]).then(function(responses) {
loadMediaFolders(page, responses[0].Items), loadChannels(page, responses[1].Items), loading.hide()
$("#txtUsername", page).val("");
$("#txtPassword", page).val("");
loading.show();
var promiseFolders = ApiClient.getJSON(ApiClient.getUrl("Library/MediaFolders", {
IsHidden: false
}));
var promiseChannels = ApiClient.getJSON(ApiClient.getUrl("Channels"));
Promise.all([promiseFolders, promiseChannels]).then(function(responses) {
loadMediaFolders(page, responses[0].Items);
loadChannels(page, responses[1].Items);
loading.hide();
})
}
function saveUser(page) {
var name = $("#txtUserName", page).val();
ApiClient.createUser(name).then(function(user) {
user.Policy.EnableAllFolders = $("#chkEnableAllFolders", page).checked(), user.Policy.EnabledFolders = user.Policy.EnableAllFolders ? [] : $(".chkFolder", page).get().filter(function(i) {
var user = {};
user.Name = $("#txtUsername", page).val();
user.Password = $("#txtPassword", page).val();
ApiClient.createUser(user).then(function(user) {
user.Policy.EnableAllFolders = $("#chkEnableAllFolders", page).checked();
user.Policy.EnabledFolders = [];
if (!user.Policy.EnableAllFolders) {
user.Policy.EnabledFolders = $(".chkFolder", page).get().filter(function(i) {
return i.checked
}).map(function(i) {
return i.getAttribute("data-id")
}), user.Policy.EnableAllChannels = $("#chkEnableAllChannels", page).checked(), user.Policy.EnabledChannels = user.Policy.EnableAllChannels ? [] : $(".chkChannel", page).get().filter(function(i) {
return i.getAttribute("data-id");
});
}
user.Policy.EnableAllChannels = $("#chkEnableAllChannels", page).checked();
user.Policy.EnabledChannels = [];
if (!user.Policy.EnableAllChannels) {
user.Policy.EnabledChannels = $(".chkChannel", page).get().filter(function(i) {
return i.checked
}).map(function(i) {
return i.getAttribute("data-id")
}), ApiClient.updateUserPolicy(user.Id, user.Policy).then(function() {
Dashboard.navigate("useredit.html?userId=" + user.Id)
})
return i.getAttribute("data-id");
});
}
ApiClient.updateUserPolicy(user.Id, user.Policy).then(function() {
Dashboard.navigate("useredit.html?userId=" + user.Id);
});
}, function(response) {
400 == response.status ? Dashboard.alert({
message: page.querySelector(".labelNewUserNameHelp").innerHTML
}) : require(["toast"], function(toast) {
toast(Globalize.translate("DefaultErrorMessage"))
}), loading.hide()
})
require(["toast"], function(toast) {
toast(Globalize.translate("DefaultErrorMessage"));
});
loading.hide();
});
}
function onSubmit() {
var page = $(this).parents(".page")[0];
return loading.show(), saveUser(page), !1
loading.show();
saveUser(page);
return false;
}
function loadData(page) {
loadUser(page)
loadUser(page);
}
$(document).on("pageinit", "#newUserPage", function() {
var page = this;
$("#chkEnableAllChannels", page).on("change", function() {
this.checked ? $(".channelAccessListContainer", page).hide() : $(".channelAccessListContainer", page).show()
}), $("#chkEnableAllFolders", page).on("change", function() {
this.checked ? $(".folderAccessListContainer", page).hide() : $(".folderAccessListContainer", page).show()
}), $(".newUserProfileForm").off("submit", onSubmit).on("submit", onSubmit)
if (this.checked) {
$(".channelAccessListContainer", page).hide();
} else {
$(".channelAccessListContainer", page).show();
}
});
$("#chkEnableAllFolders", page).on("change", function() {
if (this.checked) {
$(".folderAccessListContainer", page).hide();
} else {
$(".folderAccessListContainer", page).show();
}
});
$(".newUserProfileForm").off("submit", onSubmit).on("submit", onSubmit);
}).on("pageshow", "#newUserPage", function() {
loadData(this)
})
loadData(this);
});
});

View file

@ -70,7 +70,7 @@ progress[aria-valuenow]:before {
}
.adminDrawerLogo img {
height: 2.2em
height: 4em
}
div[data-role=controlgroup] a[data-role=button] {
@ -499,3 +499,8 @@ a[data-role=button] {
-webkit-box-shadow: 0 .0725em .29em 0 rgba(0, 0, 0, .37);
box-shadow: 0 .0725em .29em 0 rgba(0, 0, 0, .37)
}
.ui-bar-a{
text-align: center;
padding: 0 20px;
}

View file

@ -887,10 +887,6 @@
margin-bottom: 2.7em
}
.sectionTitleContainer {
margin: 1.25em 0
}
.sectionTitleButton,
.sectionTitleIconButton {
margin-right: 0 !important;
@ -898,30 +894,22 @@
vertical-align: middle
}
.sectionTitleContainer-cards {
margin-bottom: .1em
.sectionTitleContainer {
margin: 1.25em 0;
}
.sectionTitle {
margin-bottom: 1em
.sectionTitleContainer > .sectionTitle {
margin: 0;
display: inline-block;
vertical-align: middle;
}
.sectionTitleContainer-cards {
margin-bottom: 0;
}
.sectionTitle-cards {
margin-left: .28em;
margin-bottom: 0
}
@media all and (min-width:50em) {
.sectionTitle-cards {
margin-left: .55em
}
}
.sectionTitleContainer>.sectionTitle {
margin-top: 0;
margin-bottom: 0;
display: inline-block;
vertical-align: middle
}
.sectionTitleButton {
@ -930,7 +918,7 @@
flex-shrink: 0
}
.sectionTitleButton+.sectionTitleButton {
.sectionTitleButton + .sectionTitleButton {
margin-left: .5em !important
}
@ -972,97 +960,47 @@
}
.padded-left {
padding-left: 2%
padding-left: 3.3%;
}
.padded-right {
padding-right: 2%
padding-right: 3.3%;
}
.padded-top {
padding-top: 1em
padding-top: 1em;
}
.padded-bottom {
padding-bottom: 1em
padding-bottom: 1em;
}
.layout-tv .padded-top-focusscale {
padding-top: 1em;
margin-top: -1em
margin-top: -1em;
}
.layout-tv .padded-bottom-focusscale {
padding-bottom: 1em;
margin-bottom: -1em
margin-bottom: -1em;
}
@media all and (min-height:31.25em) {
.padded-left-withalphapicker {
padding-left: 7.5%
padding-left: 7.5%;
}
.padded-right-withalphapicker {
padding-right: 7.5%
}
}
@media all and (min-width:31.25em) {
.padded-left {
padding-left: 6%
}
.padded-right {
padding-right: 6%
}
}
@media all and (min-width:37.5em) {
.padded-left {
padding-left: 4%
}
.padded-right {
padding-right: 4%
}
}
@media all and (min-width:50em) {
.padded-left {
padding-left: 3.2%
}
.padded-right {
padding-right: 3.2%
}
}
@media all and (min-width:64em) {
.padded-left {
padding-left: 3.3%
}
.padded-right {
padding-right: 3.3%
}
}
@media all and (min-width:50em) {
.layout-tv .padded-left-withalphapicker {
padding-left: 4.5%
}
.layout-tv .padded-right-withalphapicker {
padding-right: 4.5%
padding-right: 7.5%;
}
}
.searchfields-icon {
color: #aaa
color: #aaaaaa;
}
.button-accent-flat {
color: #00a4dc !important
color: #00a4dc !important;
}
.clearLink {

View file

@ -14,17 +14,12 @@
}
.osdHeader {
padding-bottom: 3vh;
-webkit-transition: opacity .3s ease-out;
-o-transition: opacity .3s ease-out;
transition: opacity .3s ease-out;
position: relative;
z-index: 1;
background-color: rgba(0, 0, 0, .3) !important;
background: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, .6)), to(rgba(0, 0, 0, 0))) !important;
background: -webkit-linear-gradient(rgba(0, 0, 0, .6), rgba(0, 0, 0, 0)) !important;
background: -o-linear-gradient(rgba(0, 0, 0, .6), rgba(0, 0, 0, 0)) !important;
background: linear-gradient(rgba(0, 0, 0, .6), rgba(0, 0, 0, 0)) !important;
background-color: rgba(0, 0, 0, 0.7) !important;
-webkit-backdrop-filter: none !important;
backdrop-filter: none !important;
color: #eee
@ -93,7 +88,7 @@
.videoOsdBottom {
position: fixed;
background-color: rgba(0, 0, 0, .7);
background-color: rgba(0, 0, 0, 0.7);
padding: 1%;
display: -webkit-box;
display: -webkit-flex;
@ -103,13 +98,9 @@
-webkit-flex-direction: row;
flex-direction: row;
will-change: opacity;
-webkit-transition: opacity .3s ease-out;
-o-transition: opacity .3s ease-out;
transition: opacity .3s ease-out;
background: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .8)));
background: -webkit-linear-gradient(rgba(0, 0, 0, .5), rgba(0, 0, 0, .8));
background: -o-linear-gradient(rgba(0, 0, 0, .5), rgba(0, 0, 0, .8));
background: linear-gradient(rgba(0, 0, 0, .5), rgba(0, 0, 0, .8));
-webkit-transition: opacity 0.3s ease-out;
-o-transition: opacity 0.3s ease-out;
transition: opacity 0.3s ease-out;
color: #fff;
user-select: none;
-webkit-touch-callout: none

View file

@ -32,8 +32,8 @@
</div>
<div class="dashboardSection" style="padding-left: 0;">
<a is="emby-linkbutton" href="devices.html" style="margin-left:.8em!important;" class="button-flat sectionTitleTextButton">
<h3 style="margin:0;">${HeaderActiveDevices}</h3>
<a is="emby-linkbutton" href="devices.html" class="button-flat sectionTitleTextButton">
<h3>${HeaderActiveDevices}</h3>
<i class="md-icon">&#xE5CC;</i>
</a>
<div class="activeDevices itemsContainer vertical-wrap">

View file

@ -1,17 +1,13 @@
<div id="dlnaProfilePage" data-role="page" class="page type-interior dlnaPage withTabs">
<div data-role="content">
<div class="content-primary">
<form class="dlnaProfileForm" style="max-width: 650px;">
<div class="verticalSection">
<div class="sectionTitleContainer flex align-items-center">
<h2 class="sectionTitle">${HeaderProfileInformation}</h2>
<a is="emby-linkbutton" class="raised button-alt headerHelpButton" target="_blank" href="https://web.archive.org/web/20181216120305/https://github.com/MediaBrowser/Wiki/wiki/Dlna-profiles">${Help}</a>
</div>
</div>
<div data-role="controlgroup" data-type="horizontal" data-mini="true">
<a href="#" is="emby-linkbutton" data-role="button" class="radioTabButton" id="radioInfo" data-value="tabInfo">${TabInfo}</a>
<a href="#" is="emby-linkbutton" data-role="button" class="radioTabButton" id="radioDirectPlay" data-value="tabDirectPlayProfiles">${TabDirectPlay}</a>
@ -22,7 +18,6 @@
</div>
<br />
<div class="tabContent tabInfo">
<div class="inputContainer">
<input is="emby-input" type="text" id="txtName" required="required" label="${LabelName}" />
</div>
@ -30,7 +25,6 @@
<select is="emby-select" id="selectUser" label="${LabelUserLibrary}"></select>
<div class="fieldDescription">${LabelUserLibraryHelp}</div>
</div>
<div>
<h3 class="checkboxListLabel">${LabelSupportedMediaTypes}</h3>
<div class="checkboxList paperList checkboxList-paperList">
@ -62,7 +56,6 @@
<input type="checkbox" id="chkIgnoreTranscodeByteRangeRequests" data-mini="true" />
<div class="fieldDescription">${OptionIgnoreTranscodeByteRangeRequestsHelp}</div>
</div>
<div is="emby-collapse" title="${HeaderIdentification}">
<div class="collapseContent">
<h3>${HeaderIdentificationCriteriaHelp}</h3>
@ -102,7 +95,6 @@
<input is="emby-input" type="text" id="txtIdDeviceDescription" label="${LabelDeviceDescription}" />
<div class="fieldDescription">${LabelIdentificationFieldHelp}</div>
</div>
<div>
<h2 style="vertical-align:middle;display:inline-block;">${HeaderHttpHeaders}</h2>
<button is="emby-button" type="button" class="fab btnAddIdentificationHttpHeader submit sectionTitleButton" style="margin-left:1em;" title="${ButtonAdd}">
@ -112,11 +104,9 @@
<div class="httpHeaderIdentificationList"></div>
</div>
</div>
<div is="emby-collapse" title="${HeaderDisplaySettings}">
<div class="collapseContent">
<br />
<div class="checkboxContainer checkboxContainer-withDescription">
<label>
<input is="emby-checkbox" type="checkbox" id="chkRequiresPlainFolders" />
@ -133,7 +123,6 @@
</div>
</div>
</div>
<div is="emby-collapse" title="${HeaderImageSettings}">
<div class="collapseContent">
<div class="checkboxContainer checkboxContainer-withDescription">
@ -172,7 +161,6 @@
</div>
</div>
</div>
<div is="emby-collapse" title="${HeaderServerSettings}">
<div class="collapseContent">
<p>${HeaderProfileServerSettingsHelp}</p>
@ -218,19 +206,16 @@
</div>
</div>
</div>
<div is="emby-collapse" title="${HeaderSubtitleProfiles}">
<div class="collapseContent">
<p>${HeaderSubtitleProfilesHelp}</p>
<button is="emby-button" type="button" class="raised submit block btnAddSubtitleProfile">
<span>${ButtonAdd}</span>
</button>
<div class="subtitleProfileList"></div>
<br />
</div>
</div>
<div is="emby-collapse" title="${HeaderXmlSettings}">
<div class="collapseContent">
<div>
@ -238,7 +223,6 @@
<button is="emby-button" type="button" class="fab btnAddXmlDocumentAttribute submit sectionTitleButton" style="margin-left:1em;" title="${ButtonAdd}">
<i class="md-icon">&#xE145;</i>
</button>
</div>
<div class="xmlDocumentAttributeList"></div>
<div class="fieldDescription">${XmlDocumentAttributeListHelp}</div>
@ -246,34 +230,33 @@
</div>
</div>
</div>
<div class="tabContent tabDirectPlayProfiles">
<p>${HeaderDirectPlayProfileHelp}</p>
<button class="btnAddDirectPlayProfile" type="button" data-mini="true" data-icon="plus">${ButtonNew}</button>
<button is="emby-button" class="raised submit block btnAddDirectPlayProfile" type="button" data-mini="true" data-icon="plus">${ButtonNew}</button>
<br />
<div class="directPlayProfiles"></div>
</div>
<div class="tabContent tabTranscodingProfiles">
<p>${HeaderTranscodingProfileHelp}</p>
<button class="btnAddTranscodingProfile" type="button" data-mini="true" data-icon="plus">${ButtonNew}</button>
<button is="emby-button" class="raised submit block btnAddTranscodingProfile" type="button" data-mini="true" data-icon="plus">${ButtonNew}</button>
<br />
<div class="transcodingProfiles"></div>
</div>
<div class="tabContent tabContainerProfiles">
<p>${HeaderContainerProfileHelp}</p>
<button class="btnAddContainerProfile" type="button" data-mini="true" data-icon="plus">${ButtonNew}</button>
<button is="emby-button" class="raised submit block btnAddContainerProfile" type="button" data-mini="true" data-icon="plus">${ButtonNew}</button>
<br />
<div class="containerProfiles"></div>
</div>
<div class="tabContent tabCodecProfiles">
<p>${HeaderCodecProfileHelp}</p>
<button class="btnAddCodecProfile" type="button" data-mini="true" data-icon="plus">${ButtonNew}</button>
<button is="emby-button" class="raised submit block btnAddCodecProfile" type="button" data-icon="plus">${ButtonNew}</button>
<br />
<div class="codecProfiles"></div>
</div>
<div class="tabContent tabMediaProfiles">
<p>${HeaderResponseProfileHelp}</p>
<button class="btnAddResponseProfile" type="button" data-mini="true" data-icon="plus">${ButtonNew}</button>
<button is="emby-button" class="raised submit block btnAddResponseProfile" type="button" data-mini="true" data-icon="plus">${ButtonNew}</button>
<br />
<div class="mediaProfiles"></div>
</div>
@ -285,69 +268,56 @@
<button is="emby-button" type="button" class="button-cancel raised block" onclick="Dashboard.navigate('dlnaprofiles.html');">
<span>${ButtonCancel}</span>
</button>
</div>
</form>
</div>
</div>
<div data-role="popup" id="popupEditDirectPlayProfile" class="dialog dialog-fixedSize dialog-small hide" style="position: fixed; top: 10%;">
<div class="ui-bar-a" style="text-align: center; padding: 0 20px;">
<h3>${HeaderDirectPlayProfile}</h3>
<div data-role="popup" id="popupEditDirectPlayProfile" class="dialog dialog-fixedSize dialog-medium-tall hide" style="position: fixed; top: 10%;">
<form class="editDirectPlayProfileForm" style="padding:1em;">
<div class="ui-bar-a">
<h3 class="sectionTitle">${HeaderDirectPlayProfile}</h3>
</div>
<div data-role="content">
<form class="editDirectPlayProfileForm">
<div style="margin: 1em 0;">
<label for="selectDirectPlayProfileType">${LabelType}</label>
<select id="selectDirectPlayProfileType" data-mini="true">
<div class="selectContainer">
<select id="selectDirectPlayProfileType" name="selectDirectPlayProfileType" is="emby-select" label="${LabelType}">
<option value="Audio">${OptionProfileAudio}</option>
<option value="Photo">${OptionProfilePhoto}</option>
<option value="Video">${OptionProfileVideo}</option>
</select>
</div>
<div style="margin: 1em 0;">
<label for="txtDirectPlayContainer">${LabelProfileContainer}</label>
<input type="text" id="txtDirectPlayContainer" />
<div class="inputContainer">
<input is="emby-input" type="text" id="txtDirectPlayContainer" label="${LabelProfileContainer}" />
<div class="fieldDescription">${LabelProfileContainersHelp}</div>
</div>
<div id="fldDirectPlayVideoCodec" style="margin: 1em 0;">
<label for="txtDirectPlayVideoCodec">${LabelProfileVideoCodecs}</label>
<input type="text" id="txtDirectPlayVideoCodec" />
<div class="inputContainer">
<input is="emby-input" type="text" id="txtDirectPlayVideoCodec" label="${LabelProfileVideoCodecs}" />
<div class="fieldDescription">${LabelProfileCodecsHelp}</div>
</div>
</div>
<div id="fldDirectPlayAudioCodec" style="margin: 1em 0 2em;">
<label for="txtDirectPlayAudioCodec">${LabelProfileAudioCodecs}</label>
<input type="text" id="txtDirectPlayAudioCodec" />
<div class="inputContainer">
<input is="emby-input" type="text" id="txtDirectPlayAudioCodec" label="${LabelProfileAudioCodecs}" />
<div class="fieldDescription">${LabelProfileCodecsHelp}</div>
</div>
</div>
<p>
<button type="submit" data-icon="check" data-mini="true">
${ButtonOk}
<button is="emby-button" type="submit" class="raised button-submit block" data-icon="check" data-mini="true">
<span>${ButtonOk}</span>
</button>
<button type="button" data-icon="delete" onclick="$(this).parents('.dialog').addClass('hide');" data-mini="true">
${ButtonCancel}
<button is="emby-button" type="button" class="raised button-cancel block" data-icon="delete" onclick="$(this).parents('.dialog').addClass('hide');" data-mini="true">
<span>${ButtonCancel}</span>
</button>
</p>
</div>
</form>
</div>
<div data-role="popup" id="transcodingProfilePopup" class="dialog dialog-fixedSize dialog-medium-tall hide" style="position: fixed; top: 10%;">
<form class="transcodingProfileForm" style="padding:1em;">
<div class="ui-bar-a">
<h3 class="sectionTitle">${HeaderTranscodingProfile}</h3>
</div>
<div data-role="popup" id="transcodingProfilePopup" class="dialog dialog-fixedSize dialog-small hide" style="position: fixed; top: 10%;">
<div class="ui-bar-a" style="text-align: center; padding: 0 20px;">
<h3>${HeaderTranscodingProfile}</h3>
</div>
<div data-role="content">
<form class="transcodingProfileForm" style="min-width: 250px;">
<div data-role="controlgroup" data-type="horizontal" data-mini="true">
<input type="radio" name="radioTranscodingTab" class="radioTabButton" id="radioTranscodingBasics" value="tabTranscodingBasics">
<label for="radioTranscodingBasics">${TabInfo}</label>
@ -356,321 +326,260 @@
</div>
<br />
<div class="tabContent tabTranscodingBasics" style="display: none;">
<div style="margin: 1em 0;">
<label for="selectTranscodingProfileType">${LabelType}</label>
<select id="selectTranscodingProfileType" data-mini="true">
<div class="selectContainer">
<select id="selectTranscodingProfileType" name="selectTranscodingProfileType" is="emby-select" label="${LabelType}">
<option value="Audio">${OptionProfileAudio}</option>
<option value="Photo">${OptionProfilePhoto}</option>
<option value="Video">${OptionProfileVideo}</option>
</select>
</div>
<div id="fldTranscodingProtocol" style="margin: 1em 0;">
<label for="selectTranscodingProtocol">${LabelProtocol}</label>
<select id="selectTranscodingProtocol" data-mini="true">
<div class="selectContainer">
<select id="selectTranscodingProtocol" name="selectTranscodingProtocol" is="emby-select" label="${LabelProtocol}">
<option value="Http">${OptionProtocolHttp}</option>
<option value="Hls">${OptionProtocolHls}</option>
</select>
</div>
<div style="margin: 1em 0;">
<label for="txtTranscodingContainer">${LabelTranscodingContainer}</label>
<input type="text" id="txtTranscodingContainer" required="required" />
</div>
<div class="inputContainer">
<input is="emby-input" type="text" id="txtTranscodingContainer" label="${LabelTranscodingContainer}"; required="required" />
</div>
<div id="fldTranscodingVideoCodec" style="margin: 1em 0;">
<label for="txtTranscodingVideoCodec">${LabelTranscodingVideoCodec}</label>
<input type="text" id="txtTranscodingVideoCodec" />
<div class="inputContainer">
<input is="emby-input" type="text" id="txtTranscodingVideoCodec" label="${LabelTranscodingVideoCodec}" />
</div>
</div>
<div id="fldTranscodingAudioCodec" style="margin: 1em 0;">
<label for="txtTranscodingAudioCodec">${LabelTranscodingAudioCodec}</label>
<input type="text" id="txtTranscodingAudioCodec" />
<div class="inputContainer">
<input is="emby-input" type="text" id="txtTranscodingAudioCodec" label="${LabelTranscodingAudioCodec}" />
</div>
</div>
</div>
<div class="tabContent tabTranscodingAdvanced" style="display: none;">
<div id="fldEnableMpegtsM2TsMode" style="margin: 1em 0;">
<label for="chkEnableMpegtsM2TsMode">${OptionEnableM2tsMode}</label>
<input type="checkbox" id="chkEnableMpegtsM2TsMode" data-mini="true" />
<div class="fieldDescription">${OptionEnableM2tsModeHelp}</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label>
<input is="emby-checkbox" type="checkbox" id="chkEnableMpegtsM2TsMode" />
<span>${OptionEnableM2tsMode}</span>
</label>
<div class="fieldDescription checkboxFieldDescription">${OptionEnableM2tsModeHelp}</div>
</div>
</div>
<div id="fldEstimateContentLength" style="margin: 1em 0;">
<label for="chkEstimateContentLength">${OptionEstimateContentLength}</label>
<input type="checkbox" id="chkEstimateContentLength" data-mini="true" />
<div class="checkboxContainer checkboxContainer-withDescription">
<label>
<input is="emby-checkbox" type="checkbox" id="chkEstimateContentLength" />
<span>${OptionEstimateContentLength}</span>
</label>
</div>
</div>
<div id="fldReportByteRangeRequests" style="margin: 1em 0;">
<label for="chkReportByteRangeRequests">${OptionReportByteRangeSeekingWhenTranscoding}</label>
<input type="checkbox" id="chkReportByteRangeRequests" data-mini="true" />
<div class="fieldDescription">${OptionReportByteRangeSeekingWhenTranscodingHelp}</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label>
<input is="emby-checkbox" type="checkbox" id="chkReportByteRangeRequests" />
<span>${OptionReportByteRangeSeekingWhenTranscoding}</span>
</label>
<div class="fieldDescription checkboxFieldDescription">${OptionReportByteRangeSeekingWhenTranscodingHelp}</div>
</div>
</div>
</div>
<p>
<button type="submit" data-icon="check" data-mini="true">
${ButtonOk}
<button is="emby-button" type="submit" class="raised button-submit block" data-icon="check" data-mini="true">
<span>${ButtonOk}</span>
</button>
<button type="button" data-icon="delete" onclick="$(this).parents('.dialog').addClass('hide');" data-mini="true">
${ButtonCancel}
<button is="emby-button" type="button" class="raised button-cancel block" data-icon="delete" onclick="$(this).parents('.dialog').addClass('hide');" data-mini="true">
<span>${ButtonCancel}</span>
</button>
</p>
</div>
</form>
</div>
<div data-role="popup" id="containerProfilePopup" class="dialog dialog-fixedSize dialog-medium-tall hide" style="position: fixed; top: 10%;">
<form class="containerProfileForm" style="padding:1em;">
<div class="ui-bar-a">
<h3 class="sectionTitle">${HeaderContainerProfile}</h3>
</div>
<div data-role="popup" id="containerProfilePopup" class="dialog dialog-fixedSize dialog-small hide" style="position: fixed; top: 10%;">
<div class="ui-bar-a" style="text-align: center; padding: 0 20px;">
<h3>${HeaderContainerProfile}</h3>
</div>
<div data-role="content">
<form class="containerProfileForm" style="min-width: 250px;">
<p>${HeaderContainerProfileHelp}</p>
<!-- <div data-role="controlgroup" data-type="horizontal" data-mini="true">
<input type="radio" name="radioContainerProfileTab" class="radioTabButton" id="radioContainerProfileInfo" value="tabContainerBasics">
<label for="radioContainerProfileInfo">${TabInfo}</label>
<input type="radio" name="radioContainerProfileTab" class="radioTabButton" id="radioContainerProfileConditions" value="tabContainerConditions">
<label for="radioContainerProfileConditions">Conditions</label>
</div>-->
<div class="tabContent tabContainerBasics">
<div style="margin: 1em 0;">
<label for="selectContainerProfileType">${LabelType}</label>
<select id="selectContainerProfileType" data-mini="true">
<div class="selectContainer">
<select id="selectContainerProfileType" name="selectContainerProfileType" is="emby-select" label="${LabelType}">
<option value="Audio">${OptionProfileAudio}</option>
<option value="Photo">${OptionProfilePhoto}</option>
<option value="Video">${OptionProfileVideo}</option>
</select>
</div>
<div style="margin: 1em 0;">
<label for="txtContainerProfileContainer">Containers:</label>
<input type="text" id="txtContainerProfileContainer" />
<div class="inputContainer">
<input is="emby-input" type="text" id="txtContainerProfileContainer" label="${LabelProfileContainer}" />
<div class="fieldDescription">${LabelProfileContainersHelp}</div>
</div>
</div>
<div class="tabContent tabContainerConditions" style="display: none;">
</div>
<div class="tabContent tabContainerConditions" style="display: none;"></div>
<p>
<button type="submit" data-icon="check" data-mini="true">
${ButtonOk}
<button is="emby-button" type="submit" class="raised button-submit block" data-icon="check" data-mini="true">
<span>${ButtonOk}</span>
</button>
<button type="button" data-icon="delete" onclick="$(this).parents('.dialog').addClass('hide');" data-mini="true">
${ButtonCancel}
<button is="emby-button" type="button" class="raised button-cancel block" data-icon="delete" onclick="$(this).parents('.dialog').addClass('hide');" data-mini="true">
<span>${ButtonCancel}</span>
</button>
</p>
</div>
</form>
</div>
<div data-role="popup" id="codecProfilePopup" class="dialog dialog-fixedSize dialog-medium-tall hide" style="position: fixed; top: 10%;">
<form class="codecProfileForm" style="padding:1em;">
<div class="ui-bar-a">
<h3 class="sectionTitle">${HeaderCodecProfile}</h3>
</div>
<div data-role="popup" id="codecProfilePopup" class="dialog dialog-fixedSize dialog-small hide" style="position: fixed; top: 10%;">
<div class="ui-bar-a" style="text-align: center; padding: 0 20px;">
<h3>${HeaderCodecProfile}</h3>
</div>
<div data-role="content">
<form class="codecProfileForm" style="min-width: 250px;">
<p>${HeaderCodecProfileHelp}</p>
<div style="margin: 1em 0;">
<label for="selectCodecProfileType">${LabelType}</label>
<select id="selectCodecProfileType" data-mini="true">
<div class="selectContainer">
<select id="selectCodecProfileType" name="selectCodecProfileType" is="emby-select" label="${LabelType}">
<option value="Video">${OptionProfileVideo}</option>
<option value="VideoAudio">${OptionProfileVideoAudio}</option>
<option value="Audio">${OptionProfileAudio}</option>
</select>
</div>
<div style="margin: 1em 0;">
<label for="txtCodecProfileCodec">${LabelProfileCodecs}</label>
<input type="text" id="txtCodecProfileCodec" />
<div class="inputContainer">
<input is="emby-input" type="text" id="txtCodecProfileCodec" label="${LabelProfileCodecs}" />
<div class="fieldDescription">${LabelProfileCodecsHelp}</div>
</div>
<p>
<button type="submit" data-icon="check" data-mini="true">
${ButtonOk}
<button is="emby-button" type="submit" class="raised button-submit block" data-icon="check" data-mini="true">
<span>${ButtonOk}</span>
</button>
<button type="button" data-icon="delete" onclick="$(this).parents('.dialog').addClass('hide');" data-mini="true">
${ButtonCancel}
<button is="emby-button" type="button" class="raised button-cancel block" data-icon="delete" onclick="$(this).parents('.dialog').addClass('hide');" data-mini="true">
<span>${ButtonCancel}</span>
</button>
</p>
</div>
</form>
</div>
<div data-role="popup" id="responseProfilePopup" class="dialog dialog-fixedSize dialog-medium-tall hide" style="position: fixed; top: 10%;">
<form class="editResponseProfileForm" style="padding:1em;">
<div class="ui-bar-a">
<h3 class="sectionTitle">${HeaderResponseProfile}</h3>
</div>
<div data-role="popup" id="responseProfilePopup" class="dialog dialog-fixedSize dialog-small hide" style="position: fixed; top: 10%;">
<div class="ui-bar-a" style="text-align: center; padding: 0 20px;">
<h3>${HeaderResponseProfile}</h3>
</div>
<div data-role="content">
<form class="editResponseProfileForm">
<div style="margin: 1em 0;">
<label for="selectResponseProfileType">${LabelType}</label>
<select id="selectResponseProfileType" data-mini="true">
<div class="selectContainer">
<select id="selectResponseProfileType" name="selectResponseProfileType" is="emby-select" label="${LabelType}">
<option value="Audio">${OptionProfileAudio}</option>
<option value="Photo">${OptionProfilePhoto}</option>
<option value="Video">${OptionProfileVideo}</option>
</select>
</div>
<div style="margin: 1em 0;">
<label for="txtResponseProfileContainer">${LabelProfileContainer}</label>
<input type="text" id="txtResponseProfileContainer" />
<div class="inputContainer">
<input is="emby-input" type="text" id="txtResponseProfileContainer" label="${LabelProfileContainer}" />
<div class="fieldDescription">${LabelProfileContainersHelp}</div>
</div>
<div id="fldResponseProfileVideoCodec" style="margin: 1em 0;">
<label for="txtResponseProfileVideoCodec">${LabelProfileVideoCodecs}</label>
<input type="text" id="txtResponseProfileVideoCodec" />
<div class="inputContainer">
<input is="emby-input" type="text" id="txtResponseProfileVideoCodec" label="${LabelProfileVideoCodecs}" />
<div class="fieldDescription">${LabelProfileCodecsHelp}</div>
</div>
</div>
<div id="fldResponseProfileAudioCodec" style="margin: 1em 0 2em;">
<label for="txtResponseProfileAudioCodec">${LabelProfileAudioCodecs}</label>
<input type="text" id="txtResponseProfileAudioCodec" />
<div class="inputContainer">
<input is="emby-input" type="text" id="txtResponseProfileAudioCodec" label="${LabelProfileAudioCodecs}" />
<div class="fieldDescription">${LabelProfileCodecsHelp}</div>
</div>
</div>
<p>
<button type="submit" data-icon="check" data-mini="true">
${ButtonOk}
<button is="emby-button" type="submit" class="raised button-submit block" data-icon="check" data-mini="true">
<span>${ButtonOk}</span>
</button>
<button type="button" data-icon="delete" onclick="$(this).parents('.dialog').addClass('hide');" data-mini="true">
${ButtonCancel}
<button is="emby-button" type="button" class="raised button-cancel block" data-icon="delete" onclick="$(this).parents('.dialog').addClass('hide');" data-mini="true">
<span>${ButtonCancel}</span>
</button>
</p>
</div>
</form>
</div>
<div data-role="popup" id="identificationHeaderPopup" class="dialog dialog-fixedSize dialog-medium-tall hide" style="position: fixed; top: 10%;">
<form class="identificationHeaderForm" style="padding:1em;">
<div class="ui-bar-a">
<h3 class="sectionTitle">${HeaderIdentificationHeader}</h3>
</div>
<div data-role="popup" id="identificationHeaderPopup" class="dialog dialog-fixedSize dialog-small hide" style="position: fixed; top: 10%;">
<div class="ui-bar-a" style="text-align: center; padding: 0 20px;">
<h3>${HeaderIdentificationHeader}</h3>
</div>
<div data-role="content">
<form class="identificationHeaderForm">
<div style="margin: 1em 0;">
<label for="txtIdentificationHeaderName">${LabelName}</label>
<input type="text" id="txtIdentificationHeaderName" required="required" />
<div class="inputContainer">
<input is="emby-input" type="text" id="txtIdentificationHeaderName" label="${LabelName}" />
</div>
<div style="margin: 1em 0;">
<label for="txtIdentificationHeaderValue">${LabelValue}</label>
<input type="text" id="txtIdentificationHeaderValue" required="required" />
<div class="inputContainer">
<input is="emby-input" type="text" id="txtIdentificationHeaderValue" label="${LabelValue}" />
</div>
<div style="margin: 1em 0;">
<label for="selectMatchType">${LabelMatchType}</label>
<select id="selectMatchType" data-mini="true">
<div class="selectContainer">
<select id="selectMatchType" name="selectMatchType" is="emby-select" label="${LabelMatchType}">
<option value="Equals">${OptionEquals}</option>
<option value="Regex">${OptionRegex}</option>
<option value="Substring">${OptionSubstring}</option>
</select>
</div>
<p>
<button type="submit" data-icon="check" data-mini="true">
${ButtonOk}
<button is="emby-button" type="submit" class="raised button-submit block" data-icon="check" data-mini="true">
<span>${ButtonOk}</span>
</button>
<button type="button" data-icon="delete" onclick="$(this).parents('.dialog').addClass('hide');" data-mini="true">
${ButtonCancel}
<button is="emby-button" type="button" class="raised button-cancel block" data-icon="delete" onclick="$(this).parents('.dialog').addClass('hide');" data-mini="true">
<span>${ButtonCancel}</span>
</button>
</p>
</div>
</form>
</div>
<div data-role="popup" id="xmlAttributePopup" class="dialog dialog-fixedSize dialog-medium-tall hide" style="position: fixed; top: 10%;">
<form class="xmlAttributeForm" style="padding:1em;">
<div class="ui-bar-a">
<h3 class="sectionTitle">${HeaderXmlDocumentAttribute}</h3>
</div>
<div data-role="popup" id="xmlAttributePopup" class="dialog dialog-fixedSize dialog-small hide" style="position: fixed; top: 10%;">
<div class="ui-bar-a" style="text-align: center; padding: 0 20px;">
<h3>${HeaderXmlDocumentAttribute}</h3>
</div>
<div data-role="content">
<form class="xmlAttributeForm">
<div style="margin: 1em 0;">
<label for="txtXmlAttributeName">${LabelName}</label>
<input type="text" id="txtXmlAttributeName" required="required" />
<div class="inputContainer">
<input is="emby-input" type="text" id="txtXmlAttributeName" label="${LabelName}" />
</div>
<div style="margin: 1em 0;">
<label for="txtXmlAttributeValue">${LabelValue}</label>
<input type="text" id="txtXmlAttributeValue" required="required" />
<div class="inputContainer">
<input is="emby-input" type="text" id="txtXmlAttributeValue" label="${LabelValue}" />
</div>
<p>
<button type="submit" data-icon="check" data-mini="true">
${ButtonOk}
<button is="emby-button" type="submit" class="raised button-submit block" data-icon="check" data-mini="true">
<span>${ButtonOk}</span>
</button>
<button type="button" data-icon="delete" onclick="$(this).parents('.dialog').addClass('hide');" data-mini="true">
${ButtonCancel}
<button is="emby-button" type="button" class="raised button-cancel block" data-icon="delete" onclick="$(this).parents('.dialog').addClass('hide');" data-mini="true">
<span>${ButtonCancel}</span>
</button>
</p>
</div>
</form>
</div>
<div data-role="popup" id="subtitleProfilePopup" class="dialog dialog-fixedSize dialog-medium-tall hide" style="position: fixed; top: 10%;">
<form class="subtitleProfileForm" style="padding:1em;">
<div class="ui-bar-a">
<h3 class="sectionTitle">${HeaderSubtitleProfile}</h3>
</div>
<div data-role="popup" id="subtitleProfilePopup" class="dialog dialog-fixedSize dialog-small hide" style="position: fixed; top: 10%;">
<div class="ui-bar-a" style="text-align: center; padding: 0 20px;">
<h3>${HeaderSubtitleProfile}</h3>
</div>
<div data-role="content">
<form class="subtitleProfileForm">
<div style="margin: 1em 0;">
<label for="txtSubtitleProfileFormat">${LabelFormat}</label>
<input type="text" id="txtSubtitleProfileFormat" required="required" />
<div class="inputContainer">
<input is="emby-input" type="text" id="txtSubtitleProfileFormat" label="${LabelFormat}" />
<div class="fieldDescription">${LabelSubtitleFormatHelp}</div>
</div>
<div style="margin: 1em 0;">
<label for="selectSubtitleProfileMethod">${LabelMethod}</label>
<select id="selectSubtitleProfileMethod" data-mini="true" required="required">
<div class="selectContainer">
<select id="selectSubtitleProfileMethod" name="selectSubtitleProfileMethod" is="emby-select" label="${LabelMethod}">
<option value="Embed">${OptionEmbedSubtitles}</option>
<option value="External">${OptionExternallyDownloaded}</option>
<option value="Hls">${OptionHlsSegmentedSubtitles}</option>
</select>
</div>
<div style="margin: 1em 0;">
<label for="selectSubtitleProfileDidlMode">${LabelDidlMode}</label>
<select id="selectSubtitleProfileDidlMode" data-mini="true">
<div class="selectContainer">
<select id="selectSubtitleProfileDidlMode" name="selectSubtitleProfileDidlMode" is="emby-select" label="${LabelDidlMode}">
<option value="">${OptionResElement}</option>
<option value="CaptionInfoEx">${OptionCaptionInfoExSamsung}</option>
</select>
</div>
<p>
<button type="submit" data-icon="check" data-mini="true">
${ButtonOk}
<button is="emby-button" type="submit" class="raised button-submit block" data-icon="check" data-mini="true">
<span>${ButtonOk}</span>
</button>
<button type="button" data-icon="delete" onclick="$(this).parents('.dialog').addClass('hide');" data-mini="true">
${ButtonCancel}
<button is="emby-button" type="button" class="raised button-cancel block" data-icon="delete" onclick="$(this).parents('.dialog').addClass('hide');" data-mini="true">
<span>${ButtonCancel}</span>
</button>
</p>
</div>
</form>
</div>
</div>
</div>

View file

@ -0,0 +1 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Google Chrome icon</title><path d="M16.214 8.69l6.715-1.679A12.027 12.027 0 0 1 24 11.972C24 18.57 18.569 24 11.968 24c-.302 0-.605-.011-.907-.034l4.905-8.347c.356-.376.655-.803.881-1.271a5.451 5.451 0 0 0-.043-4.748 5.156 5.156 0 0 0-.59-.91zm-3.24 8.575l-2.121 6.682C4.738 23.345 0 18.14 0 11.977 0 9.592.709 7.26 2.038 5.279l4.834 8.377c.18.539 1.119 2.581 3.067 3.327.998.382 2.041.481 3.035.282zM11.973 7.62c-2.006.019-3.878 1.544-4.281 3.512a4.478 4.478 0 0 0 1.237 4.032c1.214 1.186 3.14 1.578 4.734.927 1.408-.576 2.47-1.927 2.691-3.431.272-1.856-.788-3.832-2.495-4.629a4.413 4.413 0 0 0-1.886-.411zM7.046 9.962L2.259 4.963A12.043 12.043 0 0 1 11.997 0c4.56 0 8.744 2.592 10.774 6.675H12.558c-1.811-.125-3.288.52-4.265 1.453a5.345 5.345 0 0 0-1.247 1.834z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 863 B

1
src/img/devices/edge.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24"><title>Microsoft Edge icon</title><path d="M23.158 14.25H7.821c0 .578.086 1.103.262 1.575.188.465.431.881.743 1.245.31.364.675.675 1.102.938.413.262.863.48 1.343.648.476.173.975.3 1.48.383a10.078 10.078 0 0 0 3.311-.026c.564-.105 1.111-.244 1.651-.42.54-.177 1.061-.387 1.583-.627.525-.24 1.057-.502 1.605-.795v5.085c-.612.3-1.212.552-1.812.769-.6.21-1.2.394-1.81.54-.612.15-1.23.263-1.865.33a18.41 18.41 0 0 1-1.957.105c-.9 0-1.77-.105-2.606-.311a10.217 10.217 0 0 1-2.355-.893 9.869 9.869 0 0 1-2.018-1.417 8.957 8.957 0 0 1-2.595-4.148 9.359 9.359 0 0 1-.356-2.61c0-.986.135-1.924.405-2.82.274-.9.66-1.717 1.17-2.467a8.92 8.92 0 0 1 1.856-1.999A9.82 9.82 0 0 1 9.426 5.91a5.206 5.206 0 0 0-1.163 1.774 7.671 7.671 0 0 0-.536 2.055h8.542c0-.863-.086-1.613-.262-2.258-.176-.645-.458-1.181-.851-1.605-.39-.427-.893-.75-1.512-.96-.618-.214-1.365-.322-2.238-.322-1.032 0-2.063.15-3.094.461-1.031.3-2.01.731-2.94 1.275-.93.551-1.785 1.2-2.565 1.942-.78.75-1.436 1.557-1.969 2.43a14 14 0 0 1 .649-2.913C1.798 6.863 2.21 6 2.706 5.2a11.606 11.606 0 0 1 1.74-2.152c.663-.645 1.398-1.2 2.212-1.65C7.472.949 8.334.585 9.272.34A13.4 13.4 0 0 1 12.257 0c.615 0 1.226.056 1.837.165.612.113 1.208.263 1.79.458 1.154.397 2.185.952 3.093 1.657a10.553 10.553 0 0 1 2.287 2.449c.62.926 1.088 1.95 1.41 3.063.323 1.114.488 2.273.488 3.477v2.981z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1 @@
<svg viewBox="0 0 24 24" role="img" xmlns="http://www.w3.org/2000/svg"><title>Mozilla Firefox icon</title><path d="M23.41 10.98c-.03-.21-.07-.34-.07-.34s-.08.1-.22.28c-.04-.51-.13-1.02-.27-1.51-.18-.62-.41-1.22-.7-1.79-.18-.38-.39-.75-.64-1.09-.13-.2-.24-.35-.26-.38-.43-.7-.91-1.12-1.48-1.92-.36-.61-.61-1.29-.73-1.99-.16.42-.28.86-.36 1.3-.57-.58-1.08-1-1.38-1.28C15.8.86 15.98.14 15.98.14s-2.8 3.12-1.59 6.37c.42 1.1 1.14 2.07 2.09 2.78 1.17.96 2.43 1.72 3.09 3.67-.53-1.03-1.34-1.88-2.33-2.47.3.71.45 1.46.44 2.23 0 2.92-2.37 5.29-5.3 5.29-.39 0-.79-.04-1.17-.13-.46-.09-.9-.24-1.31-.45-.62-.37-1.16-.86-1.58-1.45v-.01c.05.02.08.03.09.03.22.08.44.14.67.18.9.19 1.83.08 2.66-.31.84-.47 1.35-.81 1.76-.68.41.13.72-.26.44-.67-.5-.65-1.32-.96-2.12-.82-.84.12-1.61.71-2.7.14-.08-.04-.14-.08-.21-.12-.07-.05.24.06.16.01-.24-.12-.47-.25-.69-.41-.01-.01.17.05.15.04-.28-.19-.53-.44-.72-.73-.19-.35-.21-.78-.05-1.15.11-.19.26-.33.45-.42.14.07.23.12.23.12s-.07-.12-.1-.18c.01-.01.02 0 .04-.01.12.05.39.19.54.28.1.05.18.13.25.22 0 0 .05-.02.01-.13-.05-.13-.14-.24-.26-.31h.02c.11.06.21.12.31.2.09-.22.14-.44.13-.67.01-.13-.01-.26-.05-.37-.04-.08.02-.11.09-.03-.01-.06-.03-.12-.06-.18 0 0 .04-.06.06-.07.05-.05.1-.1.16-.13.35-.22.71-.41 1.09-.56.31-.13.56-.24.61-.27.08-.05.15-.1.22-.16.26-.22.43-.52.49-.85.01-.05.01-.09.01-.13V7.75c-.04-.17-.33-.29-1.84-.44-.53-.08-.96-.48-1.08-1.01v.01c-.02.05-.04.11-.06.17.02-.06.04-.11.06-.17V6.3c.29-.75.81-1.4 1.48-1.84.04-.03-.15.01-.11-.02.12-.06.25-.12.39-.17.07-.02-.29-.16-.61-.13-.19.01-.38.06-.56.13.08-.06.3-.14.25-.14-.41.07-.8.22-1.15.43 0-.04.01-.07.02-.1-.28.12-.53.31-.71.55v-.13c-.13.1-.24.21-.35.33h-.01c-.83-.32-1.73-.4-2.61-.22l-.01-.01h.01c-.18-.14-.34-.32-.46-.52l-.01.01-.02-.02c-.06-.08-.11-.18-.17-.29-.05-.07-.09-.16-.14-.25 0 0 0-.01-.01-.01s-.03.09-.04.06c-.15-.4-.23-.83-.21-1.25h-.01c-.25.17-.44.41-.53.7-.05.1-.08.15-.11.21v-.03l.03-.15c-.01.01-.01.02-.02.03-.07.08-.13.17-.18.27-.05.09-.09.19-.12.29v-.05c0-.04.01-.1 0-.08l-.01.03c-.32.71-.53 1.47-.6 2.25-.02.14-.02.27-.02.4v.02c-.23.25-.43.52-.61.81-.58.98-1.01 2.04-1.28 3.15.19-.42.42-.83.69-1.21C.76 10.66.5 12.04.5 13.44c.09-.41.2-.81.33-1.21-.08 1.65.24 3.3.93 4.81.93 2.08 2.47 3.83 4.43 5.01.79.54 1.66.96 2.57 1.24.12.04.25.09.37.13-.04-.02-.07-.04-.11-.05 1.08.32 2.21.49 3.34.49 4.01 0 5.33-1.53 5.46-1.68.19-.18.36-.39.47-.64.08-.03.15-.06.23-.1l.05-.02c.06-.03.09-.04.09-.04.61-.29 1.18-.64 1.7-1.06.78-.56 1.33-1.38 1.57-2.31.15-.34.15-.71.03-1.06.06-.1.11-.19.12-.21.86-1.38 1.35-2.96 1.42-4.59v-.01-.13c0-.34-.03-.69-.09-1.03z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>HTML5 icon</title><path d="M1.5 0h21l-1.91 21.563L11.977 24l-8.564-2.438L1.5 0zm7.031 9.75l-.232-2.718 10.059.003.23-2.622L5.412 4.41l.698 8.01h9.126l-.326 3.426-2.91.804-2.955-.81-.188-2.11H6.248l.33 4.171L12 19.351l5.379-1.443.744-8.157H8.531z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 345 B

1
src/img/devices/msie.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24"><title>Internet Explorer icon</title><path d="M22.8 7.381c1.125-2.7 1.2-4.95-.15-6.3-1.5-1.499-5.1-1.05-8.924.75h-.45c-2.7 0-5.324.976-7.274 2.7-1.65 1.5-2.85 3.45-3.375 5.625.375-.45 2.475-2.925 4.875-4.275.075 0 .675-.375.675-.375-.075 0-1.2 1.125-1.425 1.35-5.25 5.4-8.324 13.574-5.924 15.973 1.574 1.575 4.424 1.2 7.724-.6 1.425.675 3 .975 4.724.975 2.25 0 4.35-.6 6.15-1.8 1.874-1.2 3.224-3.074 4.05-5.249h-5.85c-.75 1.425-2.475 2.4-4.275 2.4-2.55 0-4.65-2.1-4.724-4.5V13.83h15.298v-.225c0-.375.075-.825.075-1.124 0-1.8-.45-3.525-1.2-5.1zM2.477 22.38c-1.2-1.2-.824-3.524.6-6.299.675 1.875 1.8 3.525 3.225 4.725.45.375.975.75 1.5 1.05-2.4 1.274-4.35 1.5-5.325.524zm15.374-11.398H8.702v-.075c.15-2.325 2.324-4.35 4.874-4.35 2.4 0 4.35 1.875 4.5 4.35v.075zm4.574-4.2c-.45-.75-1.05-1.5-1.725-2.1a11.213 11.213 0 0 0-3.6-2.25c2.4-1.124 4.425-1.274 5.475-.224.825.975.75 2.624-.15 4.574 0 .075 0 .075 0 0 0 .075 0 .075 0 0z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 1,015 B

View file

@ -0,0 +1 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Opera icon</title><path d="M8.051 5.238c-1.328 1.566-2.186 3.883-2.246 6.48v.564c.061 2.598.918 4.912 2.246 6.479 1.721 2.236 4.279 3.654 7.139 3.654 1.756 0 3.4-.537 4.807-1.471C17.879 22.846 15.074 24 12 24c-.192 0-.383-.004-.57-.014C5.064 23.689 0 18.436 0 12 0 5.371 5.373 0 12 0h.045c3.055.012 5.84 1.166 7.953 3.055-1.408-.93-3.051-1.471-4.81-1.471-2.858 0-5.417 1.42-7.14 3.654h.003zM24 12c0 3.556-1.545 6.748-4.002 8.945-3.078 1.5-5.946.451-6.896-.205 3.023-.664 5.307-4.32 5.307-8.74 0-4.422-2.283-8.075-5.307-8.74.949-.654 3.818-1.703 6.896-.205C22.455 5.25 24 8.445 24 12z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 683 B

View file

@ -0,0 +1 @@
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M3 6h18V4H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h4v-2H3V6zm10 6H9v1.78c-.61.55-1 1.33-1 2.22s.39 1.67 1 2.22V20h4v-1.78c.61-.55 1-1.34 1-2.22s-.39-1.67-1-2.22V12zm-2 5.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM22 8h-6c-.5 0-1 .5-1 1v10c0 .5.5 1 1 1h6c.5 0 1-.5 1-1V9c0-.5-.5-1-1-1zm-1 10h-4v-8h4v8z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 476 B

View file

@ -0,0 +1 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>PlayStation icon</title><path d="M8.985 2.596v17.548l3.915 1.261V6.688c0-.69.304-1.151.794-.991.636.181.76.814.76 1.505v5.876c2.441 1.193 4.362-.002 4.362-3.153 0-3.237-1.126-4.675-4.438-5.827-1.307-.448-3.728-1.186-5.391-1.502h-.002zm4.656 16.242l6.296-2.275c.715-.258.826-.625.246-.818-.586-.192-1.637-.139-2.357.123l-4.205 1.499v-2.385l.24-.085s1.201-.42 2.913-.615c1.696-.18 3.785.029 5.437.661 1.848.601 2.041 1.472 1.576 2.072s-1.622 1.036-1.622 1.036l-8.544 3.107v-2.297l.02-.023zM1.808 18.6c-1.9-.545-2.214-1.668-1.352-2.321.801-.585 2.159-1.051 2.159-1.051l5.616-2.013v2.313L4.206 17c-.705.271-.825.632-.239.826.586.195 1.637.15 2.343-.12L8.248 17v2.074c-.121.029-.256.044-.391.073-1.938.331-3.995.196-6.037-.479l-.012-.068z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 833 B

View file

@ -0,0 +1 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>safari icon</title><path d="M12 24C5.373 24 0 18.627 0 12S5.373 0 12 0s12 5.373 12 12-5.373 12-12 12zm0-.75c6.213 0 11.25-5.037 11.25-11.25S18.213.75 12 .75.75 5.787.75 12 5.787 23.25 12 23.25zM12 2a.25.25 0 0 1 .25.25v1a.25.25 0 1 1-.5 0v-1A.25.25 0 0 1 12 2zm0 18.5a.25.25 0 0 1 .25.25v1a.25.25 0 1 1-.5 0v-1a.25.25 0 0 1 .25-.25zm7.071-15.571a.25.25 0 0 1 0 .353l-.707.708a.25.25 0 0 1-.354-.354l.708-.707a.25.25 0 0 1 .353 0zM5.99 18.01a.25.25 0 0 1 0 .354l-.708.707a.25.25 0 1 1-.353-.353l.707-.708a.25.25 0 0 1 .354 0zM4.929 4.93a.25.25 0 0 1 .353 0l.708.707a.25.25 0 0 1-.354.354l-.707-.708a.25.25 0 0 1 0-.353zM18.01 18.01a.25.25 0 0 1 .354 0l.707.708a.25.25 0 1 1-.353.353l-.708-.707a.25.25 0 0 1 0-.354zM2 12a.25.25 0 0 1 .25-.25h1a.25.25 0 1 1 0 .5h-1A.25.25 0 0 1 2 12zm18.5 0a.25.25 0 0 1 .25-.25h1a.25.25 0 1 1 0 .5h-1a.25.25 0 0 1-.25-.25zm-4.593-9.205a.25.25 0 0 1 .133.328l-.391.92a.25.25 0 1 1-.46-.195l.39-.92a.25.25 0 0 1 .328-.133zM8.68 19.825a.25.25 0 0 1 .132.327l-.39.92a.25.25 0 0 1-.46-.195l.39-.92a.25.25 0 0 1 .328-.133zM21.272 8.253a.25.25 0 0 1-.138.325l-.927.375a.25.25 0 1 1-.188-.464l.927-.374a.25.25 0 0 1 .326.138zm-17.153 6.93a.25.25 0 0 1-.138.326l-.927.374a.25.25 0 1 1-.188-.463l.927-.375a.25.25 0 0 1 .326.138zM8.254 2.728a.25.25 0 0 1 .325.138l.375.927a.25.25 0 0 1-.464.188l-.374-.927a.25.25 0 0 1 .138-.326zm6.93 17.153a.25.25 0 0 1 .326.138l.374.927a.25.25 0 1 1-.463.188l-.375-.927a.25.25 0 0 1 .138-.326zM2.795 8.093a.25.25 0 0 1 .328-.133l.92.391a.25.25 0 0 1-.195.46l-.92-.39a.25.25 0 0 1-.133-.328zm17.03 7.228a.25.25 0 0 1 .327-.132l.92.39a.25.25 0 1 1-.195.46l-.92-.39a.25.25 0 0 1-.133-.328zM12.879 12.879L11.12 11.12l-4.141 5.9 5.899-4.142zm6.192-7.95l-5.834 8.308-8.308 5.834 5.834-8.308 8.308-5.834z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24"><title>Samsung icon</title><path d="M19.8166 10.2808l.0459 2.6934h-.023l-.7793-2.6934h-1.2837v3.3925h.8481l-.0458-2.785h.023l.8366 2.785h1.2264v-3.3925zm-16.149 0l-.6418 3.427h.9284l.4699-3.1175h.0229l.4585 3.1174h.9169l-.6304-3.4269zm5.1805 0l-.424 2.6132h-.023l-.424-2.6132H6.5788l-.0688 3.427h.8596l.023-3.0832h.0114l.573 3.0831h.8711l.5731-3.083h.023l.0228 3.083h.8596l-.0802-3.4269zm-7.2664 2.4527c.0343.0802.0229.1949.0114.2522-.0229.1146-.1031.2292-.3324.2292-.2177 0-.3438-.126-.3438-.3095v-.3323H0v.2636c0 .7679.6074.9971 1.2493.9971.6189 0 1.1346-.2178 1.2149-.7794.0458-.298.0114-.4928 0-.5616-.1605-.722-1.467-.9283-1.5588-1.3295-.0114-.0688-.0114-.1375 0-.1834.023-.1146.1032-.2292.3095-.2292.2063 0 .321.126.321.3095v.2063h.8595v-.2407c0-.745-.6762-.8596-1.1576-.8596-.6074 0-1.1117.2063-1.2034.7564-.023.149-.0344.2866.0114.4585.1376.7106 1.364.9169 1.5358 1.3524m11.152 0c.0343.0803.0228.1834.0114.2522-.023.1146-.1032.2292-.3324.2292-.2178 0-.3438-.126-.3438-.3095v-.3323h-.917v.2636c0 .7564.596.9857 1.2379.9857.6189 0 1.1232-.2063 1.2034-.7794.0459-.298.0115-.4814 0-.5616-.1375-.7106-1.4327-.9284-1.5243-1.318-.0115-.0688-.0115-.1376 0-.1835.0229-.1146.1031-.2292.3094-.2292.1948 0 .321.126.321.3095v.2063h.848v-.2407c0-.745-.6647-.8596-1.146-.8596-.6075 0-1.1004.1948-1.192.7564-.023.149-.023.2866.0114.4585.1376.7106 1.341.9054 1.513 1.3524m2.8882.4585c.2407 0 .3094-.1605.3323-.2522.0115-.0343.0115-.0917.0115-.126v-2.533h.871v2.4642c0 .0688 0 .1948-.0114.2292-.0573.6419-.5616.8482-1.192.8482-.6303 0-1.1346-.2063-1.192-.8482 0-.0344-.0114-.1604-.0114-.2292v-2.4642h.871v2.533c0 .0458 0 .0916.0115.126 0 .0917.0688.2522.3095.2522m7.1518-.0344c.2522 0 .3324-.1605.3553-.2522.0115-.0343.0115-.0917.0115-.126v-.4929h-.3553v-.5043H24v.917c0 .0687 0 .1145-.0115.2292-.0573.6303-.596.8481-1.2034.8481-.6075 0-1.1461-.2178-1.2034-.8481-.0115-.1147-.0115-.1605-.0115-.2293v-1.444c0-.0574.0115-.172.0115-.2293.0802-.6419.596-.8482 1.2034-.8482s1.1347.2063 1.2034.8482c.0115.1031.0115.2292.0115.2292v.1146h-.8596v-.1948s0-.0803-.0115-.1261c-.0114-.0802-.0802-.2521-.3438-.2521-.2521 0-.321.1604-.3438.2521-.0115.0458-.0115.1032-.0115.1605v1.5702c0 .0458 0 .0916.0115.126 0 .0917.0917.2522.3323.2522" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -0,0 +1 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Windows icon</title><path d="M0 3.449L9.75 2.1v9.451H0m10.949-9.602L24 0v11.4H10.949M0 12.6h9.75v9.451L0 20.699M10.949 12.6H24V24l-12.9-1.801" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 241 B

1
src/img/devices/xbox.svg Normal file
View file

@ -0,0 +1 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Xbox icon</title><path d="M4.102 21.033C6.211 22.881 8.977 24 12 24c3.026 0 5.789-1.119 7.902-2.967 1.877-1.912-4.316-8.709-7.902-11.417-3.582 2.708-9.779 9.505-7.898 11.417zm11.16-14.406c2.5 2.961 7.484 10.313 6.076 12.912C23.002 17.48 24 14.861 24 12.004c0-3.34-1.365-6.362-3.57-8.536 0 0-.027-.022-.082-.042-.063-.022-.152-.045-.281-.045-.592 0-1.985.434-4.805 3.246zM3.654 3.426c-.057.02-.082.041-.086.042C1.365 5.642 0 8.664 0 12.004c0 2.854.998 5.473 2.661 7.533-1.401-2.605 3.579-9.951 6.08-12.91-2.82-2.813-4.216-3.245-4.806-3.245-.131 0-.223.021-.281.046v-.002zM12 3.551S9.055 1.828 6.755 1.746c-.903-.033-1.454.295-1.521.339C7.379.646 9.659 0 11.984 0H12c2.334 0 4.605.646 6.766 2.085-.068-.046-.615-.372-1.52-.339C14.946 1.828 12 3.545 12 3.545v.006z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 861 B

BIN
src/img/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

View file

@ -207,9 +207,7 @@
</div>
<div class="collectionItems"></div>
<div class="nextUpSection verticalSection detailVerticalSection hide">
<h2 class="sectionTitle sectionTitle-cards padded-left">
${HeaderNextUp}
</h2>
<h2 class="sectionTitle sectionTitle-cards padded-left">${HeaderNextUp}</h2>
<div is="emby-itemscontainer" class="nextUpItems vertical-wrap padded-left padded-right"></div>
</div>
<div class="programGuideSection hide verticalSection detailVerticalSection">
@ -224,18 +222,15 @@
</div>
</div>
<div id="additionalPartsCollapsible" class="verticalSection detailVerticalSection hide">
<h2 class="sectionTitle sectionTitle-cards padded-left">
${HeaderAdditionalParts}
</h2>
<h2 class="sectionTitle sectionTitle-cards padded-left">${HeaderAdditionalParts}</h2>
<div id="additionalPartsContent" is="emby-itemscontainer" class="itemsContainer vertical-wrap padded-left padded-right"></div>
</div>
<div class="verticalSection itemVerticalSection moreFromSeasonSection hide">
<h2 class="sectionTitle sectionTitle-cards padded-left padded-right"></h2>
<div is="emby-scroller" class="emby-scroller" data-mousewheel="false" data-centerfocus="true" data-horizontal="true">
<div class="scrollerframe padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer padded-left padded-right"></div>
<div is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer"></div>
</div>
</div>
</div>
@ -243,20 +238,17 @@
<h2 class="sectionTitle sectionTitle-cards padded-left padded-right"></h2>
<div is="emby-scroller" class="emby-scroller" data-mousewheel="false" data-centerfocus="true" data-horizontal="true">
<div class="scrollerframe padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer padded-left padded-right"></div>
<div is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer"></div>
</div>
</div>
</div>
<div id="castCollapsible" class="verticalSection detailVerticalSection hide">
<h2 id="peopleHeader" class="sectionTitle sectionTitle-cards padded-left padded-right">
${HeaderCastCrew}
</h2>
<h2 id="peopleHeader" class="sectionTitle sectionTitle-cards padded-left padded-right">${HeaderCastCrew}</h2>
<div is="emby-scroller" class="emby-scroller" data-mousewheel="false" data-centerfocus="true" data-horizontal="true">
<div class="scrollerframe padded-top-focusscale padded-bottom-focusscale">
<div id="castContent" is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer padded-left padded-right"></div>
<div id="castContent" is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer"></div>
</div>
</div>
</div>
@ -285,9 +277,8 @@
<h2 class="sectionTitle sectionTitle-cards padded-left padded-right">${HeaderScenes}</h2>
<div is="emby-scroller" class="emby-scroller" data-mousewheel="false" data-centerfocus="true" data-horizontal="true">
<div class="scrollerframe padded-top-focusscale padded-bottom-focusscale">
<div id="scenesContent" is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer padded-left padded-right"></div>
<div id="scenesContent" is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer"></div>
</div>
</div>
</div>
@ -296,9 +287,8 @@
<h2 class="sectionTitle sectionTitle-cards padded-left padded-right">${HeaderMoreLikeThis}</h2>
<div is="emby-scroller" class="emby-scroller" data-mousewheel="false" data-centerfocus="true" data-horizontal="true">
<div class="scrollerframe padded-top-focusscale padded-bottom-focusscale">
<div is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer padded-left padded-right similarContent"></div>
<div is="emby-itemscontainer" class="scrollSlider focuscontainer-x itemsContainer similarContent"></div>
</div>
</div>
</div>

View file

@ -1,8 +1,15 @@
<div id="libraryDisplayPage" data-role="page" class="page type-interior librarySectionPage withTabs">
<div>
<div class="content-primary">
<form>
<div class="selectContainer">
<select is="emby-select" id="selectDateAdded" data-mini="true" label="${LabelDateAddedBehavior}">
<option value="0">${OptionDateAddedImportTime}</option>
<option value="1">${OptionDateAddedFileTime}</option>
</select>
<div class="fieldDescription">${LabelDateAddedBehaviorHelp}</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label>
<input type="checkbox" is="emby-checkbox" class="chkFolderView" />
@ -10,10 +17,12 @@
</label>
<div class="fieldDescription checkboxFieldDescription">${OptionDisplayFolderViewHelp}</div>
</div>
<label class="checkboxContainer">
<input type="checkbox" is="emby-checkbox" class="chkDisplaySpecialsWithinSeasons"/>
<span>${LabelDisplaySpecialsWithinSeasons}</span>
</label>
<div class="checkboxContainer checkboxContainer-withDescription">
<label>
<input type="checkbox" is="emby-checkbox" class="chkGroupMoviesIntoCollections" />
@ -29,11 +38,19 @@
</label>
<div class="fieldDescription checkboxFieldDescription">${OptionEnableExternalContentInSuggestionsHelp}</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription fldSaveMetadataHidden hide">
<label>
<input type="checkbox" is="emby-checkbox" class="chkAirDays" id="chkSaveMetadataHidden" data-filter="Sunday" />
<span>${OptionSaveMetadataAsHidden}</span>
</label>
<div class="fieldDescription checkboxFieldDescription">${OptionSaveMetadataAsHiddenHelp}</div>
</div>
<br />
<button is="emby-button" type="submit" class="raised button-submit block">
<span>${ButtonSave}</span>
</button>
</form>
</div>
</div>

View file

@ -1,38 +0,0 @@
<div id="librarySettingsPage" data-role="page" class="page type-interior librarySectionPage withTabs">
<div>
<div class="content-primary">
<form class="librarySettingsForm">
<div class="selectContainer">
<select is="emby-select" id="selectDateAdded" data-mini="true" label="${LabelDateAddedBehavior}">
<option value="0">${OptionDateAddedImportTime}</option>
<option value="1">${OptionDateAddedFileTime}</option>
</select>
<div class="fieldDescription">${LabelDateAddedBehaviorHelp}</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription fldSaveMetadataHidden hide">
<label>
<input type="checkbox" is="emby-checkbox" class="chkAirDays" id="chkSaveMetadataHidden" data-filter="Sunday" />
<span>${OptionSaveMetadataAsHidden}</span>
</label>
<div class="fieldDescription checkboxFieldDescription">${OptionSaveMetadataAsHiddenHelp}</div>
</div>
<div is="emby-collapse" title="Fanart.tv">
<div class="collapseContent">
<div class="inputContainer">
<input is="emby-input" type="text" id="txtFanartApiKey" label="${LabelFanartApiKey}" />
<div class="fieldDescription">${LabelFanartApiKeyHelp}</div>
<div class="fieldDescription"><a is="emby-linkbutton" class="button-link" href="https://fanart.tv/2015/01/personal-api-keys" target="_blank">${ButtonLearnMore}</a></div>
</div>
</div>
</div>
<br />
<button is="emby-button" type="submit" class="raised button-submit block"><span>${ButtonSave}</span></button>
</form>
</div>
</div>
</div>

View file

@ -4,7 +4,7 @@
"description": "Jellyfin: the Free Software Media System.",
"lang": "en-US",
"short_name": "Jellyfin",
"start_url": "/web/index.html",
"start_url": "/web/index.html#!/home.html",
"theme_color": "#101010",
"background_color": "#101010",
"display": "standalone",
@ -28,8 +28,5 @@
"src": "touchicon512.png",
"type": "image/png"
}
],
"related_applications": [{
"platform": "web"
}]
]
}

View file

@ -1,13 +1,10 @@
<div id="dashboardHostingPage" data-role="page" class="page type-interior advancedConfigurationPage withTabs">
<div id="networkingPage" data-role="page" class="page type-interior advancedConfigurationPage">
<div>
<div class="content-primary">
<form class="dashboardHostingForm">
<div class="verticalSection verticalSection-extrabottompadding">
<div class="sectionTitleContainer flex align-items-center">
<h2 class="sectionTitle">${TabHosting}</h2>
<h2 class="sectionTitle">${TabNetworking}</h2>
<a is="emby-linkbutton" class="raised button-alt headerHelpButton" target="_blank" href="https://web.archive.org/web/20181216120305/https://github.com/MediaBrowser/Wiki/wiki/Hosting-Settings">${Help}</a>
</div>
@ -97,7 +94,6 @@
</button>
</div>
</form>
</div>
</div>
</div>

View file

@ -23,9 +23,9 @@
</div>
</div>
</div>
<div data-role="popup" id="popupAddTrigger" class="dialog dialog-fixedSize dialog-small hide" style="position: fixed; top: 10%;">
<div data-role="popup" id="popupAddTrigger" class="dialog dialog-fixedSize dialog-medium-tall hide" style="position: fixed; top: 10%;">
<form class="addTriggerForm" style="padding:1em;">
<div class="ui-bar-a" style="text-align: center; padding: 0 20px;">
<div class="ui-bar-a">
<h3>${HeaderAddScheduledTaskTrigger}</h3>
</div>
<div data-role="content">
@ -75,11 +75,11 @@
<input is="emby-input" id="txtTimeLimit" type="number" pattern="[0-9]*" min="1" step=".5" label="${LabelTimeLimitHours}" />
</div>
<div>
<button type="submit" data-icon="check">
${ButtonAdd}
<button is="emby-button" type="submit" class="raised button-submit block" data-icon="check">
<span>${ButtonAdd}</span>
</button>
<button type="button" data-icon="delete" onclick="$(this).parents('.dialog').addClass('hide');">
${ButtonCancel}
<button is="emby-button" type="button" class="raised button-cancel block" data-icon="delete" onclick="$(this).parents('.dialog').addClass('hide');">
<span>${ButtonCancel}</span>
</button>
</div>
</div>

View file

@ -0,0 +1,64 @@
define(["browser"], function (browser) {
"use strict";
function getDeviceIcon(device) {
var baseUrl = "img/devices/";
switch (device) {
case "Opera":
case "Opera TV":
return baseUrl + "opera.svg";
case "Samsung Smart TV":
return baseUrl + "samsung.svg";
case "Xbox One":
return baseUrl + "xbox.svg";
case "Sony PS4":
return baseUrl + "playstation.svg";
case "Chrome":
return baseUrl + "chrome.svg";
case "Firefox":
return baseUrl + "firefox.svg";
case "Edge":
return baseUrl + "edge.svg";
case "Internet Explorer":
return baseUrl + "msie.svg";
case "Web Browser":
return baseUrl + "html5.svg";
default:
return baseUrl + "other.svg";
}
}
function getLibraryIcon(library) {
switch (library) {
case "movies":
return "video_library";
case "music":
return "library_music";
case "photos":
return "photo_library";
case "livetv":
return "live_tv";
case "tvshows":
return "tv";
case "trailers":
return "local_movies";
case "homevideos":
return "photo_library";
case "musicvideos":
return "music_video";
case "books":
return "library_books";
case "channels":
return "videocam";
case "playlists":
return "view_list";
default:
return "folder";
}
}
return {
getDeviceIcon: getDeviceIcon,
getLibraryIcon: getLibraryIcon
};
});

View file

@ -1,4 +1,4 @@
define(["dom", "layoutManager", "inputManager", "connectionManager", "events", "viewManager", "libraryBrowser", "appRouter", "apphost", "playbackManager", "browser", "globalize", "paper-icon-button-light", "material-icons", "scrollStyles", "flexStyles"], function (dom, layoutManager, inputManager, connectionManager, events, viewManager, libraryBrowser, appRouter, appHost, playbackManager, browser, globalize) {
define(["dom", "layoutManager", "inputManager", "connectionManager", "events", "viewManager", "libraryBrowser", "appRouter", "apphost", "playbackManager", "browser", "globalize", "scripts/imagehelper", "paper-icon-button-light", "material-icons", "scrollStyles", "flexStyles"], function (dom, layoutManager, inputManager, connectionManager, events, viewManager, libraryBrowser, appRouter, appHost, playbackManager, browser, globalize, imageHelper) {
"use strict";
function getCurrentApiClient() {
@ -268,7 +268,7 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", "
}, {
name: globalize.translate("TabDashboard"),
href: "dashboard.html",
pageIds: ["dashboardPage", "serverActivityPage"],
pageIds: ["dashboardPage"],
icon: "dashboard"
}, {
name: globalize.translate("General"),
@ -281,15 +281,13 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", "
pageIds: ["userProfilesPage", "newUserPage", "editUserPage", "userLibraryAccessPage", "userParentalControlPage", "userPasswordPage"],
icon: "people"
}, {
name: globalize.translate("TabLibrary"),
name: globalize.translate("HeaderLibraries"),
href: "library.html",
pageIds: ["mediaLibraryPage", "librarySettingsPage", "libraryDisplayPage", "metadataImagesConfigurationPage", "metadataNfoPage"],
icon: "folder",
color: "#38c"
icon: "folder"
}, {
name: globalize.translate("TabPlayback"),
icon: "play_arrow",
color: "#E5342E",
href: "playbackconfiguration.html",
pageIds: ["playbackConfigurationPage", "streamingSettingsPage"]
}, {
@ -309,6 +307,12 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", "
pageIds: ["devicesPage", "devicePage"],
icon: "devices"
});
links.push({
name: globalize.translate("HeaderActivity"),
href: "serveractivity.html",
pageIds: ["serverActivityPage"],
icon: "assessment"
});
links.push({
name: globalize.translate("DLNA"),
href: "dlnasettings.html",
@ -323,24 +327,29 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", "
name: globalize.translate("TabLiveTV"),
href: "livetvstatus.html",
pageIds: ["liveTvStatusPage", "liveTvTunerPage"],
icon: "tv"
icon: "live_tv"
});
links.push({
name: globalize.translate("DVR"),
href: "livetvsettings.html",
pageIds: ["liveTvSettingsPage"],
icon: "list"
icon: "dvr"
});
links.push({
divider: true,
name: globalize.translate("TabExpert")
name: globalize.translate("TabAdvanced")
});
links.push({
name: globalize.translate("TabAdvanced"),
icon: "code",
href: "dashboardhosting.html",
color: "#F16834",
pageIds: ["dashboardHostingPage", "serverSecurityPage"]
name: globalize.translate("TabNetworking"),
icon: "cloud",
href: "networking.html",
pageIds: ["networkingPage"]
});
links.push({
name: globalize.translate("HeaderApiKeys"),
icon: "vpn_key",
href: "apikeys.html",
pageIds: ["apiKeysPage"]
});
links.push({
name: globalize.translate("TabLogs"),
@ -351,14 +360,12 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", "
links.push({
name: globalize.translate("TabNotifications"),
icon: "notifications",
color: "brown",
href: "notificationsettings.html",
pageIds: ["notificationSettingsPage", "notificationSettingPage"]
});
links.push({
name: globalize.translate("TabPlugins"),
icon: "shopping_cart",
color: "#9D22B1",
href: "installedplugins.html",
pageIds: ["pluginsPage", "pluginCatalogPage"]
});
@ -436,8 +443,8 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", "
function createDashboardMenu(apiClient) {
return getToolsMenuHtml(apiClient).then(function (toolsMenuHtml) {
var html = "";
html += '<a class="adminDrawerLogo clearLink" is="emby-linkbutton" href="home.html" style="text-align:left;">';
html += '<img src="img/logoblack.png" />';
html += '<a class="adminDrawerLogo clearLink" is="emby-linkbutton" href="home.html">';
html += '<img src="img/logo.png" />';
html += "</a>";
html += toolsMenuHtml;
navDrawerScrollContainer.innerHTML = html;
@ -525,46 +532,11 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", "
html += globalize.translate("HeaderMedia");
html += "</h3>";
html += items.map(function (i) {
var icon = "folder";
var icon = i.icon || imageHelper.getLibraryIcon(i.CollectionType);
var itemId = i.Id;
if ("channels" === i.CollectionType) {
itemId = "channels";
}
else if ("livetv" === i.CollectionType) {
itemId = "livetv";
}
else if ("photos" === i.CollectionType) {
icon = "photo_library";
}
else if ("music" === i.CollectionType || "musicvideos" === i.CollectionType) {
icon = "library_music";
}
else if ("books" === i.CollectionType) {
icon = "library_books";
}
else if ("playlists" === i.CollectionType) {
icon = "view_list";
}
else if ("movies" === i.CollectionType) {
icon = "video_library";
}
else if ("channels" === i.CollectionType || "Channel" === i.Type) {
icon = "videocam";
}
else if ("tvshows" === i.CollectionType) {
icon = "tv";
}
else if ("livetv" === i.CollectionType) {
icon = "live_tv";
}
icon = i.icon || icon;
if (i.onclick) {
i.onclick;
}
return '<a is="emby-linkbutton" data-itemid="' + itemId + '" class="lnkMediaFolder navMenuOption" href="' + getItemHref(i, i.CollectionType) + '"><i class="md-icon navMenuOptionIcon">' + icon + '</i><span class="sectionName navMenuOptionText">' + i.Name + "</span></a>";
}).join("");
libraryMenuOptions.innerHTML = html;
@ -762,7 +734,9 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", "
return new Promise(function (resolve, reject) {
require(["navdrawer"], function (navdrawer) {
navDrawerInstance = new navdrawer(getNavDrawerOptions());
if (!layoutManager.tv) {
navDrawerElement.classList.remove("hide");
}
resolve(navDrawerInstance);
});
});

View file

@ -58,10 +58,10 @@ define([
roles: "admin"
});
defineRoute({
path: "/dashboardhosting.html",
path: "/networking.html",
autoFocus: false,
roles: "admin",
controller: "dashboardhosting"
controller: "networking"
});
defineRoute({
path: "/devices.html",
@ -334,10 +334,10 @@ define([
controller: "serveractivity"
});
defineRoute({
path: "/serversecurity.html",
path: "/apikeys.html",
autoFocus: false,
roles: "admin",
controller: "serversecurity"
controller: "apikeys"
});
defineRoute({
path: "/streamingsettings.html",

View file

@ -213,17 +213,14 @@ var Dashboard = {
}
},
capabilities: function (appHost) {
var caps = {
var capabilities = {
PlayableMediaTypes: ["Audio", "Video"],
SupportedCommands: ["MoveUp", "MoveDown", "MoveLeft", "MoveRight", "PageUp", "PageDown", "PreviousLetter", "NextLetter", "ToggleOsd", "ToggleContextMenu", "Select", "Back", "SendKey", "SendString", "GoHome", "GoToSettings", "VolumeUp", "VolumeDown", "Mute", "Unmute", "ToggleMute", "SetVolume", "SetAudioStreamIndex", "SetSubtitleStreamIndex", "DisplayContent", "GoToSearch", "DisplayMessage", "SetRepeatMode", "ChannelUp", "ChannelDown", "PlayMediaSource", "PlayTrailers"],
SupportsPersistentIdentifier: "cordova" === self.appMode || "android" === self.appMode,
SupportsMediaControl: true
};
caps.IconUrl = appHost.deviceIconUrl();
caps.SupportsSync = appHost.supports("sync");
caps.SupportsContentUploading = appHost.supports("cameraupload");
appHost.getPushTokenInfo();
return caps = Object.assign(caps, appHost.getPushTokenInfo());
return capabilities = Object.assign(capabilities, appHost.getPushTokenInfo());
}
};
var AppInfo = {};
@ -484,6 +481,9 @@ var AppInfo = {};
onGlobalizeInit(browser);
});
});
require(["keyboardnavigation"], function(keyboardnavigation) {
keyboardnavigation.enable();
});
});
});
}
@ -521,13 +521,13 @@ var AppInfo = {};
}
require(["apphost", "css!css/librarybrowser"], function (appHost) {
loadPlugins([], appHost, browser).then(function () {
loadPlugins(appHost, browser).then(function () {
onAppReady(browser);
});
});
}
function loadPlugins(externalPlugins, appHost, browser, shell) {
function loadPlugins(appHost, browser, shell) {
console.log("Loading installed plugins");
var list = [
"components/playback/playaccessvalidation",
@ -546,8 +546,8 @@ var AppInfo = {};
}
}
for (var index = 0, length = externalPlugins.length; index < length; index++) {
list.push(externalPlugins[index]);
if (window.NativeShell) {
list = list.concat(window.NativeShell.getPlugins());
}
return new Promise(function (resolve, reject) {
@ -880,6 +880,7 @@ var AppInfo = {};
define("serverNotifications", [componentsPath + "/serverNotifications/serverNotifications"], returnFirstDependency);
define("appFooter-shared", ["appFooter"], createSharedAppFooter);
define("skinManager", [componentsPath + "/skinManager"], returnFirstDependency);
define("keyboardnavigation", [componentsPath + "/keyboardnavigation"], returnFirstDependency);
define("connectionManager", [], function () {
return ConnectionManager;
});
@ -1015,6 +1016,9 @@ var AppInfo = {};
}
if ("livetv" === item) {
if ("programs" === options.section) {
return "livetv.html?tab=0&serverId=" + options.serverId;
}
if ("guide" === options.section) {
return "livetv.html?tab=1&serverId=" + options.serverId;
}
@ -1047,6 +1051,10 @@ var AppInfo = {};
return "livetv.html?tab=4&serverId=" + options.serverId;
}
if ("seriesrecording" === options.section) {
return "livetv.html?tab=5&serverId=" + options.serverId;
}
return "livetv.html?serverId=" + options.serverId;
}

View file

@ -1,7 +1,7 @@
<div id="selectServerPage" data-role="page" class="page noSecondaryNavPage standalonePage pageContainer fullWidth vertical flex flex-direction-column">
<div class="verticalSection flex-shrink-zero flex flex-direction-column" style="margin: 2em 0 1em;">
<div class="padded-left padded-right flex align-items-center justify-content-center" style="margin-bottom:2em;">
<h1 class="sectionTitle sectionTitle-cards" style="margin:0;">${HeaderSelectServer}</h1>
<h1 class="sectionTitle sectionTitle-cards">${HeaderSelectServer}</h1>
</div>
<div class="padded-top padded-bottom-focusscale flex-grow flex" data-mousewheel="false" data-horizontal="true" data-centerfocus="card">
<div is="emby-itemscontainer" class="scrollSlider focuscontainer-x padded-left padded-right servers flex-grow" style="display: block; text-align: center;" data-hovermenu="false" data-multiselect="false"></div>

View file

@ -1,13 +1,10 @@
<div id="serverActivityPage" data-role="page" class="page type-interior serverActivityPage noSecondaryNavPage" data-title="${HeaderActivity}">
<div>
<div class="content-primary">
<div class="verticalSection">
<h2 class="sectionTitle">
</h2>
</div>
<div class="readOnlyContent">
<div class="paperList activityItems" data-activitylimit="100">
</div>

View file

@ -1,7 +1,6 @@
{
"AddItemToCollectionHelp": "أضف عناصر إلى المجاميع بالبحث عنهم واستخدام قائمة الزر الأيمن أو قئامة اللمس لإضافتهم إلى المجاميع.",
"AdditionalNotificationServices": "تصفح كتالوج الملحقات لتثبيث خدمات إشعارات إضافية.",
"Advanced": "متقدم",
"Alerts": "التنبيهات",
"All": "الكل",
"AllLibraries": "كل المكتبات",
@ -390,8 +389,6 @@
"LabelExtractChaptersDuringLibraryScan": "استخلص صور الأبواب أثناء تمشيط المكتبة",
"LabelExtractChaptersDuringLibraryScanHelp": "عند التفعيل، فإن صور الأبواب ستُستخلص عندما تدرج الفيديوهات الجديدة أثناء تمشيط المكتبة. عند عدم التفعيل فإن عملية الاستخلاص ستكون محصورة أثناء مهمة صور الأبواب المجدولة، ما يسمح لعملية تمشيط المكتبة أن تنتهي بصورة أسرع.",
"LabelFailed": "العملية فشلت",
"LabelFanartApiKey": "مفتاح api شخصي:",
"LabelFanartApiKeyHelp": "الطلبات الموجهة لخدمة fanart دون حيازة مفتاح api شخصي ستظهر لك الصور التي تم اعتمادها قبل أكثر من 7 أيام. أما مع استعمال مفتاح api شخصي، فإن فترة اعتماد الصور ستنخفض إلى 48 ساعة. أما إذا كنت تملك اشتراك VIP في خدمة fanart فإن فترة الاعتماد ستنخفض إلى 10 دقائق.",
"LabelFileOrUrl": "الملف أو الرابط:",
"LabelFinish": "إنهاء",
"LabelForgotPasswordUsernameHelp": "أدخل اسم المستخدم الخاص بك، إن كنت تتذكرها",
@ -831,11 +828,9 @@
"TabDirectPlay": "تشغيل مباشر",
"TabDisplay": "إظهار",
"TabEpisodes": "الحلقات",
"TabExpert": "الخبير",
"TabFavorites": "المفضلة",
"TabGenres": "أنواع الأفلام",
"TabGuide": "الدليل",
"TabHosting": "الاستضافة",
"TabInfo": "معلومات",
"TabLatest": "الاخير",
"TabLibrary": "المكتبة",
@ -862,7 +857,6 @@
"TabResponses": "الردود",
"TabResumeSettings": "استئناف الإعدادات",
"TabScheduledTasks": "المهام المجدولة",
"TabSecurity": "الحماية",
"TabSeries": "المسلسلات",
"TabServer": "الخادم",
"TabSettings": "الإعدادات",

View file

@ -4,7 +4,6 @@
"AddToCollection": "Добавяне към колекция",
"AddToPlaylist": "Добавяне към списък",
"AddedOnValue": "Добавено на {0}",
"Advanced": "Разширени",
"AirDate": "Дата на излъчване",
"Aired": "Излъчено",
"Albums": "Албуми",
@ -349,8 +348,6 @@
"LabelEvent": "Събитие:",
"LabelEveryXMinutes": "На всеки:",
"LabelFailed": "Неуспешно",
"LabelFanartApiKey": "Личен ППИ ключ:",
"LabelFanartApiKeyHelp": "Заявки до fanart без личен API ключ връщат изображения, които са били одобрени преди повече от 7 дни. С личен API ключ, това време пада на 48 часа, а ако сте и fanart VIP потребител, това става около 10 минути.",
"LabelFinish": "Готово",
"LabelFont": "Шрифт:",
"LabelForgotPasswordUsernameHelp": "Въведете потребителското си име, ако го помните.",
@ -710,11 +707,9 @@
"TabDirectPlay": "Директно пускане",
"TabDisplay": "Показване",
"TabEpisodes": "Епизоди",
"TabExpert": "За напреднали",
"TabFavorites": "Любими",
"TabGenres": "Жанрове",
"TabGuide": "Ръководство",
"TabHosting": "Хостинг",
"TabInfo": "Информация",
"TabLatest": "Последни",
"TabLibrary": "Библиотека",
@ -741,7 +736,6 @@
"TabResponses": "Отговори",
"TabResumeSettings": "Настройки за продължаване",
"TabScheduledTasks": "Планирани задачи",
"TabSecurity": "Защита",
"TabSeries": "Сериали",
"TabServer": "Сървър",
"TabSettings": "Настройки",

View file

@ -4,7 +4,6 @@
"AddToCollection": "Afegeix a col·lecció",
"AddToPlayQueue": "Afegeix a la llista de reproducció",
"AddToPlaylist": "Afegeix a la llista de reproducció",
"Advanced": "Avançat",
"All": "Tot",
"AllChannels": "Tots els canals",
"AllEpisodes": "Tots els episodis",
@ -331,7 +330,6 @@
"LabelExternalDDNS": "Domini extern:",
"LabelExtractChaptersDuringLibraryScan": "Extrau imatges dels episodis durant l'escaneig de la biblioteca",
"LabelFailed": "Fallit",
"LabelFanartApiKey": "Clau api personal:",
"LabelFinish": "Finalitzar",
"LabelFriendlyName": "Nom amistós",
"LabelServerNameHelp": "El nom servirà per identificar aquest servidor. Si es deixa en blanc s'emprarà el nom de l'ordinador.",
@ -702,7 +700,6 @@
"TabRecordings": "Enregistraments",
"TabResponses": "Respostes",
"TabScheduledTasks": "Tasques Programades",
"TabSecurity": "Seguretat",
"TabSeries": "Sèries",
"TabServer": "Servidor",
"TabSettings": "Preferències",

View file

@ -8,7 +8,6 @@
"AddToPlaylist": "Přidat do playlistu",
"AddedOnValue": "Přidáno {0}",
"AdditionalNotificationServices": "Prohlédněte si katalog zásuvných modulů pro nainstalaci další oznámovací služby.",
"Advanced": "Pokročilé",
"Albums": "Alba",
"All": "Vše",
"AllChannels": "Všechny kanály",
@ -305,7 +304,7 @@
"HeaderFrequentlyPlayed": "Nejčastěji přehráváno",
"HeaderGenres": "Žánry",
"HeaderGuideProviders": "Průvodce poskytovatelů",
"HeaderHttpHeaders": "HTTP hlavičky",
"HeaderHttpHeaders": "Http hlavičky",
"HeaderIdentification": "Identifikace",
"HeaderIdentificationCriteriaHelp": "Zadejte alespoň jedno identifikační kritérium.",
"HeaderIdentificationHeader": "Hlavička identifikace",
@ -548,8 +547,6 @@
"LabelExtractChaptersDuringLibraryScan": "Extrakce obrázků kapitol během prohledávání vaší knihovny",
"LabelExtractChaptersDuringLibraryScanHelp": "Jestliže povolíte, budou snímky kapitol extrahovány při pravidelném prohledávání vaší knihovny. Pokud zakážete budou snímky extrahovány během naplánované úlohy pro extrakci snímků z kapitol, což umožní, při pravidelném prohledávání vaší knihovny, dokončit skenování rychleji.",
"LabelFailed": "Selhání",
"LabelFanartApiKey": "Osobní klíč api:",
"LabelFanartApiKeyHelp": "Žádosti o fanart bez osobního API klíče vrátí pouze výsledky, které byly schváleny před 7-mi dny a dříve. S osobním API klíčem, získáte schválené výsledky do 48 hodin, a pokud jste fanart VIP člen, pak limit klesne na 10 minut.",
"LabelFileOrUrl": "Soubor nebo URL:",
"LabelFinish": "Dokončit",
"LabelFont": "Písmo:",
@ -621,8 +618,8 @@
"LabelMetadataSaversHelp": "Vyberte formáty souborů pro uložení metadat.",
"LabelMethod": "Metoda:",
"LabelMinBackdropDownloadWidth": "Maximální šířka pro stažení pozadí:",
"LabelMinResumeDuration": "Minimální doba trvání (v sekundách):",
"LabelMinResumeDurationHelp": "Tituly kratší než tato délka nebudou pozastavitelné",
"LabelMinResumeDuration": "Minimální doba trvání:",
"LabelMinResumeDurationHelp": "Videa kratší než tato délka nebudou pozastavitelné",
"LabelMinResumePercentage": "Minimální procento pro přerušení:",
"LabelMinResumePercentageHelp": "Tituly budou označeny jako \"nepřehráno\", pokud budou zastaveny před tímto časem",
"LabelMinScreenshotDownloadWidth": "Minimální šířka screenshotu obrazovky:",
@ -1146,7 +1143,6 @@
"TabFavorites": "Oblíbené",
"TabGenres": "Žánry",
"TabGuide": "Průvodce",
"TabHosting": "Hostování",
"TabLatest": "Nejnovější",
"TabLibrary": "Knihovna",
"TabLogs": "Záznamy",
@ -1155,7 +1151,7 @@
"TabMusicVideos": "Hudební videa",
"TabMyPlugins": "Moje zásuvné moduly",
"TabNetworks": "Sítě",
"TabNfoSettings": "Nfo nastavení",
"TabNfoSettings": "NFO nastavení",
"TabNotifications": "Oznámení",
"TabOther": "Další",
"TabParentalControl": "Rodičovská kontrola",
@ -1167,9 +1163,8 @@
"TabProfiles": "Profily",
"TabRecordings": "Nahrané",
"TabResponses": "Odpovědi",
"TabResumeSettings": "Obnovit nastavení",
"TabResumeSettings": "Obnovit",
"TabScheduledTasks": "Naplánované úlohy",
"TabSecurity": "Zabezpečení",
"TabSeries": "Série",
"TabSettings": "Nastavení",
"TabShows": "Seriály",
@ -1388,7 +1383,7 @@
"LabelHomeNetworkQuality": "Kvalita na domácí síti:",
"LabelInternetQuality": "Kvalita na internetu:",
"LabelKodiMetadataUser": "Uložení dat sledování uživatele do nfo pro:",
"LabelKodiMetadataUserHelp": "Povolte toto nastavení pro uložení dat sledování do souborů nfo pro jiné aplikace, které chcete používat.",
"LabelKodiMetadataUserHelp": "Povolte toto nastavení pro uložení dat sledování do souborů NFO pro jiné aplikace, které chcete používat.",
"LabelLanNetworks": "Sítě LAN:",
"LabelLimit": "Limit:",
"LabelMaxStreamingBitrate": "Maximální kvalita streamování:",
@ -1515,7 +1510,6 @@
"SubtitleSettingsIntro": "Chcete-li nastavit výchozí vzhled a jazyk titulků, zastavte přehrávání videa a klepněte na ikonu uživatele v pravé horní části aplikace.",
"TV": "TV",
"TabDirectPlay": "Přímé přehrávání",
"TabExpert": "Expert",
"TabInfo": "Info",
"TabLiveTV": "Live TV",
"TabMetadata": "Metadata",
@ -1535,5 +1529,24 @@
"Vertical": "Svisle",
"VideoRange": "Rozsah videa",
"ViewPlaybackInfo": "Zobrazení informací o přehrávání",
"Whitelist": "Whitelist"
"Whitelist": "Whitelist",
"HeaderHome": "Domů",
"HeaderHomeSettings": "Nastavení domov. obrazovky",
"DashboardOperatingSystem": "Operační systém: {0}",
"DashboardArchitecture": "Architektura: {0}",
"LaunchWebAppOnStartup": "Spusťte webovou aplikaci Jellyfin ve svém webovém prohlížeči po nastartování Jellyfin serveru",
"LaunchWebAppOnStartupHelp": "Toto otevře se webovou aplikaci ve vašem výchozím webovém prohlížeči, když se spustí server Jellyfin. K tomu nedochází při použití funkce restartování serveru.",
"MessageNoServersAvailable": "Pomocí automatického zjišťování nebyly nalezeny žádné servery.",
"OptionBanner": "Banner",
"OptionList": "Seznam",
"OptionPoster": "Plakát",
"OptionPosterCard": "Filmový pás",
"OptionThumb": "Náhled",
"OptionThumbCard": "Panel náhledů",
"PlaybackData": "Data přehrávání",
"MusicAlbum": "Hudební album",
"MusicArtist": "Interpret",
"MusicVideo": "Videoklip",
"SubtitleOffset": "Nastavení titulků",
"TabNetworking": "Vytváření sítí"
}

View file

@ -7,7 +7,6 @@
"AddToPlaylist": "Tilføj til afspilningsliste",
"AddedOnValue": "Tilføjet {0}",
"AdditionalNotificationServices": "Kig i plugin-kataloget for at få yderligere uderretnings-tjenester",
"Advanced": "Avanceret",
"Alerts": "Advarsler",
"All": "Alle",
"AllChannels": "Alle kanaler",
@ -483,8 +482,6 @@
"LabelExtractChaptersDuringLibraryScan": "Udtræk kapitelbilleder under biblioteksskanning",
"LabelExtractChaptersDuringLibraryScanHelp": "Aktiver dette for at udtrække kapitelbillleder mens videofiler bliver importeret under biblioteksskanningen. Hvi det ikke er aktiveret, bliver de udtrukket når den planlagte opgave kapitelbilleder kører, og lader den almindelige biblioteksskanning afslutte hurtigere.",
"LabelFailed": "Fejlet",
"LabelFanartApiKey": "Personlig API nøgle:",
"LabelFanartApiKeyHelp": "Forespørgsler til fanart uden en personlig api nøgle returnerer resultater godkendt for over 7 dage siden. Med en personlig api nøgle falder dette til 48 timer, og hvis du er fanart VIP-medlem falder dette yderligere til omkring 10 minutter.",
"LabelFileOrUrl": "Fil eller url:",
"LabelFinish": "Afslut",
"LabelForgotPasswordUsernameHelp": "Indtast dit brugernavn, hvis du kan huske det.",
@ -1019,7 +1016,6 @@
"TabDirectPlay": "Direkte afspilning",
"TabDisplay": "Visning",
"TabEpisodes": "Episoder",
"TabExpert": "Ekspert",
"TabFavorites": "Favoritter",
"TabGenres": "Genre",
"TabLatest": "Seneste",
@ -1043,7 +1039,6 @@
"TabResponses": "Svar",
"TabResumeSettings": "Indstillinger for Genoptag",
"TabScheduledTasks": "Planlagte opgaver",
"TabSecurity": "Sikkerhed",
"TabSeries": "Serier",
"TabSettings": "Indstillinger",
"TabShows": "Serier",
@ -1494,7 +1489,6 @@
"TabCodecs": "Codeks",
"TabDLNA": "DLNA",
"TabGuide": "Vejledning",
"TabHosting": "Vært",
"TabInfo": "Information",
"TabLiveTV": "Live TV",
"TabLogs": "Log",

View file

@ -12,7 +12,6 @@
"AddUserByManually": "Lege einen lokalen User durch manuelle Eingabe der User-Informationen an.",
"AddedOnValue": "Hinzugefügt {0}",
"AdditionalNotificationServices": "Schau im Pluginkatalog, um weitere Benachrichtigungsdienste zu installieren.",
"Advanced": "Fortgeschritten",
"AirDate": "Erstausstrahlung",
"Aired": "Ausgestrahlt",
"Albums": "Alben",
@ -23,7 +22,7 @@
"AllLanguages": "Alle Sprachen",
"AllLibraries": "Alle Bibliotheken",
"AllowDeletionFromAll": "Erlaube Medienlöschung in allen Bibliotheken",
"AllowHWTranscodingHelp": "Wenn aktiviert, erlaube dem Empfänger eine Transkodierung des Streams in Echtzeit vorzunehmen. Kann CPU-Ressourcen sparen",
"AllowHWTranscodingHelp": "Wenn aktiviert, übernimmt der Tuner die Transkodierung in Echtzeit. Das hilft eventuell die Transkodierung auf dem Jellyfin Servers zu reduzieren. (Spart Hardwareressourcen)",
"AllowMediaConversion": "Erlaube Medienkonvertierung",
"AllowMediaConversionHelp": "Erlaube oder unterbinde Zugriff auf die Medienkonvertierung.",
"AllowOnTheFlySubtitleExtraction": "Erlaube Untertitelextraktion \"on-the-fly\"",
@ -145,7 +144,7 @@
"ColorSpace": "Farbraum",
"CommunityRating": "Community Bewertung",
"Composer": "Komponist",
"ConfigureDateAdded": "Bestimme in den Bibliotheks-Einstellungen des Jellyfin Server Dashboards, wie das Feld \"Hinzugefügt am\" interpretiert werden soll.",
"ConfigureDateAdded": "Bestimme in den Bibliotheks-Einstellungen des Jellyfin Server Dashboards, wie das Feld \"Hinzugefügt am\" interpretiert werden soll",
"ConfirmDeleteImage": "Bild löschen?",
"ConfirmDeleteItem": "Löschen dieses Eintrages bedeutet das Löschen der Datei und das Entfernen aus der Medien-Bibliothek. Möchtest du wirklich fortfahren?",
"ConfirmDeleteItems": "Das Löschen dieser Objekte löscht die Dateien vom Laufwerk und in deiner Medienbibliothek. Bist du wirklich sicher?",
@ -344,7 +343,7 @@
"HeaderFrequentlyPlayed": "Oft gesehen",
"HeaderGuideProviders": "Fernsehprogramm Quellen",
"HeaderIdentification": "Identifizierung",
"HeaderIdentificationCriteriaHelp": "Gebe mindestens ein Identifikationskriterium an.",
"HeaderIdentificationCriteriaHelp": "Gib mindestens ein Identifikationskriterium an.",
"HeaderIdentificationHeader": "Identfikations Header",
"HeaderIdentifyItemHelp": "Gib ein oder mehrere Suchkriterien ein. Entferne Kriterien um die Suchergebnisse zu erweitern.",
"HeaderImageOptions": "Bild Einstellungen",
@ -354,7 +353,7 @@
"HeaderItems": "Inhalte",
"HeaderKeepRecording": "Aufnahme behalten",
"HeaderKeepSeries": "Serie behalten",
"HeaderKodiMetadataHelp": "Jellyfin bietet native Unterstützung von Nfo Metadatendateien. Um Nfo Metadaten zu aktivieren oder deaktivieren, verwende den \"Metadaten\" Tab um die Optionen für deinen Medientypen zu konfigurieren.",
"HeaderKodiMetadataHelp": "Jellyfin bietet native Unterstützung von NFO Metadatendateien. Um NFO Metadaten zu aktivieren oder deaktivieren, verwende den \"Metadaten\" Tab um die Optionen für deinen Medientypen zu konfigurieren.",
"HeaderLatestEpisodes": "Neueste Episoden",
"HeaderLatestMedia": "Neueste Medien",
"HeaderLatestMovies": "Neueste Filme",
@ -594,8 +593,6 @@
"LabelExtractChaptersDuringLibraryScan": "Erzeuge Kapitelbilder während des Bibliothekscans",
"LabelExtractChaptersDuringLibraryScanHelp": "Fall aktiviert, werden Kapitelbilder während des Imports von Videos beim Bibliothekenscan erzeugt. Falls deaktiviert, werden die Kapitelbilder während einer eigens dafür geplanten Aufgabe erstellt, was den regelmäßig Bibliothekenscan beschleunigt.",
"LabelFailed": "Fehlgeschlagen",
"LabelFanartApiKey": "Persönlicher API Schlüssel:",
"LabelFanartApiKeyHelp": "Fanart Anfragen ohne einen persönlichen API Schlüssel liefert Bilder der letzten 7 Tage. Bei Verwendung eines persönlichen API Schlüssels werden Ergebnisse der letzten 48 Stunden, und als VIP Member, der letzten 10 Minuten geliefert.",
"LabelFileOrUrl": "Datei oder URL:",
"LabelFinish": "Fertig",
"LabelFont": "Schriftart:",
@ -629,7 +626,7 @@
"LabelKodiMetadataEnableExtraThumbs": "Kopiere Extrafanart in Extrathumbs",
"LabelKodiMetadataEnableExtraThumbsHelp": "Beim downloaden von Bildern können diese sowohl als Extrafanart als auch als Extrathumb gespeichert werden, um maximale Kodi Kompatibilität zu erzielen.",
"LabelKodiMetadataEnablePathSubstitution": "Aktiviere Pfadersetzung",
"LabelKodiMetadataEnablePathSubstitutionHelp": "Aktiviert die Pfadersetzung für Bildpfade durch Benutzung der Server Pfadersetzung Einstellungen",
"LabelKodiMetadataEnablePathSubstitutionHelp": "Aktiviert die Pfadersetzung für Bildpfade durch Benutzung der Server Pfadersetzung Einstellungen.",
"LabelKodiMetadataSaveImagePaths": "Speicher Bildpfade innerhalb der NFO Dateien",
"LabelKodiMetadataSaveImagePathsHelp": "Dies ist empfehlenswert wenn du Dateinamen hast, die nicht den Kodi Richtlinien entsprechen.",
"LabelKodiMetadataUser": "Speichere den \"Gesehen\" Status von Benutzern in NFO's für:",
@ -666,8 +663,8 @@
"LabelMetadataSaversHelp": "Wähle das Dateiformat in dem deine Metadaten gespeichert werden sollen.",
"LabelMethod": "Methode:",
"LabelMinBackdropDownloadWidth": "Minimale Breite für zu herunterladende Hintergründe:",
"LabelMinResumeDuration": "Minimale Dauer für Wiederaufnahme (Sekunden):",
"LabelMinResumeDurationHelp": "Titel die kürzer als dieser Wert sind, werden nicht fortsetzbar sein",
"LabelMinResumeDuration": "Minimale Dauer für Wiederaufnahme:",
"LabelMinResumeDurationHelp": "Die kürzeste Videolänge in Sekunden, die den Wiedergabeplatz speichert und dich fortsetzen lässt",
"LabelMinResumePercentage": "Minimale Prozent für Wiederaufnahme:",
"LabelMinResumePercentageHelp": "Titel werden als \"Ungesehen\" eingetragen, wenn sie vor dieser Zeit gestoppt werden",
"LabelMinScreenshotDownloadWidth": "Minimale Breite für zu herunterladende Screenshot:",
@ -684,7 +681,7 @@
"LabelMusicStreamingTranscodingBitrateHelp": "Wähle die maximale Bitrate für das streamen von Musik",
"LabelNewName": "Neuer Name:",
"LabelNewPassword": "Neues Passwort:",
"LabelNewPasswordConfirm": "Neues Passwort wiederhohlen:",
"LabelNewPasswordConfirm": "Neues Passwort wiederholen:",
"LabelNewsCategories": "Nachrichtenkategorien:",
"LabelNext": "Nächstes",
"LabelNotificationEnabled": "Aktiviere diese Benachrichtigung",
@ -754,7 +751,7 @@
"LabelSkipBackLength": "Sprungweite rückwärts:",
"LabelSkipForwardLength": "Sprungweite vorwärts:",
"LabelSkipIfAudioTrackPresent": "Überspringen, falls der Ton bereits der herunterladbaren Sprache entspricht",
"LabelSkipIfAudioTrackPresentHelp": "Entferne den Haken, um sicherzustellen das alle Videos Untertitel haben, unabhängig von der Audiosprache",
"LabelSkipIfAudioTrackPresentHelp": "Entferne den Haken, um sicherzustellen das alle Videos Untertitel haben, unabhängig von der Audiosprache.",
"LabelSkipIfGraphicalSubsPresent": "Überspringen, falls das Video bereits eingebettete Untertitel enthält",
"LabelSkipIfGraphicalSubsPresentHelp": "Das Vorhalten von textbasierten Untertiteln führt zu einer effizienteren Anzeige und verringert die Wahrscheinlichkeit einer Videotranskodierung.",
"LabelSonyAggregationFlags": "Sony Aggregation Flags:",
@ -814,7 +811,7 @@
"LabelZipCode": "PLZ:",
"LabelffmpegPath": "FFmpeg Verzeichnis:",
"LabelffmpegPathHelp": "Verzeichnis zur runtergeladenen FFmpeg Applikation oder zum Ordner, der FFMpeg enthält.",
"LanNetworksHelp": "Komma separierte Liste von IP Adressen oder IP Masken die als lokale Netzwerke behandelt werden sollen um Bandbreitenlimitationen auszusetzen. Wenn befüllt werden alle anderen IP Adressen als externe Netzwerke behandelt und unterliegen den Bandbreitenlimitationen für externe Verbindungen. Wenn leer, wird nur das SubNetz des Servers als Lokales Netz gesetzt-",
"LanNetworksHelp": "Komma separierte Liste von IP Adressen oder IP Masken die als lokale Netzwerke behandelt werden sollen um Bandbreitenlimitationen auszusetzen. Wenn befüllt werden alle anderen IP Adressen als externe Netzwerke behandelt und unterliegen den Bandbreitenlimitationen für externe Verbindungen. Wenn leer, wird nur das SubNetz des Servers als Lokales Netz gesetzt.",
"Large": "Groß",
"LatestFromLibrary": "Neueste {0}",
"LearnHowYouCanContribute": "Erfahre, wie du unterstützen kannst.",
@ -848,7 +845,7 @@
"MediaInfoTimestamp": "Zeitstempel",
"MediaIsBeingConverted": "Das Medium wird in ein Format konvertiert, das mit dem Abspielgerät kompatibel ist.",
"Menu": "Menü",
"MessageAlreadyInstalled": "Diese Version ist bereits installiert",
"MessageAlreadyInstalled": "Diese Version ist bereits installiert.",
"MessageAreYouSureDeleteSubtitles": "Bist du dir sicher diese Untertitel Datei löschen zu wollen?",
"MessageAreYouSureYouWishToRemoveMediaFolder": "Bist du dir sicher dieses Medienverzeichnis entfernen zu wollen?",
"MessageConfirmDeleteGuideProvider": "Möchten Sie diese Quelle wirklich löschen?",
@ -873,8 +870,8 @@
"MessageInstallPluginFromApp": "Dieses Plugin muss von der App aus installiert werden, mit der du es benutzen willst.",
"MessageInvalidForgotPasswordPin": "Ein ungültiger oder abgelaufener PIN wurde eingegeben. Bitte versuche es noch einmal.",
"MessageInvalidUser": "Falscher Benutzername oder Passwort. Bitte versuche es noch einmal.",
"MessageItemSaved": "Element gespeichert",
"MessageItemsAdded": "Einträge hinzugefügt",
"MessageItemSaved": "Element gespeichert.",
"MessageItemsAdded": "Einträge hinzugefügt.",
"MessageLeaveEmptyToInherit": "Freilassen für die Vererbung von Berechtigungen oder dem systemweiten Standardwert.",
"MessageNoAvailablePlugins": "Keine verfügbaren Erweiterungen.",
"MessageNoMovieSuggestionsAvailable": "Momentan sind keine Filmvorschläge verfügbar. Schaue und bewerte zuerst deine Filme. Komme danach zurück, um deine Filmvorschläge anzuschauen.",
@ -888,7 +885,7 @@
"MessagePluginConfigurationRequiresLocalAccess": "Melde dich bitte direkt an deinem lokalen Server an, um dieses Plugin konfigurieren zu können.",
"MessagePluginInstallDisclaimer": "Plugins aus der Jellyfin Community sind eine gute Möglichkeit um Jellyfin mit weiteren Funktionen und Vorteilen aufzuwerten. Bevor Sie diese jedoch installieren, seien Sie sich den daraus resultierenden möglichen Umständen für Jellyfin bewusst. Dies können z.B. längere Bibliotheken Scans, weiterführende Verarbeitung von Daten im Hintergrund sowie Systeminstabilität sein.",
"MessageReenableUser": "Für Reaktivierung schauen Sie unten",
"MessageSettingsSaved": "Einstellungen gespeichert",
"MessageSettingsSaved": "Einstellungen gespeichert.",
"MessageTheFollowingLocationWillBeRemovedFromLibrary": "Die folgenden Medienverzeichnisse werden aus der Jellyfin Bibliothek entfernt:",
"MessageUnableToConnectToServer": "Wir können gerade keine Verbindung zum gewählten Server herstellen. Bitte stellen Sie sicher das dieser läuft und versuchen Sie es erneut.",
"MessageUnsetContentHelp": "Inhalte werden als Verzeichnisse dargestellt. Für eine besser Anzeige nutzen Sie nach Möglichkeit den Meta-Data Manager und wählen Sie einen Medien-Typen für Unterverzeichnisse.",
@ -947,13 +944,13 @@
"OptionAllowRemoteControlOthers": "Erlaube Fernsteuerung anderer Benutzer",
"OptionAllowRemoteSharedDevices": "Erlaube Fernsteuerung geteilter Geräte",
"OptionAllowRemoteSharedDevicesHelp": "DLNA-Geräte werden gemeinsam genutzt, bis ein Benutzer die Steuerung übernimmt.",
"OptionAllowSyncTranscoding": "Erlaube Herunterladen von Dateien, die transkodiert werden müssen.",
"OptionAllowSyncTranscoding": "Erlaube Herunterladen von Dateien, die transkodiert werden müssen",
"OptionAllowUserToManageServer": "Dieser Benutzer kann den Server managen",
"OptionAllowVideoPlaybackRemuxing": "Erlaube Video-Wiedergabe mittels Konvertierung ohne Neu-Enkodierung",
"OptionAllowVideoPlaybackTranscoding": "Erlaube Video-Wiedergabe die Transkodierung benötigt",
"OptionArtist": "Interpret",
"OptionAscending": "Aufsteigend",
"OptionAutomaticallyGroupSeries": "Vermische Serieninhalte, die in verschiedenen Ordnern abgelegt sind.",
"OptionAutomaticallyGroupSeries": "Vermische Serieninhalte, die in verschiedenen Ordnern abgelegt sind",
"OptionAutomaticallyGroupSeriesHelp": "Wenn aktiviert, werden Inhalte einer Serie in verschiedenen Ordnern innerhalb einer Bibliothek als eine Serie angezeigt.",
"OptionBlockBooks": "Bücher",
"OptionBlockChannelContent": "Internet Channelinhalte",
@ -1030,9 +1027,9 @@
"OptionPlayed": "Gesehen",
"OptionPremiereDate": "Premiere",
"OptionReleaseDate": "Veröffentlichungsdatum",
"OptionReportByteRangeSeekingWhenTranscoding": "Teilt die Unterstützung der Bytesuche während des transkodierens auf dem Server mit.",
"OptionReportByteRangeSeekingWhenTranscoding": "Teilt die Unterstützung der Bytesuche während des transkodierens auf dem Server mit",
"OptionReportByteRangeSeekingWhenTranscodingHelp": "Dies wird für manche Abspielgeräte benötigt, auf denen die Zeitsuche nicht gut funktioniert.",
"OptionRequirePerfectSubtitleMatch": "Lade nur Untertitel mit einem perfekten Ergebnis zu meinen Videos.",
"OptionRequirePerfectSubtitleMatch": "Lade nur Untertitel mit einem perfekten Ergebnis zu meinen Videos",
"OptionRequirePerfectSubtitleMatchHelp": "Perfektes Ergebnis wählt beim Filtern nur Untertitel, welche getestet und für deine exakte Videodatei verifiziert wurden. Die Abwahl dieser Option erhöht die Chance, dass Untertitel heruntergeladen werden, die Möglichkeit falscher Untertitel oder dass Text an falschen Positionen angezeigt wird ist aber ebenfalls größer.",
"OptionResElement": "Res Element",
"OptionResumable": "Fortsetzen",
@ -1053,20 +1050,20 @@
"OptionWeekly": "Wöchentlich",
"OriginalAirDateValue": "Erstausstrahlung: {0}",
"Overview": "Übersicht",
"PackageInstallCancelled": "{0} Installation abgebrochen",
"PackageInstallCompleted": "{0} Installation abgeschlossen",
"PackageInstallFailed": "{0} Installation fehlgeschlagen",
"PackageInstallCancelled": "{0} Installation abgebrochen.",
"PackageInstallCompleted": "{0} Installation abgeschlossen.",
"PackageInstallFailed": "{0} Installation fehlgeschlagen.",
"ParentalRating": "Altersfreigabe",
"PasswordMatchError": "Die Passwörter müssen übereinstimmen.",
"PasswordResetComplete": "Das Passwort wurde zurückgesetzt.",
"PasswordResetConfirmation": "Möchtest du das Passwort wirklich zurücksetzen?",
"PasswordResetHeader": "Passwort zurücksetzen",
"PasswordSaved": "Passwort gespeichert",
"PasswordSaved": "Passwort gespeichert.",
"People": "Personen",
"PerfectMatch": "Perfektes Ergbnis",
"Photos": "Fotos",
"PictureInPicture": "Bild-in-Bild",
"PinCodeResetComplete": "Der PIN wurde zurückgesetzt",
"PinCodeResetComplete": "Der PIN wurde zurückgesetzt.",
"PinCodeResetConfirmation": "Sind Sie sich sicher, dass Sie Ihren PIN Code zurücksetzen möchten?",
"PlaceFavoriteChannelsAtBeginning": "Platziere favorisierte Kanäle am Anfang",
"Play": "Abspielen",
@ -1085,7 +1082,7 @@
"PluginInstalledMessage": "Das Plugin wurde erfolgreich installiert. Der Jellyfin-Server muss neu gestartet werden, um die Änderungen zu übernehmen.",
"PreferEmbeddedTitlesOverFileNames": "Bevorzuge eingebettete Titel vor Dateinamen",
"PreferEmbeddedTitlesOverFileNamesHelp": "Das bestimmt den Standard Displaytitel wenn keine lokale oder Internetmetadaten verfügbar sind.",
"PreferredNotRequired": "Bevorzugt, aber nicht benötigt.",
"PreferredNotRequired": "Bevorzugt, aber nicht benötigt",
"Premieres": "Premieren",
"Previous": "Vorheriges",
"Primary": "Primär",
@ -1163,7 +1160,7 @@
"Shows": "Serien",
"Shuffle": "Zufallswiedergabe",
"SimultaneousConnectionLimitHelp": "Die maximale Anzahl der parallel erlaubten Streams. 0 für kein Limit.",
"SkipEpisodesAlreadyInMyLibrary": "Nehme keine Episoden auf, die schon in meiner Bibliothek verfügbar sind.",
"SkipEpisodesAlreadyInMyLibrary": "Nehme keine Episoden auf, die schon in meiner Bibliothek verfügbar sind",
"SkipEpisodesAlreadyInMyLibraryHelp": "Episoden werden mittels Staffel- und Episodennummer verglichen, wenn verfügbar.",
"Small": "Klein",
"SmallCaps": "Kapitälchen",
@ -1197,7 +1194,6 @@
"TabDirectPlay": "Direktwiedergabe",
"TabDisplay": "Anzeige",
"TabEpisodes": "Episoden",
"TabExpert": "Experte",
"TabFavorites": "Favoriten",
"TabGuide": "Programm",
"TabLatest": "Neueste",
@ -1209,7 +1205,7 @@
"TabMusicVideos": "Musikvideos",
"TabMyPlugins": "Meine Plugins",
"TabNetworks": "Sendergruppen",
"TabNfoSettings": "Nfo Einstellungen",
"TabNfoSettings": "NFO Einstellungen",
"TabNotifications": "Benachrichtigungen",
"TabOther": "Andere",
"TabParentalControl": "Kindersicherung",
@ -1221,9 +1217,8 @@
"TabProfiles": "Profile",
"TabRecordings": "Aufnahmen",
"TabResponses": "Antworten",
"TabResumeSettings": "Fortsetzen Einstellungen",
"TabResumeSettings": "Fortsetzen",
"TabScheduledTasks": "Geplante Aufgaben",
"TabSecurity": "Sicherheit",
"TabSeries": "Serie",
"TabSettings": "Einstellungen",
"TabShows": "Serien",
@ -1384,7 +1379,6 @@
"TV": "TV",
"TabCodecs": "Codecs",
"TabGenres": "Genres",
"TabHosting": "Hosting",
"TabInfo": "Info",
"TabLogs": "Protokoll",
"TabPlugins": "Plugins",
@ -1447,5 +1441,7 @@
"OptionLoginAttemptsBeforeLockout": "Legt fest, wie viele falsche Anmeldeversuche durchgeführt werden können, bevor es zur Sperrung kommt.",
"OptionLoginAttemptsBeforeLockoutHelp": "0 bedeutet, die Vorgabe von 3 für Nicht-Administratoren und 5 für Administratoren zu übernehmen, -1 deaktiviert die Sperre",
"PasswordResetProviderHelp": "Wählen Sie einen Password Reset Provider, der verwendet werden soll, wenn dieser Benutzer ein Passwort zurücksetzen möchte",
"Box": "Box"
"Box": "Box",
"HeaderHome": "Home",
"HeaderHomeSettings": "Home Einstellungen"
}

View file

@ -8,7 +8,6 @@
"AddToPlaylist": "Πρόσθεσε σε λίστα",
"AddedOnValue": "Προστέθηκε {0}",
"AdditionalNotificationServices": "Περιηγηθείτε στον κατάλογο plugin για να εγκαταστήσετε πρόσθετες υπηρεσίες ειδοποίησης.",
"Advanced": "Για προχωρημένους",
"AirDate": "Ημερομηνία προβολής",
"Aired": "Προβλήθηκε",
"Albums": "Άλμπουμ",
@ -534,8 +533,6 @@
"LabelExtractChaptersDuringLibraryScan": "Εξαγωγή εικόνων κεφαλαίου κατά τη διάρκεια της σάρωσης βιβλιοθήκης",
"LabelExtractChaptersDuringLibraryScanHelp": "Αν είναι ενεργοποιημένη, οι εικόνες κεφαλαίων θα εξαχθούν όταν εισάγονται βίντεο κατά τη διάρκεια της σάρωσης της βιβλιοθήκης. Αν απενεργοποιηθούν, θα εξαχθούν κατά τη διάρκεια της προγραμματισμένης εργασίας των κεφαλαίων, επιτρέποντας την ταχύτερη ολοκλήρωση της σάρωσης κανονικής βιβλιοθήκης.",
"LabelFailed": "Αποτυχία",
"LabelFanartApiKey": "Προσωπικό κλειδί api :",
"LabelFanartApiKeyHelp": "Τα αιτήματα για προβολή χωρίς προσωπικό κλειδί API επιστρέφουν εικόνες που εγκρίθηκαν πριν από 7 ημέρες. Με ένα προσωπικό κλειδί API που πέφτει σε 48 ώρες και αν είστε επίσης fanart μέλος VIP που θα μειωθεί περαιτέρω σε περίπου 10 λεπτά.",
"LabelFinish": "Τέλος",
"LabelFont": "Γραμματοσειρά: ",
"LabelForgotPasswordUsernameHelp": "Εισαγωγή όνομα χρήστη,αν το θυμάστε.",
@ -1072,11 +1069,9 @@
"TabDirectPlay": "Άμεση Αναπαραγωγή",
"TabDisplay": "Εμφάνιση",
"TabEpisodes": "Επεισόδια",
"TabExpert": "Ειδικός",
"TabFavorites": "Αγαπημένα",
"TabGenres": "Είδη",
"TabGuide": "Οδηγός",
"TabHosting": "Φιλοξενία",
"TabInfo": "Πληροφορία",
"TabLatest": "Τελευταία",
"TabLibrary": "Βιβλιοθήκη",
@ -1100,7 +1095,6 @@
"TabRecordings": "Εγγραφές",
"TabResponses": "Απαντήσεις",
"TabScheduledTasks": "Προγραμματισμένες Εργασίες",
"TabSecurity": "Aσφάλεια ",
"TabSeries": "Σειρές",
"TabServer": "Διακομιστής",
"TabSettings": "Ρυθμισεις",

View file

@ -58,7 +58,6 @@
"AddToPlayQueue": "Add to play queue",
"AddToPlaylist": "Add to playlist",
"AddedOnValue": "Added {0}",
"Advanced": "Advanced",
"AirDate": "Air date",
"Aired": "Aired",
"Alerts": "Alerts",

View file

@ -9,7 +9,6 @@
"AddToPlaylist": "Add to playlist",
"AddedOnValue": "Added {0}",
"AdditionalNotificationServices": "Browse the plugin catalog to install additional notification services.",
"Advanced": "Advanced",
"AirDate": "Air date",
"Aired": "Aired",
"Albums": "Albums",
@ -299,7 +298,7 @@
"HeaderAllowMediaDeletionFrom": "Allow Media Deletion From",
"HeaderApiKey": "API Key",
"HeaderApiKeys": "API Keys",
"HeaderApiKeysHelp": "External applications are required to have an API key in order to communicate with Jellyfin Server. Keys are issued by logging in with an Jellyfin account, or by manually granting the application a key.",
"HeaderApiKeysHelp": "External applications are required to have an API key in order to communicate with Jellyfin Server. Keys are issued by logging in with a Jellyfin account, or by manually granting the application a key.",
"HeaderApp": "App",
"HeaderAppearsOn": "Appears On",
"HeaderAudioBooks": "Audio Books",
@ -371,7 +370,7 @@
"HeaderGuideProviders": "TV Guide Data Providers",
"HeaderHome": "Home",
"HeaderHomeSettings": "Home Settings",
"HeaderHttpHeaders": "Http Headers",
"HeaderHttpHeaders": "HTTP Headers",
"HeaderIdentification": "Identification",
"HeaderIdentificationCriteriaHelp": "Enter at least one identification criteria.",
"HeaderIdentificationHeader": "Identification Header",
@ -636,8 +635,6 @@
"LabelExtractChaptersDuringLibraryScan": "Extract chapter images during the library scan",
"LabelExtractChaptersDuringLibraryScanHelp": "If enabled, chapter images will be extracted when videos are imported during the library scan. If disabled they will be extracted during the chapter images scheduled task, allowing the regular library scan to complete faster.",
"LabelFailed": "Failed",
"LabelFanartApiKey": "Personal api key:",
"LabelFanartApiKeyHelp": "Requests to fanart without a personal API key return images that were approved over 7 days ago. With a personal API key that drops to 48 hours and if you are also a fanart VIP member that will further drop to around 10 minutes.",
"LabelFileOrUrl": "File or url:",
"LabelFinish": "Finish",
"LabelFont": "Font:",
@ -677,7 +674,7 @@
"LabelKodiMetadataSaveImagePaths": "Save image paths within nfo files",
"LabelKodiMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Kodi guidelines.",
"LabelKodiMetadataUser": "Save user watch data to nfo's for:",
"LabelKodiMetadataUserHelp": "Enable this to save watch data to Nfo files for other applications to utilize.",
"LabelKodiMetadataUserHelp": "Enable this to save watch data to NFO files for other applications to utilize.",
"LabelLanNetworks": "LAN networks:",
"LabelLanguage": "Language:",
"LabelLineup": "Lineup:",
@ -693,11 +690,11 @@
"LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:",
"LabelMaxChromecastBitrate": "Chromecast streaming quality:",
"LabelMaxParentalRating": "Maximum allowed parental rating:",
"LabelMaxResumePercentage": "Max resume percentage:",
"LabelMaxResumePercentage": "Maximum resume percentage:",
"LabelMaxResumePercentageHelp": "Titles are assumed fully played if stopped after this time",
"LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:",
"LabelMaxStreamingBitrate": "Max streaming quality:",
"LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.",
"LabelMaxStreamingBitrate": "Maximum streaming quality:",
"LabelMaxStreamingBitrateHelp": "Specify a maximum bitrate when streaming.",
"LabelMessageText": "Message text:",
"LabelMessageTitle": "Message title:",
"LabelMetadata": "Metadata:",
@ -711,9 +708,9 @@
"LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
"LabelMethod": "Method:",
"LabelMinBackdropDownloadWidth": "Minimum backdrop download width:",
"LabelMinResumeDuration": "Min resume duration (seconds):",
"LabelMinResumeDurationHelp": "Titles shorter than this will not be resumable",
"LabelMinResumePercentage": "Min resume percentage:",
"LabelMinResumeDuration": "Minimum resume duration:",
"LabelMinResumeDurationHelp": "The shortest video length in seconds that will save playback location and let you resume",
"LabelMinResumePercentage": "Minimum resume percentage:",
"LabelMinResumePercentageHelp": "Titles are assumed unplayed if stopped before this time",
"LabelMinScreenshotDownloadWidth": "Minimum screenshot download width:",
"LabelModelDescription": "Model description",
@ -965,7 +962,7 @@
"MessageItemsAdded": "Items added.",
"MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
"MessageNoAvailablePlugins": "No available plugins.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, and albums Albums. Click the + button to start creating collections.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, and Albums. Click the + button to start creating collections.",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoPluginsInstalled": "You have no plugins installed.",
"MessageNoServersAvailable": "No servers have been found using the automatic server discovery.",
@ -997,6 +994,9 @@
"MoveRight": "Move right",
"MovieLibraryHelp": "Review the {0}Jellyfin movie naming guide{1}.",
"Movies": "Movies",
"MusicAlbum": "Music Album",
"MusicArtist": "Music Artist",
"MusicVideo": "Music Video",
"Mute": "Mute",
"MySubtitles": "My Subtitles",
"Name": "Name",
@ -1310,6 +1310,7 @@
"SubtitleAppearanceSettingsAlsoPassedToCastDevices": "These settings also apply to any Chromecast playback started by this device.",
"SubtitleAppearanceSettingsDisclaimer": "These settings will not apply to graphical subtitles (PGS, DVD, etc), or subtitles that have their own styles embedded (ASS/SSA).",
"SubtitleDownloadersHelp": "Enable and rank your preferred subtitle downloaders in order of priority.",
"SubtitleOffset": "Subtitle Offset",
"Subtitles": "Subtitles",
"Suggestions": "Suggestions",
"Sunday": "Sunday",
@ -1331,11 +1332,9 @@
"TabDirectPlay": "Direct Play",
"TabDisplay": "Display",
"TabEpisodes": "Episodes",
"TabExpert": "Expert",
"TabFavorites": "Favorites",
"TabGenres": "Genres",
"TabGuide": "Guide",
"TabHosting": "Hosting",
"TabInfo": "Info",
"TabLatest": "Latest",
"TabLibrary": "Library",
@ -1347,7 +1346,8 @@
"TabMusicVideos": "Music Videos",
"TabMyPlugins": "My Plugins",
"TabNetworks": "Networks",
"TabNfoSettings": "Nfo Settings",
"TabNetworking": "Networking",
"TabNfoSettings": "NFO Settings",
"TabNotifications": "Notifications",
"TabOther": "Other",
"TabParentalControl": "Parental Control",
@ -1360,9 +1360,8 @@
"TabProfiles": "Profiles",
"TabRecordings": "Recordings",
"TabResponses": "Responses",
"TabResumeSettings": "Resume Settings",
"TabResumeSettings": "Resume",
"TabScheduledTasks": "Scheduled Tasks",
"TabSecurity": "Security",
"TabSeries": "Series",
"TabServer": "Server",
"TabSettings": "Settings",

View file

@ -56,7 +56,6 @@
"AddToPlaylist": "Añadir a la lista de reproducción",
"AddedOnValue": "Añadidos {0}",
"AdditionalNotificationServices": "Navegue el catálogo de plugins para instalar servicios de notificación adicionales.",
"Advanced": "Avanzado",
"AirDate": "Fecha de emisión",
"Aired": "Emitido",
"Alerts": "Alertas",

View file

@ -9,7 +9,6 @@
"AddToPlaylist": "Agregar a lista de reproducción",
"AddedOnValue": "Agregado {0}",
"AdditionalNotificationServices": "Explore el catálogo de complementos para instalar servicios de notificación adicionales.",
"Advanced": "Avanzado",
"AirDate": "Fecha de emisión",
"Aired": "Transmitido",
"Albums": "Álbumes",
@ -289,8 +288,8 @@
"HeaderAlbums": "Álbumes",
"HeaderAlert": "Alerta",
"HeaderAllowMediaDeletionFrom": "Permitir Eliminacion de Medios De",
"HeaderApiKey": "Llave de API",
"HeaderApiKeys": "Llaves de API",
"HeaderApiKey": "Clave API",
"HeaderApiKeys": "Claves de API",
"HeaderApiKeysHelp": "Son necesarias aplicaciones externas para obtener una clave Api para comunicarse con el Servidor Jellyfin. Las clave son emitidas accediendo con una cuenta Jellyfin, u obteniendo manualmente la clave de la aplicación.",
"HeaderAppearsOn": "Aparece En",
"HeaderAudioBooks": "Audio Libros",
@ -301,7 +300,7 @@
"HeaderBranding": "Establecer Marca",
"HeaderCancelRecording": "Cancelar Grabación",
"HeaderCancelSeries": "Cancelar Serie",
"HeaderCastAndCrew": "Reparto & Personal:",
"HeaderCastAndCrew": "Reparto & Personal",
"HeaderCastCrew": "Reparto y Personal",
"HeaderChannelAccess": "Acceso a los Canales",
"HeaderChannels": "Canales",
@ -389,7 +388,7 @@
"HeaderMyDevice": "Mi Dispositivo",
"HeaderMyMedia": "Mis Medios",
"HeaderMyMediaSmall": "Mis medios (pequeño)",
"HeaderNewApiKey": "Nueva llave de API",
"HeaderNewApiKey": "Nueva clave API",
"HeaderNewDevices": "Nuevos Dispositivos",
"HeaderNextEpisodePlayingInValue": "El Siguiente Episodio se Reproducirá en {0}",
"HeaderNextUp": "A Continuación",
@ -421,7 +420,7 @@
"HeaderRemoteControl": "Control Remoto",
"HeaderRemoveMediaFolder": "Eliminar Carpteta de Medios",
"HeaderRemoveMediaLocation": "Eliminar Ubicación de Medios",
"HeaderResponseProfile": "Perfil de Respuesta:",
"HeaderResponseProfile": "Perfil de Respuesta",
"HeaderResponseProfileHelp": "Los perfiles de respuesta proporcionan un medio para personalizar la información enviada a un dispositivo cuando se reproducen ciertos tipos de medios.",
"HeaderRestart": "Reiniciar",
"HeaderRevisionHistory": "Historial de Versiones",
@ -440,7 +439,7 @@
"HeaderSelectTranscodingPath": "Seleccionar Ruta para Transcodificación Temporal",
"HeaderSelectTranscodingPathHelp": "Explore o introduzca la ruta a utilizar para los archivos temporales de transcodificación. La carpeta debe tener permisos de escritura.",
"HeaderSendMessage": "Enviar Mensaje",
"HeaderSeries": "Series:",
"HeaderSeries": "Series",
"HeaderSeriesOptions": "Opciones de Serie",
"HeaderSeriesStatus": "Estado de la Serie",
"HeaderServerSettings": "Configuración del Servidor",
@ -508,7 +507,7 @@
"LabelAirsAfterSeason": "Transmisión después de la temporada:",
"LabelAirsBeforeEpisode": "Transmisión antes del episodio:",
"LabelAirsBeforeSeason": "Transmisión antes de la temporada:",
"LabelAlbum": "Álbum",
"LabelAlbum": "Álbum:",
"LabelAlbumArtHelp": "PN usado para arte del álbum, dentro del atributo dlna:profileID en upnp:albumArtURI. Algunos dispositivos requieren valores específicos, independientemente del tamaño de la imagen.",
"LabelAlbumArtMaxHeight": "Altura máxima para arte del álbum:",
"LabelAlbumArtMaxHeightHelp": "Máxima resolución para arte del album expuesta via upnp:albumArtURI.",
@ -610,8 +609,6 @@
"LabelExtractChaptersDuringLibraryScan": "Extraer imágenes de capítulos durante la exploración de la biblioteca",
"LabelExtractChaptersDuringLibraryScanHelp": "Si se activa, las imágenes de capítulos serán extraídas cuando los videos sean importados durante la exploración de la biblioteca. Si se deshabilita, serán extraídas durante la ejecución de la tarea programada de extracción de imágenes de capítulos, permitiéndo que la exploración normal de la biblioteca se complete más rápidamente.",
"LabelFailed": "Fallido",
"LabelFanartApiKey": "Clave api personal:",
"LabelFanartApiKeyHelp": "Solicitar fanart sin una clave API personal muestra los imagenes que fueron aprobadas hace 7 días. Con una clave API personal se reduce a 48 horas y si eres miembro VIP de fanart será alrededor de 10 minutos.",
"LabelFileOrUrl": "Archivo o url:",
"LabelFinish": "Terminar",
"LabelFont": "Fuente:",
@ -661,8 +658,8 @@
"LabelLoginDisclaimer": "Aviso legal:",
"LabelLoginDisclaimerHelp": "Esto se mostrara al final de la pagina de inicio de sesión.",
"LabelLogs": "Bitácoras:",
"LabelManufacturer": "Fabricante:",
"LabelManufacturerUrl": "URL del fabricante:",
"LabelManufacturer": "Fabricante",
"LabelManufacturerUrl": "URL del fabricante",
"LabelMatchType": "Tipo de Coincidencia:",
"LabelMaxBackdropsPerItem": "Número máximo de imágenes de fondo por ítem:",
"LabelMaxChromecastBitrate": "Tasa maxima de bits para El Chromecast:",
@ -690,10 +687,10 @@
"LabelMinResumePercentage": "Porcentaje mínimo para continuar:",
"LabelMinResumePercentageHelp": "Se asumirá que los títulos no han sido reproducidos si se detienen antes de este momento",
"LabelMinScreenshotDownloadWidth": "Anchura mínima de descarga de capturas de pantalla:",
"LabelModelDescription": "Descripción del modelo:",
"LabelModelName": "Nombre del modelo:",
"LabelModelNumber": "Número del modelo:",
"LabelModelUrl": "URL del modelo:",
"LabelModelDescription": "Descripción del modelo",
"LabelModelName": "Nombre del modelo",
"LabelModelNumber": "Número del modelo",
"LabelModelUrl": "URL del modelo",
"LabelMonitorUsers": "Monitorear actividad desde:",
"LabelMovieCategories": "Categorías de películas:",
"LabelMoviePrefix": "Prefijo de la película:",
@ -709,7 +706,7 @@
"LabelNext": "Siguiente",
"LabelNotificationEnabled": "Habilitar esta notificación",
"LabelNumber": "Número:",
"LabelNumberOfGuideDays": "Número de días de datos de la programación a descargar",
"LabelNumberOfGuideDays": "Número de días de datos de la programación a descargar:",
"LabelNumberOfGuideDaysHelp": "Descargar más días de datos de programación permite programar con mayor anticipación y ver más listados, pero tomará más tiempo en descargar. Auto hará la selección basada en el número de canales.",
"LabelOptionalNetworkPath": "(Opcional) Carpeta de red compartida:",
"LabelOptionalNetworkPathHelp": "Si esta carpeta es compartida en su red, proveer la ruta del recurso compartido de red puede permitir a las aplicaciones Jellyfin en otros dispositivos acceder a los archivos de medios directamente.",
@ -767,7 +764,7 @@
"LabelSelectUsers": "Seleccionar Usuarios:",
"LabelSelectVersionToInstall": "Seleccionar versión a instalar:",
"LabelSendNotificationToUsers": "Enviar la notificación a:",
"LabelSerialNumber": "Número de serie:",
"LabelSerialNumber": "Número de serie",
"LabelSeriesRecordingPath": "Ruta para grabaciones de Series (Opcional):",
"LabelServerHost": "Servidor:",
"LabelServerHostHelp": "192.168.1.100 O https://miservidor.com",
@ -800,7 +797,7 @@
"LabelSupportedMediaTypes": "Tipos de Medios Soportados:",
"LabelTVHomeScreen": "Modo de pantalla de TV:",
"LabelTag": "Etiqueta:",
"LabelTagline": "Eslogan",
"LabelTagline": "Eslogan:",
"LabelTextBackgroundColor": "Color de fondo para el texto:",
"LabelTextColor": "Color de texto:",
"LabelTextSize": "Tamaño de texto:",
@ -846,7 +843,7 @@
"LabelffmpegPathHelp": "La ruta hacia el archivo de aplicación de ffmpeg, o la carpeta que contenga ffmpeg.",
"LanNetworksHelp": "Lista separada por comas de direcciones IP/mascaras de subred para las redes que serán consideradas como locales al enforzar restricciones de ancho de banda. Si se establece, todas las demás direcciones IP serán consideradas como redes externas y estarán sujetas a restricciones de ancho de banda. Si se deja en blanco, sólo la subred del servidor será considerada como red local.",
"Large": "Grande",
"LatestFromLibrary": "Más recientes {0}",
"LatestFromLibrary": "Más recientes - {0}",
"LearnHowYouCanContribute": "Aprenda como puede contribuír.",
"LibraryAccessHelp": "Seleccione las carpetas de medios para compartir con este usuario. Los administradores podrán editar todas las carpetas usando el administrador de metadatos.",
"Like": "Me gusta",
@ -920,7 +917,7 @@
"MessageNoPluginsInstalled": "No tienes extensiones instaladas.",
"MessageNoTrailersFound": "No se encontraron tráilers. Instale el canal de tráilers para mejorar su experiencia con películas al agregar una biblioteca de tráilers desde el Internet.",
"MessageNothingHere": "Nada aquí.",
"MessagePasswordResetForUsers": "Las contraseñas han sido eliminadas para los siguientes usuarios. Para acceder, inicie sesión con la contraseña en blanco.",
"MessagePasswordResetForUsers": "Los siguientes usuarios han restablecido sus contraseñas. Ahora pueden iniciar sesión con los códigos PIN que se usaron para realizar el restablecimiento.",
"MessagePlayAccessRestricted": "La reproducción de este contenido se encuentra restringida actualmente. Por favor contacte a su administrador del Servidor Jellyfin para mas información.",
"MessagePleaseEnsureInternetMetadata": "Por favor asegúrese que la descarga de metadatos de internet esta habilitada.",
"MessagePleaseWait": "Espere por favor. Esto podría tomar un minuto.",
@ -1038,7 +1035,7 @@
"OptionEnableExternalContentInSuggestions": "Habilitar contenido externo en las sugerencias",
"OptionEnableExternalContentInSuggestionsHelp": "Permitir que los trailers de Internet y programas de tv en vivo sean incluidos dentro del contenido sugerido.",
"OptionEnableForAllTuners": "Habilitar para todos los dispositivos sintonizadores",
"OptionEnableM2tsMode": "Habilitar modo M2ts:",
"OptionEnableM2tsMode": "Habilitar modo M2ts",
"OptionEnableM2tsModeHelp": "Habilita el modo m2ts cuando se codifican mpegs.",
"OptionEnded": "Finalizado",
"OptionEquals": "Igual a",
@ -1255,11 +1252,9 @@
"TabDirectPlay": "Reproducción Directa",
"TabDisplay": "Pantalla",
"TabEpisodes": "Episodios",
"TabExpert": "Experto",
"TabFavorites": "Favoritos",
"TabGenres": "Géneros",
"TabGuide": "Guía",
"TabHosting": "Hospedaje",
"TabLatest": "Recientes",
"TabLibrary": "Biblioteca",
"TabLiveTV": "TV en Vivo",
@ -1285,7 +1280,6 @@
"TabResponses": "Respuestas",
"TabResumeSettings": "Configuración para Continuar",
"TabScheduledTasks": "Tareas Programadas",
"TabSecurity": "Seguridad",
"TabServer": "Servidor",
"TabSettings": "Configuración",
"TabShows": "Programas",
@ -1368,5 +1362,89 @@
"ButtonInfo": "Info",
"ButtonNo": "No",
"ButtonOk": "Ok",
"ButtonTrailer": "Trailer"
"ButtonTrailer": "Trailer",
"AuthProviderHelp": "Seleccione un proveedor de autenticación que se utilizará para autenticar la contraseña de este usuario",
"Director": "Director",
"DirectorValue": "Director: {0}",
"Extras": "Extras",
"General": "General",
"HeaderAdmin": "Administrador",
"HeaderApp": "App",
"HeaderAudioLanguages": "Idiomas de audio",
"HeaderError": "Error",
"HeaderFavoriteMovies": "Peliculas favoritas",
"HeaderFavoriteShows": "Programas favoritos",
"HeaderFavoriteEpisodes": "Episodios favoritos",
"HeaderFavoriteAlbums": "Álbumes favoritos",
"HeaderFavoriteArtists": "Artistas favoritos",
"HeaderFavoriteSongs": "Canciones favoritas",
"HeaderFavoriteVideos": "Videos favoritos",
"HeaderHome": "Inicio",
"HeaderHomeSettings": "Configuraciones de Inicio",
"HeaderRestartingServer": "Reiniciando servidor",
"HeaderVideos": "Videos",
"Horizontal": "Horizontal",
"LabelAudio": "Audio:",
"LabelAuthProvider": "Proveedor de autenticación:",
"LabelDynamicExternalId": "{0} Id:",
"LabelPasswordResetProvider": "Proveedor de restablecimiento de contraseña:",
"LabelProfileCodecs": "Codecs:",
"LabelServerName": "Nombre del servidor:",
"LabelTranscodePath": "Ruta de transcodificación:",
"LabelTranscodes": "Transcodificaciones:",
"LabelUserLoginAttemptsBeforeLockout": "Intentos fallidos de inicio de sesión antes de que el usuario se bloquee:",
"DashboardVersionNumber": "Versión: {0}",
"DashboardServerName": "Servidor: {0}",
"DashboardOperatingSystem": "Sistema operativo: {0}",
"DashboardArchitecture": "Arquitectura: {0}",
"LabelVideo": "Video:",
"LabelWeb": "Web: ",
"LaunchWebAppOnStartup": "Iniciar la aplicación web Jellyfin en mi navegador web cuando se inicie Jellyfin Server",
"LaunchWebAppOnStartupHelp": "Esto abrirá la aplicación web en su navegador web predeterminado cuando Jellyfin Server se inicie inicialmente. Esto no ocurrirá cuando se utiliza la función de reinicio del servidor.",
"LeaveBlankToNotSetAPassword": "Opcional - Dejar en blanco para no establecer una contraseña",
"MediaInfoCodec": "Codec",
"MediaInfoSoftware": "Software",
"MediaInfoStreamTypeAudio": "Audio",
"MediaInfoStreamTypeData": "Dato",
"MediaInfoStreamTypeEmbeddedImage": "Imagen incrustada",
"MediaInfoStreamTypeSubtitle": "Subtitulo",
"MediaInfoStreamTypeVideo": "Video",
"MessageImageFileTypeAllowed": "Solo se admite archivos JPEG y PNG.",
"MessageImageTypeNotSelected": "Seleccione un tipo de imagen en el menú desplegable.",
"MessageNoCollectionsAvailable": "Las colecciones le permiten disfrutar de agrupaciones personalizadas de películas, series y álbumes. Haga clic en el botón + para comenzar a crear colecciones.",
"MessageNoServersAvailable": "No se encontraron servidores utilizando el descubrimiento automático del servidor.",
"MusicAlbum": "Álbum de música",
"MusicArtist": "Artista musical",
"MusicVideo": "Video musical",
"No": "No",
"Normal": "Normal",
"Option3D": "3D",
"OptionBanner": "Banner",
"OptionBluray": "Bluray",
"OptionCaptionInfoExSamsung": "CaptionInfoEx (Samsung)",
"OptionDownloadLogoImage": "Logo",
"OptionIsHD": "HD",
"OptionIsSD": "SD",
"OptionList": "Lista",
"OptionLoginAttemptsBeforeLockout": "Determina cuántos intentos de inicio de sesión incorrectos se pueden hacer antes de que ocurra el bloqueo.",
"OptionLoginAttemptsBeforeLockoutHelp": "0 significa heredar el valor predeterminado de 3 para no administrador y 5 para administrador, -1 deshabilita el bloqueo",
"OptionPoster": "Póster",
"OptionPosterCard": "Ficha de póster",
"OptionProfileAudio": "Audio",
"OptionProfileVideo": "Video",
"OptionProtocolHttp": "HTTP",
"OptionRegex": "Expresión regular",
"PasswordResetProviderHelp": "Elija un proveedor de restablecimiento de contraseña para usar cuando este usuario solicite un restablecimiento de contraseña",
"PlaybackData": "Datos de reproducción",
"Series": "Series",
"SubtitleOffset": "Desplazamiento de subtítulos",
"TV": "TV",
"TabCodecs": "Codecs",
"TabInfo": "Información",
"TabSeries": "Series",
"ValueMinutes": "{0} min",
"ValueSeriesCount": "{0} series",
"Vertical": "Vertical",
"OptionThumb": "Miniatura",
"OptionThumbCard": "Pequeña miniatura"
}

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more