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

Merge branch 'master' into config

This commit is contained in:
dkanada 2020-04-02 19:46:31 +09:00 committed by GitHub
commit 20391c52e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 473 additions and 217 deletions

View file

@ -78,12 +78,15 @@
"overrides": [ "overrides": [
{ {
"test": [ "test": [
"src/components/autoFocuser.js",
"src/components/cardbuilder/cardBuilder.js", "src/components/cardbuilder/cardBuilder.js",
"src/components/dom.js",
"src/components/filedownloader.js", "src/components/filedownloader.js",
"src/components/filesystem.js", "src/components/filesystem.js",
"src/components/input/keyboardnavigation.js", "src/components/input/keyboardnavigation.js",
"src/components/sanatizefilename.js", "src/components/sanatizefilename.js",
"src/scripts/settings/webSettings.js" "src/scripts/settings/webSettings.js",
"src/components/scrollManager.js"
], ],
"plugins": [ "plugins": [
"@babel/plugin-transform-modules-amd" "@babel/plugin-transform-modules-amd"

View file

@ -1,22 +1,29 @@
define(["focusManager", "layoutManager"], function (focusManager, layoutManager) { /* eslint-disable indent */
"use strict";
/**
* Module for performing auto-focus.
* @module components/autoFocuser
*/
import focusManager from "focusManager";
import layoutManager from "layoutManager";
/** /**
* Previously selected element. * Previously selected element.
*/ */
var activeElement; let activeElement;
/** /**
* Returns true if AutoFocuser is enabled. * Returns _true_ if AutoFocuser is enabled.
*/ */
function isEnabled() { export function isEnabled() {
return layoutManager.tv; return layoutManager.tv;
} }
/** /**
* Start AutoFocuser * Start AutoFocuser.
*/ */
function enable() { export function enable() {
if (!isEnabled()) { if (!isEnabled()) {
return; return;
} }
@ -28,24 +35,19 @@ define(["focusManager", "layoutManager"], function (focusManager, layoutManager)
console.debug("AutoFocuser enabled"); console.debug("AutoFocuser enabled");
} }
/**
* Create an array from some source.
*/
var arrayFrom = Array.prototype.from || function (src) {
return Array.prototype.slice.call(src);
}
/** /**
* Set focus on a suitable element, taking into account the previously selected. * Set focus on a suitable element, taking into account the previously selected.
* @param {HTMLElement} [container] - Element to limit scope.
* @returns {HTMLElement} Focused element.
*/ */
function autoFocus(container) { export function autoFocus(container) {
if (!isEnabled()) { if (!isEnabled()) {
return; return null;
} }
container = container || document.body; container = container || document.body;
var candidates = []; let candidates = [];
if (activeElement) { if (activeElement) {
// These elements are recreated // These elements are recreated
@ -62,10 +64,10 @@ define(["focusManager", "layoutManager"], function (focusManager, layoutManager)
candidates.push(activeElement); candidates.push(activeElement);
} }
candidates = candidates.concat(arrayFrom(container.querySelectorAll(".btnResume"))); candidates = candidates.concat(Array.from(container.querySelectorAll(".btnResume")));
candidates = candidates.concat(arrayFrom(container.querySelectorAll(".btnPlay"))); candidates = candidates.concat(Array.from(container.querySelectorAll(".btnPlay")));
var focusedElement; let focusedElement;
candidates.every(function (element) { candidates.every(function (element) {
if (focusManager.isCurrentlyFocusable(element)) { if (focusManager.isCurrentlyFocusable(element)) {
@ -79,7 +81,7 @@ define(["focusManager", "layoutManager"], function (focusManager, layoutManager)
if (!focusedElement) { if (!focusedElement) {
// FIXME: Multiple itemsContainers // FIXME: Multiple itemsContainers
var itemsContainer = container.querySelector(".itemsContainer"); const itemsContainer = container.querySelector(".itemsContainer");
if (itemsContainer) { if (itemsContainer) {
focusedElement = focusManager.autoFocus(itemsContainer); focusedElement = focusManager.autoFocus(itemsContainer);
@ -93,9 +95,8 @@ define(["focusManager", "layoutManager"], function (focusManager, layoutManager)
return focusedElement; return focusedElement;
} }
return { export default {
isEnabled: isEnabled, isEnabled: isEnabled,
enable: enable, enable: enable,
autoFocus: autoFocus autoFocus: autoFocus
}; };
});

View file

@ -1853,3 +1853,14 @@ import 'programStyles';
cell.removeAttribute('data-seriestimerid'); cell.removeAttribute('data-seriestimerid');
} }
} }
export default {
getCardsHtml: getCardsHtml,
getDefaultBackgroundClass: getDefaultBackgroundClass,
getDefaultText: getDefaultText,
buildCards: buildCards,
onUserDataChanged: onUserDataChanged,
onTimerCreated: onTimerCreated,
onTimerCancelled: onTimerCancelled,
onSeriesTimerCancelled: onSeriesTimerCancelled
};

View file

@ -1,8 +1,18 @@
define([], function () { /* eslint-disable indent */
'use strict';
function parentWithAttribute(elem, name, value) { /**
* Useful DOM utilities.
* @module components/dom
*/
/**
* Returns parent of element with specified attribute value.
* @param {HTMLElement} elem - Element whose parent need to find.
* @param {string} name - Attribute name.
* @param {mixed} value - Attribute value.
* @returns {HTMLElement} Parent with specified attribute value.
*/
export function parentWithAttribute(elem, name, value) {
while ((value ? elem.getAttribute(name) !== value : !elem.getAttribute(name))) { while ((value ? elem.getAttribute(name) !== value : !elem.getAttribute(name))) {
elem = elem.parentNode; elem = elem.parentNode;
@ -14,8 +24,13 @@ define([], function () {
return elem; return elem;
} }
function parentWithTag(elem, tagNames) { /**
* Returns parent of element with one of specified tag names.
* @param {HTMLElement} elem - Element whose parent need to find.
* @param {(string|Array)} tagNames - Tag name or array of tag names.
* @returns {HTMLElement} Parent with one of specified tag names.
*/
export function parentWithTag(elem, tagNames) {
// accept both string and array passed in // accept both string and array passed in
if (!Array.isArray(tagNames)) { if (!Array.isArray(tagNames)) {
tagNames = [tagNames]; tagNames = [tagNames];
@ -32,9 +47,14 @@ define([], function () {
return elem; return elem;
} }
/**
* Returns _true_ if class list contains one of specified names.
* @param {DOMTokenList} classList - Class list.
* @param {Array} classNames - Array of class names.
* @returns {boolean} _true_ if class list contains one of specified names.
*/
function containsAnyClass(classList, classNames) { function containsAnyClass(classList, classNames) {
for (let i = 0, length = classNames.length; i < length; i++) {
for (var i = 0, length = classNames.length; i < length; i++) {
if (classList.contains(classNames[i])) { if (classList.contains(classNames[i])) {
return true; return true;
} }
@ -42,8 +62,13 @@ define([], function () {
return false; return false;
} }
function parentWithClass(elem, classNames) { /**
* Returns parent of element with one of specified class names.
* @param {HTMLElement} elem - Element whose parent need to find.
* @param {(string|Array)} classNames - Class name or array of class names.
* @returns {HTMLElement} Parent with one of specified class names.
*/
export function parentWithClass(elem, classNames) {
// accept both string and array passed in // accept both string and array passed in
if (!Array.isArray(classNames)) { if (!Array.isArray(classNames)) {
classNames = [classNames]; classNames = [classNames];
@ -60,9 +85,9 @@ define([], function () {
return elem; return elem;
} }
var supportsCaptureOption = false; let supportsCaptureOption = false;
try { try {
var opts = Object.defineProperty({}, 'capture', { const opts = Object.defineProperty({}, 'capture', {
// eslint-disable-next-line getter-return // eslint-disable-next-line getter-return
get: function () { get: function () {
supportsCaptureOption = true; supportsCaptureOption = true;
@ -73,29 +98,58 @@ define([], function () {
console.debug('error checking capture support'); console.debug('error checking capture support');
} }
function addEventListenerWithOptions(target, type, handler, options) { /**
var optionsOrCapture = options || {}; * Adds event listener to specified target.
* @param {EventTarget} target - Event target.
* @param {string} type - Event type.
* @param {function} handler - Event handler.
* @param {Object} [options] - Listener options.
*/
export function addEventListener(target, type, handler, options) {
let optionsOrCapture = options || {};
if (!supportsCaptureOption) { if (!supportsCaptureOption) {
optionsOrCapture = optionsOrCapture.capture; optionsOrCapture = optionsOrCapture.capture;
} }
target.addEventListener(type, handler, optionsOrCapture); target.addEventListener(type, handler, optionsOrCapture);
} }
function removeEventListenerWithOptions(target, type, handler, options) { /**
var optionsOrCapture = options || {}; * Removes event listener from specified target.
* @param {EventTarget} target - Event target.
* @param {string} type - Event type.
* @param {function} handler - Event handler.
* @param {Object} [options] - Listener options.
*/
export function removeEventListener(target, type, handler, options) {
let optionsOrCapture = options || {};
if (!supportsCaptureOption) { if (!supportsCaptureOption) {
optionsOrCapture = optionsOrCapture.capture; optionsOrCapture = optionsOrCapture.capture;
} }
target.removeEventListener(type, handler, optionsOrCapture); target.removeEventListener(type, handler, optionsOrCapture);
} }
var windowSize; /**
var windowSizeEventsBound; * Cached window size.
*/
let windowSize;
/**
* Flag of event listener bound.
*/
let windowSizeEventsBound;
/**
* Resets cached window size.
*/
function clearWindowSize() { function clearWindowSize() {
windowSize = null; windowSize = null;
} }
function getWindowSize() { /**
* Returns window size.
* @returns {Object} Window size.
*/
export function getWindowSize() {
if (!windowSize) { if (!windowSize) {
windowSize = { windowSize = {
innerHeight: window.innerHeight, innerHeight: window.innerHeight,
@ -104,46 +158,60 @@ define([], function () {
if (!windowSizeEventsBound) { if (!windowSizeEventsBound) {
windowSizeEventsBound = true; windowSizeEventsBound = true;
addEventListenerWithOptions(window, "orientationchange", clearWindowSize, { passive: true }); addEventListener(window, "orientationchange", clearWindowSize, { passive: true });
addEventListenerWithOptions(window, 'resize', clearWindowSize, { passive: true }); addEventListener(window, 'resize', clearWindowSize, { passive: true });
} }
} }
return windowSize; return windowSize;
} }
var standardWidths = [480, 720, 1280, 1440, 1920, 2560, 3840, 5120, 7680]; /**
function getScreenWidth() { * Standard screen widths.
var width = window.innerWidth; */
var height = window.innerHeight; const standardWidths = [480, 720, 1280, 1440, 1920, 2560, 3840, 5120, 7680];
/**
* Returns screen width.
* @returns {number} Screen width.
*/
export function getScreenWidth() {
let width = window.innerWidth;
const height = window.innerHeight;
if (height > width) { if (height > width) {
width = height * (16.0 / 9.0); width = height * (16.0 / 9.0);
} }
var closest = standardWidths.sort(function (a, b) { const closest = standardWidths.sort(function (a, b) {
return Math.abs(width - a) - Math.abs(width - b); return Math.abs(width - a) - Math.abs(width - b);
})[0]; })[0];
return closest; return closest;
} }
var _animationEvent; /**
function whichAnimationEvent() { * Name of animation end event.
*/
let _animationEvent;
/**
* Returns name of animation end event.
* @returns {string} Name of animation end event.
*/
export function whichAnimationEvent() {
if (_animationEvent) { if (_animationEvent) {
return _animationEvent; return _animationEvent;
} }
var t; const el = document.createElement("div");
var el = document.createElement("div"); const animations = {
var animations = {
"animation": "animationend", "animation": "animationend",
"OAnimation": "oAnimationEnd", "OAnimation": "oAnimationEnd",
"MozAnimation": "animationend", "MozAnimation": "animationend",
"WebkitAnimation": "webkitAnimationEnd" "WebkitAnimation": "webkitAnimationEnd"
}; };
for (t in animations) { for (let t in animations) {
if (el.style[t] !== undefined) { if (el.style[t] !== undefined) {
_animationEvent = animations[t]; _animationEvent = animations[t];
return animations[t]; return animations[t];
@ -154,26 +222,36 @@ define([], function () {
return _animationEvent; return _animationEvent;
} }
function whichAnimationCancelEvent() { /**
* Returns name of animation cancel event.
* @returns {string} Name of animation cancel event.
*/
export function whichAnimationCancelEvent() {
return whichAnimationEvent().replace('animationend', 'animationcancel').replace('AnimationEnd', 'AnimationCancel'); return whichAnimationEvent().replace('animationend', 'animationcancel').replace('AnimationEnd', 'AnimationCancel');
} }
var _transitionEvent; /**
function whichTransitionEvent() { * Name of transition end event.
*/
let _transitionEvent;
/**
* Returns name of transition end event.
* @returns {string} Name of transition end event.
*/
export function whichTransitionEvent() {
if (_transitionEvent) { if (_transitionEvent) {
return _transitionEvent; return _transitionEvent;
} }
var t; const el = document.createElement("div");
var el = document.createElement("div"); const transitions = {
var transitions = {
"transition": "transitionend", "transition": "transitionend",
"OTransition": "oTransitionEnd", "OTransition": "oTransitionEnd",
"MozTransition": "transitionend", "MozTransition": "transitionend",
"WebkitTransition": "webkitTransitionEnd" "WebkitTransition": "webkitTransitionEnd"
}; };
for (t in transitions) { for (let t in transitions) {
if (el.style[t] !== undefined) { if (el.style[t] !== undefined) {
_transitionEvent = transitions[t]; _transitionEvent = transitions[t];
return transitions[t]; return transitions[t];
@ -184,16 +262,15 @@ define([], function () {
return _transitionEvent; return _transitionEvent;
} }
return { export default {
parentWithAttribute: parentWithAttribute, parentWithAttribute: parentWithAttribute,
parentWithClass: parentWithClass, parentWithClass: parentWithClass,
parentWithTag: parentWithTag, parentWithTag: parentWithTag,
addEventListener: addEventListenerWithOptions, addEventListener: addEventListener,
removeEventListener: removeEventListenerWithOptions, removeEventListener: removeEventListener,
getWindowSize: getWindowSize, getWindowSize: getWindowSize,
getScreenWidth: getScreenWidth, getScreenWidth: getScreenWidth,
whichTransitionEvent: whichTransitionEvent, whichTransitionEvent: whichTransitionEvent,
whichAnimationEvent: whichAnimationEvent, whichAnimationEvent: whichAnimationEvent,
whichAnimationCancelEvent: whichAnimationCancelEvent whichAnimationCancelEvent: whichAnimationCancelEvent
}; };
});

View file

@ -1,3 +1,8 @@
/**
* Module for performing keyboard navigation.
* @module components/input/keyboardnavigation
*/
import inputManager from "inputManager"; import inputManager from "inputManager";
import layoutManager from "layoutManager"; import layoutManager from "layoutManager";
@ -55,8 +60,8 @@ if (!hasFieldKey) {
/** /**
* Returns key name from event. * Returns key name from event.
* *
* @param {KeyboardEvent} event keyboard event * @param {KeyboardEvent} event - Keyboard event.
* @return {string} key name * @return {string} Key name.
*/ */
export function getKeyName(event) { export function getKeyName(event) {
return KeyNames[event.keyCode] || event.key; return KeyNames[event.keyCode] || event.key;
@ -65,8 +70,8 @@ export function getKeyName(event) {
/** /**
* Returns _true_ if key is used for navigation. * Returns _true_ if key is used for navigation.
* *
* @param {string} key name * @param {string} key - Key name.
* @return {boolean} _true_ if key is used for navigation * @return {boolean} _true_ if key is used for navigation.
*/ */
export function isNavigationKey(key) { export function isNavigationKey(key) {
return NavigationKeys.indexOf(key) != -1; return NavigationKeys.indexOf(key) != -1;
@ -155,3 +160,9 @@ function attachGamepadScript(e) {
// No need to check for gamepads manually at load time, the eventhandler will be fired for that // No need to check for gamepads manually at load time, the eventhandler will be fired for that
window.addEventListener("gamepadconnected", attachGamepadScript); window.addEventListener("gamepadconnected", attachGamepadScript);
export default {
enable: enable,
getKeyName: getKeyName,
isNavigationKey: isNavigationKey
};

View file

@ -1,38 +1,46 @@
define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManager) { /* eslint-disable indent */
"use strict";
/**
* Module for controlling scroll behavior.
* @module components/scrollManager
*/
import dom from "dom";
import browser from "browser";
import layoutManager from "layoutManager";
/** /**
* Scroll time in ms. * Scroll time in ms.
*/ */
var ScrollTime = 270; const ScrollTime = 270;
/** /**
* Epsilon for comparing values. * Epsilon for comparing values.
*/ */
var Epsilon = 1e-6; const Epsilon = 1e-6;
// FIXME: Need to scroll to top of page to fully show the top menu. This can be solved by some marker of top most elements or their containers // FIXME: Need to scroll to top of page to fully show the top menu. This can be solved by some marker of top most elements or their containers
/** /**
* Returns minimum vertical scroll. * Returns minimum vertical scroll.
* Scroll less than that value will be zeroed. * Scroll less than that value will be zeroed.
* *
* @return {number} minimum vertical scroll * @return {number} Minimum vertical scroll.
*/ */
function minimumScrollY() { function minimumScrollY() {
var topMenu = document.querySelector(".headerTop"); const topMenu = document.querySelector(".headerTop");
if (topMenu) { if (topMenu) {
return topMenu.clientHeight; return topMenu.clientHeight;
} }
return 0; return 0;
} }
var supportsSmoothScroll = "scrollBehavior" in document.documentElement.style; const supportsSmoothScroll = "scrollBehavior" in document.documentElement.style;
var supportsScrollToOptions = false; let supportsScrollToOptions = false;
try { try {
var elem = document.createElement("div"); const elem = document.createElement("div");
var opts = Object.defineProperty({}, "behavior", { const opts = Object.defineProperty({}, "behavior", {
// eslint-disable-next-line getter-return // eslint-disable-next-line getter-return
get: function () { get: function () {
supportsScrollToOptions = true; supportsScrollToOptions = true;
@ -47,10 +55,10 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
/** /**
* Returns value clamped by range [min, max]. * Returns value clamped by range [min, max].
* *
* @param {number} value clamped value * @param {number} value - Clamped value.
* @param {number} min begining of range * @param {number} min - Begining of range.
* @param {number} max ending of range * @param {number} max - Ending of range.
* @return {number} clamped value * @return {number} Clamped value.
*/ */
function clamp(value, min, max) { function clamp(value, min, max) {
return value <= min ? min : value >= max ? max : value; return value <= min ? min : value >= max ? max : value;
@ -60,15 +68,15 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
* Returns the required delta to fit range 1 into range 2. * Returns the required delta to fit range 1 into range 2.
* In case of range 1 is bigger than range 2 returns delta to fit most out of range part. * In case of range 1 is bigger than range 2 returns delta to fit most out of range part.
* *
* @param {number} begin1 begining of range 1 * @param {number} begin1 - Begining of range 1.
* @param {number} end1 ending of range 1 * @param {number} end1 - Ending of range 1.
* @param {number} begin2 begining of range 2 * @param {number} begin2 - Begining of range 2.
* @param {number} end2 ending of range 2 * @param {number} end2 - Ending of range 2.
* @return {number} delta: <0 move range1 to the left, >0 - to the right * @return {number} Delta: <0 move range1 to the left, >0 - to the right.
*/ */
function fitRange(begin1, end1, begin2, end2) { function fitRange(begin1, end1, begin2, end2) {
var delta1 = begin1 - begin2; const delta1 = begin1 - begin2;
var delta2 = end2 - end1; const delta2 = end2 - end1;
if (delta1 < 0 && delta1 < delta2) { if (delta1 < 0 && delta1 < delta2) {
return -delta1; return -delta1;
} else if (delta2 < 0) { } else if (delta2 < 0) {
@ -80,13 +88,21 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
/** /**
* Ease value. * Ease value.
* *
* @param {number} t value in range [0, 1] * @param {number} t - Value in range [0, 1].
* @return {number} eased value in range [0, 1] * @return {number} Eased value in range [0, 1].
*/ */
function ease(t) { function ease(t) {
return t*(2 - t); // easeOutQuad === ease-out return t*(2 - t); // easeOutQuad === ease-out
} }
/**
* @typedef {Object} Rect
* @property {number} left - X coordinate of top-left corner.
* @property {number} top - Y coordinate of top-left corner.
* @property {number} width - Width.
* @property {number} height - Height.
*/
/** /**
* Document scroll wrapper helps to unify scrolling and fix issues of some browsers. * Document scroll wrapper helps to unify scrolling and fix issues of some browsers.
* *
@ -100,41 +116,68 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
* *
* Tizen 5 Browser/Native: scrolls documentElement (and window); has a document.scrollingElement * Tizen 5 Browser/Native: scrolls documentElement (and window); has a document.scrollingElement
*/ */
function DocumentScroller() { class DocumentScroller {
} /**
* Horizontal scroll position.
DocumentScroller.prototype = { * @type {number}
*/
get scrollLeft() { get scrollLeft() {
return window.pageXOffset; return window.pageXOffset;
}, }
set scrollLeft(val) { set scrollLeft(val) {
window.scroll(val, window.pageYOffset); window.scroll(val, window.pageYOffset);
}, }
/**
* Vertical scroll position.
* @type {number}
*/
get scrollTop() { get scrollTop() {
return window.pageYOffset; return window.pageYOffset;
}, }
set scrollTop(val) { set scrollTop(val) {
window.scroll(window.pageXOffset, val); window.scroll(window.pageXOffset, val);
}, }
/**
* Horizontal scroll size (scroll width).
* @type {number}
*/
get scrollWidth() { get scrollWidth() {
return Math.max(document.documentElement.scrollWidth, document.body.scrollWidth); return Math.max(document.documentElement.scrollWidth, document.body.scrollWidth);
}, }
/**
* Vertical scroll size (scroll height).
* @type {number}
*/
get scrollHeight() { get scrollHeight() {
return Math.max(document.documentElement.scrollHeight, document.body.scrollHeight); return Math.max(document.documentElement.scrollHeight, document.body.scrollHeight);
}, }
/**
* Horizontal client size (client width).
* @type {number}
*/
get clientWidth() { get clientWidth() {
return Math.min(document.documentElement.clientWidth, document.body.clientWidth); return Math.min(document.documentElement.clientWidth, document.body.clientWidth);
}, }
/**
* Vertical client size (client height).
* @type {number}
*/
get clientHeight() { get clientHeight() {
return Math.min(document.documentElement.clientHeight, document.body.clientHeight); return Math.min(document.documentElement.clientHeight, document.body.clientHeight);
}, }
getBoundingClientRect: function() { /**
* Returns bounding client rect.
* @return {Rect} Bounding client rect.
*/
getBoundingClientRect() {
// Make valid viewport coordinates: documentElement.getBoundingClientRect returns rect of entire document relative to viewport // Make valid viewport coordinates: documentElement.getBoundingClientRect returns rect of entire document relative to viewport
return { return {
left: 0, left: 0,
@ -142,26 +185,34 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
width: this.clientWidth, width: this.clientWidth,
height: this.clientHeight height: this.clientHeight
}; };
}, }
scrollTo: function() { /**
* Scrolls window.
* @param {...mixed} args See window.scrollTo.
*/
scrollTo() {
window.scrollTo.apply(window, arguments); window.scrollTo.apply(window, arguments);
} }
}; }
var documentScroller = new DocumentScroller();
/** /**
* Returns parent element that can be scrolled. If no such, returns documentElement. * Default (document) scroller.
*/
const documentScroller = new DocumentScroller();
/**
* Returns parent element that can be scrolled. If no such, returns document scroller.
* *
* @param {HTMLElement} element element for which parent is being searched * @param {HTMLElement} element - Element for which parent is being searched.
* @param {boolean} vertical search for vertical scrollable parent * @param {boolean} vertical - Search for vertical scrollable parent.
* @param {HTMLElement|DocumentScroller} Parent element that can be scrolled or document scroller.
*/ */
function getScrollableParent(element, vertical) { function getScrollableParent(element, vertical) {
if (element) { if (element) {
var nameScroll = "scrollWidth"; let nameScroll = "scrollWidth";
var nameClient = "clientWidth"; let nameClient = "clientWidth";
var nameClass = "scrollX"; let nameClass = "scrollX";
if (vertical) { if (vertical) {
nameScroll = "scrollHeight"; nameScroll = "scrollHeight";
@ -169,7 +220,7 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
nameClass = "scrollY"; nameClass = "scrollY";
} }
var parent = element.parentElement; let parent = element.parentElement;
while (parent) { while (parent) {
// Skip 'emby-scroller' because it scrolls by itself // Skip 'emby-scroller' because it scrolls by itself
@ -187,20 +238,20 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
/** /**
* @typedef {Object} ScrollerData * @typedef {Object} ScrollerData
* @property {number} scrollPos current scroll position * @property {number} scrollPos - Current scroll position.
* @property {number} scrollSize scroll size * @property {number} scrollSize - Scroll size.
* @property {number} clientSize client size * @property {number} clientSize - Client size.
*/ */
/** /**
* Returns scroll data for specified orientation. * Returns scroller data for specified orientation.
* *
* @param {HTMLElement} scroller scroller * @param {HTMLElement} scroller - Scroller.
* @param {boolean} vertical vertical scroll data * @param {boolean} vertical - Vertical scroller data.
* @return {ScrollerData} scroll data * @return {ScrollerData} Scroller data.
*/ */
function getScrollerData(scroller, vertical) { function getScrollerData(scroller, vertical) {
var data = {}; let data = {};
if (!vertical) { if (!vertical) {
data.scrollPos = scroller.scrollLeft; data.scrollPos = scroller.scrollLeft;
@ -218,14 +269,14 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
/** /**
* Returns position of child of scroller for specified orientation. * Returns position of child of scroller for specified orientation.
* *
* @param {HTMLElement} scroller scroller * @param {HTMLElement} scroller - Scroller.
* @param {HTMLElement} element child of scroller * @param {HTMLElement} element - Child of scroller.
* @param {boolean} vertical vertical scroll * @param {boolean} vertical - Vertical scroll.
* @return {number} child position * @return {number} Child position.
*/ */
function getScrollerChildPos(scroller, element, vertical) { function getScrollerChildPos(scroller, element, vertical) {
var elementRect = element.getBoundingClientRect(); const elementRect = element.getBoundingClientRect();
var scrollerRect = scroller.getBoundingClientRect(); const scrollerRect = scroller.getBoundingClientRect();
if (!vertical) { if (!vertical) {
return scroller.scrollLeft + elementRect.left - scrollerRect.left; return scroller.scrollLeft + elementRect.left - scrollerRect.left;
@ -237,21 +288,21 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
/** /**
* Returns scroll position for element. * Returns scroll position for element.
* *
* @param {ScrollerData} scrollerData scroller data * @param {ScrollerData} scrollerData - Scroller data.
* @param {number} elementPos child element position * @param {number} elementPos - Child element position.
* @param {number} elementSize child element size * @param {number} elementSize - Child element size.
* @param {boolean} centered scroll to center * @param {boolean} centered - Scroll to center.
* @return {number} scroll position * @return {number} Scroll position.
*/ */
function calcScroll(scrollerData, elementPos, elementSize, centered) { function calcScroll(scrollerData, elementPos, elementSize, centered) {
var maxScroll = scrollerData.scrollSize - scrollerData.clientSize; const maxScroll = scrollerData.scrollSize - scrollerData.clientSize;
var scroll; let scroll;
if (centered) { if (centered) {
scroll = elementPos + (elementSize - scrollerData.clientSize) / 2; scroll = elementPos + (elementSize - scrollerData.clientSize) / 2;
} else { } else {
var delta = fitRange(elementPos, elementPos + elementSize - 1, scrollerData.scrollPos, scrollerData.scrollPos + scrollerData.clientSize - 1); const delta = fitRange(elementPos, elementPos + elementSize - 1, scrollerData.scrollPos, scrollerData.scrollPos + scrollerData.clientSize - 1);
scroll = scrollerData.scrollPos - delta; scroll = scrollerData.scrollPos - delta;
} }
@ -261,14 +312,14 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
/** /**
* Calls scrollTo function in proper way. * Calls scrollTo function in proper way.
* *
* @param {HTMLElement} scroller scroller * @param {HTMLElement} scroller - Scroller.
* @param {ScrollToOptions} options scroll options * @param {ScrollToOptions} options - Scroll options.
*/ */
function scrollToHelper(scroller, options) { function scrollToHelper(scroller, options) {
if ("scrollTo" in scroller) { if ("scrollTo" in scroller) {
if (!supportsScrollToOptions) { if (!supportsScrollToOptions) {
var scrollX = (options.left !== undefined ? options.left : scroller.scrollLeft); const scrollX = (options.left !== undefined ? options.left : scroller.scrollLeft);
var scrollY = (options.top !== undefined ? options.top : scroller.scrollTop); const scrollY = (options.top !== undefined ? options.top : scroller.scrollTop);
scroller.scrollTo(scrollX, scrollY); scroller.scrollTo(scrollX, scrollY);
} else { } else {
scroller.scrollTo(options); scroller.scrollTo(options);
@ -286,14 +337,14 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
/** /**
* Performs built-in scroll. * Performs built-in scroll.
* *
* @param {HTMLElement} xScroller horizontal scroller * @param {HTMLElement} xScroller - Horizontal scroller.
* @param {number} scrollX horizontal coordinate * @param {number} scrollX - Horizontal coordinate.
* @param {HTMLElement} yScroller vertical scroller * @param {HTMLElement} yScroller - Vertical scroller.
* @param {number} scrollY vertical coordinate * @param {number} scrollY - Vertical coordinate.
* @param {boolean} smooth smooth scrolling * @param {boolean} smooth - Smooth scrolling.
*/ */
function builtinScroll(xScroller, scrollX, yScroller, scrollY, smooth) { function builtinScroll(xScroller, scrollX, yScroller, scrollY, smooth) {
var scrollBehavior = smooth ? "smooth" : "instant"; const scrollBehavior = smooth ? "smooth" : "instant";
if (xScroller !== yScroller) { if (xScroller !== yScroller) {
scrollToHelper(xScroller, {left: scrollX, behavior: scrollBehavior}); scrollToHelper(xScroller, {left: scrollX, behavior: scrollBehavior});
@ -303,7 +354,10 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
} }
} }
var scrollTimer; /**
* Requested frame for animated scroll.
*/
let scrollTimer;
/** /**
* Resets scroll timer to stop scrolling. * Resets scroll timer to stop scrolling.
@ -316,29 +370,29 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
/** /**
* Performs animated scroll. * Performs animated scroll.
* *
* @param {HTMLElement} xScroller horizontal scroller * @param {HTMLElement} xScroller - Horizontal scroller.
* @param {number} scrollX horizontal coordinate * @param {number} scrollX - Horizontal coordinate.
* @param {HTMLElement} yScroller vertical scroller * @param {HTMLElement} yScroller - Vertical scroller.
* @param {number} scrollY vertical coordinate * @param {number} scrollY - Vertical coordinate.
*/ */
function animateScroll(xScroller, scrollX, yScroller, scrollY) { function animateScroll(xScroller, scrollX, yScroller, scrollY) {
var ox = xScroller.scrollLeft; const ox = xScroller.scrollLeft;
var oy = yScroller.scrollTop; const oy = yScroller.scrollTop;
var dx = scrollX - ox; const dx = scrollX - ox;
var dy = scrollY - oy; const dy = scrollY - oy;
if (Math.abs(dx) < Epsilon && Math.abs(dy) < Epsilon) { if (Math.abs(dx) < Epsilon && Math.abs(dy) < Epsilon) {
return; return;
} }
var start; let start;
function scrollAnim(currentTimestamp) { function scrollAnim(currentTimestamp) {
start = start || currentTimestamp; start = start || currentTimestamp;
var k = Math.min(1, (currentTimestamp - start) / ScrollTime); let k = Math.min(1, (currentTimestamp - start) / ScrollTime);
if (k === 1) { if (k === 1) {
resetScrollTimer(); resetScrollTimer();
@ -348,8 +402,8 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
k = ease(k); k = ease(k);
var x = ox + dx*k; const x = ox + dx*k;
var y = oy + dy*k; const y = oy + dy*k;
builtinScroll(xScroller, x, yScroller, y, false); builtinScroll(xScroller, x, yScroller, y, false);
@ -362,11 +416,11 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
/** /**
* Performs scroll. * Performs scroll.
* *
* @param {HTMLElement} xScroller horizontal scroller * @param {HTMLElement} xScroller - Horizontal scroller.
* @param {number} scrollX horizontal coordinate * @param {number} scrollX - Horizontal coordinate.
* @param {HTMLElement} yScroller vertical scroller * @param {HTMLElement} yScroller - Vertical scroller.
* @param {number} scrollY vertical coordinate * @param {number} scrollY - Vertical coordinate.
* @param {boolean} smooth smooth scrolling * @param {boolean} smooth - Smooth scrolling.
*/ */
function doScroll(xScroller, scrollX, yScroller, scrollY, smooth) { function doScroll(xScroller, scrollX, yScroller, scrollY, smooth) {
@ -403,26 +457,26 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
/** /**
* Returns true if scroll manager is enabled. * Returns true if scroll manager is enabled.
*/ */
var isEnabled = function() { export function isEnabled() {
return layoutManager.tv; return layoutManager.tv;
}; }
/** /**
* Scrolls the document to a given position. * Scrolls the document to a given position.
* *
* @param {number} scrollX horizontal coordinate * @param {number} scrollX - Horizontal coordinate.
* @param {number} scrollY vertical coordinate * @param {number} scrollY - Vertical coordinate.
* @param {boolean} [smooth=false] smooth scrolling * @param {boolean} [smooth=false] - Smooth scrolling.
*/ */
var scrollTo = function(scrollX, scrollY, smooth) { export function scrollTo(scrollX, scrollY, smooth) {
smooth = !!smooth; smooth = !!smooth;
// Scroller is document itself by default // Scroller is document itself by default
var scroller = getScrollableParent(null, false); const scroller = getScrollableParent(null, false);
var xScrollerData = getScrollerData(scroller, false); const xScrollerData = getScrollerData(scroller, false);
var yScrollerData = getScrollerData(scroller, true); const yScrollerData = getScrollerData(scroller, true);
scrollX = clamp(Math.round(scrollX), 0, xScrollerData.scrollSize - xScrollerData.clientSize); scrollX = clamp(Math.round(scrollX), 0, xScrollerData.scrollSize - xScrollerData.clientSize);
scrollY = clamp(Math.round(scrollY), 0, yScrollerData.scrollSize - yScrollerData.clientSize); scrollY = clamp(Math.round(scrollY), 0, yScrollerData.scrollSize - yScrollerData.clientSize);
@ -433,39 +487,39 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
/** /**
* Scrolls the document to a given element. * Scrolls the document to a given element.
* *
* @param {HTMLElement} element target element of scroll task * @param {HTMLElement} element - Target element of scroll task.
* @param {boolean} [smooth=false] smooth scrolling * @param {boolean} [smooth=false] - Smooth scrolling.
*/ */
var scrollToElement = function(element, smooth) { export function scrollToElement(element, smooth) {
smooth = !!smooth; smooth = !!smooth;
var scrollCenterX = true; let scrollCenterX = true;
var scrollCenterY = true; let scrollCenterY = true;
var offsetParent = element.offsetParent; const offsetParent = element.offsetParent;
// In Firefox offsetParent.offsetParent is BODY // In Firefox offsetParent.offsetParent is BODY
var isFixed = offsetParent && (!offsetParent.offsetParent || window.getComputedStyle(offsetParent).position === "fixed"); const isFixed = offsetParent && (!offsetParent.offsetParent || window.getComputedStyle(offsetParent).position === "fixed");
// Scroll fixed elements to nearest edge (or do not scroll at all) // Scroll fixed elements to nearest edge (or do not scroll at all)
if (isFixed) { if (isFixed) {
scrollCenterX = scrollCenterY = false; scrollCenterX = scrollCenterY = false;
} }
var xScroller = getScrollableParent(element, false); const xScroller = getScrollableParent(element, false);
var yScroller = getScrollableParent(element, true); const yScroller = getScrollableParent(element, true);
var elementRect = element.getBoundingClientRect(); const elementRect = element.getBoundingClientRect();
var xScrollerData = getScrollerData(xScroller, false); const xScrollerData = getScrollerData(xScroller, false);
var yScrollerData = getScrollerData(yScroller, true); const yScrollerData = getScrollerData(yScroller, true);
var xPos = getScrollerChildPos(xScroller, element, false); const xPos = getScrollerChildPos(xScroller, element, false);
var yPos = getScrollerChildPos(yScroller, element, true); const yPos = getScrollerChildPos(yScroller, element, true);
var scrollX = calcScroll(xScrollerData, xPos, elementRect.width, scrollCenterX); const scrollX = calcScroll(xScrollerData, xPos, elementRect.width, scrollCenterX);
var scrollY = calcScroll(yScrollerData, yPos, elementRect.height, scrollCenterY); let scrollY = calcScroll(yScrollerData, yPos, elementRect.height, scrollCenterY);
// HACK: Scroll to top for top menu because it is hidden // HACK: Scroll to top for top menu because it is hidden
// FIXME: Need a marker to scroll top/bottom // FIXME: Need a marker to scroll top/bottom
@ -490,9 +544,8 @@ define(["dom", "browser", "layoutManager"], function (dom, browser, layoutManage
}, {capture: true}); }, {capture: true});
} }
return { export default {
isEnabled: isEnabled, isEnabled: isEnabled,
scrollTo: scrollTo, scrollTo: scrollTo,
scrollToElement: scrollToElement scrollToElement: scrollToElement
}; };
});

View file

@ -433,13 +433,9 @@ define(['browser'], function (browser) {
var supportsDts = browser.tizen || browser.orsay || browser.web0s || options.supportsDts; var supportsDts = browser.tizen || browser.orsay || browser.web0s || options.supportsDts;
if (self.tizen && self.tizen.systeminfo) { // DTS audio not supported in 2018 models (Tizen 4.0)
var v = tizen.systeminfo.getCapability('http://tizen.org/feature/platform.version'); if (browser.tizenVersion >= 4) {
supportsDts = false;
// DTS audio not supported in 2018 models (Tizen 4.0)
if (v && parseFloat(v) >= parseFloat('4.0')) {
supportsDts = false;
}
} }
if (supportsDts) { if (supportsDts) {
@ -766,6 +762,11 @@ define(['browser'], function (browser) {
maxH264Level = 51; maxH264Level = 51;
} }
// Support H264 Level 52 (Tizen 5.0) - app only
if (browser.tizenVersion >= 5 && window.NativeShell) {
maxH264Level = 52;
}
if (browser.tizen || browser.orsay || if (browser.tizen || browser.orsay ||
videoTestElement.canPlayType('video/mp4; codecs="avc1.6e0033"').replace(/no/, '')) { videoTestElement.canPlayType('video/mp4; codecs="avc1.6e0033"').replace(/no/, '')) {

View file

@ -10,7 +10,7 @@
"All": "Всички", "All": "Всички",
"AllLibraries": "Всички библиотеки", "AllLibraries": "Всички библиотеки",
"Art": "Картина", "Art": "Картина",
"Artists": "Изпълнители", "Artists": "Артисти",
"AttributeNew": "Нови", "AttributeNew": "Нови",
"Audio": "Звук", "Audio": "Звук",
"Auto": "Автоматично", "Auto": "Автоматично",
@ -839,5 +839,7 @@
"LabelKodiMetadataSaveImagePathsHelp": "Препоръчително е ако имате изображения, пътят към които не е съобразен с изискванията на Коди.", "LabelKodiMetadataSaveImagePathsHelp": "Препоръчително е ако имате изображения, пътят към които не е съобразен с изискванията на Коди.",
"LabelKodiMetadataSaveImagePaths": "Записване на пътеките към изображенията в nfo файловете", "LabelKodiMetadataSaveImagePaths": "Записване на пътеките към изображенията в nfo файловете",
"LabelChannels": "Канали:", "LabelChannels": "Канали:",
"DropShadow": "Сянка" "DropShadow": "Сянка",
"Raised": "Повишено",
"OptionResElement": "рес. елемент"
} }

View file

@ -1401,7 +1401,7 @@
"TitleSupport": "Hilfe", "TitleSupport": "Hilfe",
"Whitelist": "Erlaubt", "Whitelist": "Erlaubt",
"AuthProviderHelp": "Auswählen eines Authentifizierungsanbieter, der zur Authentifizierung des Passworts dieses Benutzes verwendet werden soll.", "AuthProviderHelp": "Auswählen eines Authentifizierungsanbieter, der zur Authentifizierung des Passworts dieses Benutzes verwendet werden soll.",
"Features": "Features", "Features": "Funktionen",
"HeaderFavoriteBooks": "Lieblingsbücher", "HeaderFavoriteBooks": "Lieblingsbücher",
"HeaderFavoriteMovies": "Lieblingsfilme", "HeaderFavoriteMovies": "Lieblingsfilme",
"HeaderFavoriteShows": "Lieblingsserien", "HeaderFavoriteShows": "Lieblingsserien",

View file

@ -224,5 +224,96 @@
"AddedOnValue": "{0} افزوده شد", "AddedOnValue": "{0} افزوده شد",
"AddToPlaylist": "افزودن به لیست پخش", "AddToPlaylist": "افزودن به لیست پخش",
"AddToPlayQueue": "افزودن به صف پخش", "AddToPlayQueue": "افزودن به صف پخش",
"AddToCollection": "افزودن به مجموعه" "AddToCollection": "افزودن به مجموعه",
"ExitFullscreen": "خروج از تمام صفحه",
"EveryNDays": "هر {0} روز",
"ErrorMessageStartHourGreaterThanEnd": "زمان پایان باید پس از زمان شروع باشد.",
"Episodes": "قسمت‌ها",
"EndsAtValue": "تمام شده در {0}",
"Ended": "تمام شده",
"EnableThemeVideos": "تم فیلم‌ها",
"EnableThemeSongs": "آهنگ‌های تم",
"EnableStreamLooping": "چرخش خودکار پخش‌های زنده",
"EnablePhotos": "نمایش عکس‌ها",
"EnableNextVideoInfoOverlay": "نمایش اطلاعات ودیوی بعدی حین پخش ویدیو",
"EnableHardwareEncoding": "فعال سازی رمزگذاری سخت افزاری",
"EnableExternalVideoPlayersHelp": "یک منوی پخش کننده ویدیوی خارجی، زمانی که شروع به پخش ویدیو می‌شود نمایش داده خواهد شد.",
"EnableExternalVideoPlayers": "پخش کننده ویدیوی خارجی",
"EnableDisplayMirroring": "نمایش حالت آینه",
"EnableCinemaMode": "حالت سینما",
"EnableBackdrops": "پشت‌زمینه‌ها",
"EditSubtitles": "ویرایش زیرنویس‌ها",
"EditMetadata": "ویرایش ابرداده",
"EditImages": "ویرایش عکس‌ها",
"Edit": "ویرایش",
"DropShadow": "سایه پشت زمینه",
"DrmChannelsNotImported": "کانال‌ها با DRM وارد نخواند شد.",
"DownloadsValue": "{0} بارگیری‌ها",
"Download": "بارگیری",
"Down": "پایین",
"DoNotRecord": "ضبط نکن",
"DisplayModeHelp": "نوع صفحه نمایشی که Jellyfin را اجرا می‌کنید را انتخاب کنید‌‌.",
"DisplayMissingEpisodesWithinSeasons": "قسمت‌های ناموجود در فصل‌ها را نمایش بده",
"DisplayInMyMedia": "نمایش در صفحه‌ی خانه",
"Display": "نمایش",
"Dislike": "دوست نداشتن",
"Disconnect": "قطع اتصال",
"Disc": "دیسک",
"Directors": "کارگردانان",
"Director": "کارگردان",
"DirectStreaming": "پخش مستقیم",
"DirectStreamHelp2": "پخش مستقیم فایل از قدرت پردازش بسیار کمی بدون از دست دادن کیفیت ویدیو استفاده می‌کند.",
"DirectPlaying": "پخش مستقیم",
"DetectingDevices": "در حال تشخیص دستگاه‌ها",
"Descending": "پایین رونده",
"Depressed": "پژمرده",
"DeleteUserConfirmation": "آیا اطمینان دارید که می‌خواهید این کاربر را حذف کنید؟",
"DeleteUser": "حذف کاربر",
"DeleteImageConfirmation": "آیا اطمینان دارید که می‌خواهید این تصویر را حذف کنید؟",
"DeleteImage": "حذف تصویر",
"DeleteDeviceConfirmation": "آیا از حذف این دستگاه اطمینان دارید؟ هنگامی که یک کاربر دوباره با آن دستگاه وارد شود، دوباره نمایش داده می‌شود.",
"Delete": "حذف",
"DefaultMetadataLangaugeDescription": "این موارد پیشفرض‌های شماست و می‌توانید برای هر کتابخانه آن را شخصی سازی کنید.",
"DefaultErrorMessage": "خطایی در پردازش درخواست رخ داد. لطفا اندکی بعد دوباره تلاش کنید.",
"Default": "پیشفرض",
"DeathDateValue": "تلف شد: {0}",
"DatePlayed": "تاریخ پخش شده",
"DateAdded": "تاریخ اضافه شده",
"CriticRating": "امتیاز منتقدان",
"CopyStreamURLError": "در کپی کردن آدرس خطایی رخ داد.",
"CopyStreamURLSuccess": "آدرس با موفقیت کپی شد.",
"CopyStreamURL": "کپی آدرس پخش",
"Continuing": "ادامه",
"ContinueWatching": "ادامه تماشا",
"Connect": "اتصال",
"ConfirmEndPlayerSession": "آیا می‌خواهید Jellyfin را روی {0} خاموش کنید؟",
"ConfirmDeletion": "تایید حذف",
"ConfirmDeleteImage": "حذف تصویر؟",
"Composer": "آهنگساز",
"CommunityRating": "امتیاز عمومی",
"ColorTransfer": "انتقال رنگ",
"ColorSpace": "فضای رنگی",
"ColorPrimaries": "مقدمات رنگی",
"ClientSettings": "تنظیمات مشتری",
"ChannelNumber": "شماره کانال",
"ChannelNameOnly": "تنها کانال {0}",
"Categories": "دسته‌بندی‌ها",
"CancelSeries": "لغو سریال‌ها",
"CancelRecording": "لغو ضبط",
"ButtonWebsite": "وبسایت",
"ButtonViewWebsite": "بازدید وبسایت",
"ButtonUp": "بالا",
"ButtonUninstall": "حذف نصب",
"ButtonTrailer": "تریلر",
"ButtonSubtitles": "زیرنویس‌ها",
"ButtonSubmit": "تایید",
"ButtonSplit": "جدا کردن",
"ButtonStop": "توقف",
"ButtonStart": "شروع",
"ButtonSignIn": "ورود",
"ButtonShutdown": "خاموش",
"ButtonSelectDirectory": "انتخاب مسیر",
"ButtonEditOtherUserPreferences": "نمایه، تصویر و ترجیحات شخصی این کاربر را ویرایش کنید.",
"BrowsePluginCatalogMessage": "برای مرور کردن افزونه‌های موجود، به فروشگاه افزونه‌های ما سر بزنید.",
"AuthProviderHelp": "ارائه دهنده تأیید اعتبار را انتخاب کنید تا برای تأیید اعتبار گذرواژه این کاربر استفاده شود."
} }

View file

@ -1446,7 +1446,7 @@
"LabelAudioChannels": "Canaux audio :", "LabelAudioChannels": "Canaux audio :",
"HeaderFavoriteBooks": "Livres préférés", "HeaderFavoriteBooks": "Livres préférés",
"FetchingData": "Récuperer des données suplémentaires", "FetchingData": "Récuperer des données suplémentaires",
"CopyStreamURLSuccess": "URL copiée avec succès", "CopyStreamURLSuccess": "URL copiée avec succès.",
"CopyStreamURL": "Copier l'URL du flux", "CopyStreamURL": "Copier l'URL du flux",
"LabelBaseUrlHelp": "Vous pouvez ajouter un sous-répertoire personalisé ici pour accéder au serveur depuis une URL plus exclusive.", "LabelBaseUrlHelp": "Vous pouvez ajouter un sous-répertoire personalisé ici pour accéder au serveur depuis une URL plus exclusive.",
"HeaderFavoritePeople": "Personnes préférées", "HeaderFavoritePeople": "Personnes préférées",

View file

@ -264,7 +264,7 @@
"HeaderAddUser": "Aggiungi utente", "HeaderAddUser": "Aggiungi utente",
"HeaderAdditionalParts": "Parti addizionali", "HeaderAdditionalParts": "Parti addizionali",
"HeaderAdmin": "Admin", "HeaderAdmin": "Admin",
"HeaderAlbumArtists": "Artisti dell' Album", "HeaderAlbumArtists": "Artisti degli Album",
"HeaderAlbums": "Album", "HeaderAlbums": "Album",
"HeaderAlert": "Avviso", "HeaderAlert": "Avviso",
"HeaderAllowMediaDeletionFrom": "Abilita Eliminazione Media Da", "HeaderAllowMediaDeletionFrom": "Abilita Eliminazione Media Da",
@ -572,7 +572,7 @@
"LabelEvent": "Evento:", "LabelEvent": "Evento:",
"LabelEveryXMinutes": "Tutti:", "LabelEveryXMinutes": "Tutti:",
"LabelExtractChaptersDuringLibraryScan": "Estrarre immagini capitolo durante la scansione della libreria", "LabelExtractChaptersDuringLibraryScan": "Estrarre immagini capitolo durante la scansione della libreria",
"LabelExtractChaptersDuringLibraryScanHelp": "Genera le immagini del capitolo quando i video vengono importati durante la scansione della libreria. Altrimenti verranno estratti durante l'operazione pianificata di estrazione delle immagini capitolo, permettendo la scansione della libreria più velocemente.", "LabelExtractChaptersDuringLibraryScanHelp": "Genera le immagini capitolo quando i video vengono importati durante la scansione della libreria. Alternativamente, verranno estratti durante l'operazione pianificata di estrazione delle immagini capitolo, permettendo la scansione della libreria più velocemente.",
"LabelFailed": "Fallito", "LabelFailed": "Fallito",
"LabelFileOrUrl": "File o URL:", "LabelFileOrUrl": "File o URL:",
"LabelFinish": "Finito", "LabelFinish": "Finito",
@ -947,8 +947,8 @@
"OptionCustomUsers": "Personalizza", "OptionCustomUsers": "Personalizza",
"OptionDaily": "Giornaliero", "OptionDaily": "Giornaliero",
"OptionDateAdded": "Aggiunto il", "OptionDateAdded": "Aggiunto il",
"OptionDateAddedFileTime": "Utilizzare file di data di creazione", "OptionDateAddedFileTime": "Utilizzare la data di creazione del file",
"OptionDateAddedImportTime": "Utilizza la data scansionato in biblioteca", "OptionDateAddedImportTime": "Utilizza la data di scansione nella libreria",
"OptionDatePlayed": "Visto il", "OptionDatePlayed": "Visto il",
"OptionDescending": "Decrescente", "OptionDescending": "Decrescente",
"OptionDisableUser": "Disabilita questo utente", "OptionDisableUser": "Disabilita questo utente",
@ -1076,7 +1076,7 @@
"Programs": "Programmi", "Programs": "Programmi",
"Quality": "Qualità", "Quality": "Qualità",
"QueueAllFromHere": "In coda tutto da qui in poi", "QueueAllFromHere": "In coda tutto da qui in poi",
"Raised": "Sospeso", "Raised": "Rilievo",
"Rate": "Vota", "Rate": "Vota",
"RecentlyWatched": "Visti di recente", "RecentlyWatched": "Visti di recente",
"RecommendationBecauseYouLike": "Perché ti piace {0}", "RecommendationBecauseYouLike": "Perché ti piace {0}",
@ -1168,7 +1168,7 @@
"SystemDlnaProfilesHelp": "I profili di sistema sono in sola lettura. Le modifiche ad un profilo di sistema verranno salvate in un nuovo profilo personalizzato.", "SystemDlnaProfilesHelp": "I profili di sistema sono in sola lettura. Le modifiche ad un profilo di sistema verranno salvate in un nuovo profilo personalizzato.",
"TabAccess": "Accesso", "TabAccess": "Accesso",
"TabAdvanced": "Avanzato", "TabAdvanced": "Avanzato",
"TabAlbumArtists": "Artisti degli album", "TabAlbumArtists": "Artisti degli Album",
"TabAlbums": "Album", "TabAlbums": "Album",
"TabArtists": "Artisti", "TabArtists": "Artisti",
"TabCatalog": "Catalogo", "TabCatalog": "Catalogo",
@ -1312,7 +1312,7 @@
"HeaderFavoriteArtists": "Artisti Preferiti", "HeaderFavoriteArtists": "Artisti Preferiti",
"HeaderFavoriteSongs": "Brani Preferiti", "HeaderFavoriteSongs": "Brani Preferiti",
"HeaderFavoriteVideos": "Video Preferiti", "HeaderFavoriteVideos": "Video Preferiti",
"HeaderFetcherSettings": "Impostazioni Fetcher", "HeaderFetcherSettings": "Impostazioni del Fetcher",
"HeaderImageOptions": "Opzioni Immagine", "HeaderImageOptions": "Opzioni Immagine",
"HeaderRestartingServer": "Riavvio Server", "HeaderRestartingServer": "Riavvio Server",
"Home": "Home", "Home": "Home",
@ -1467,5 +1467,8 @@
"LabelCorruptedFrames": "Frame corrotti:", "LabelCorruptedFrames": "Frame corrotti:",
"AskAdminToCreateLibrary": "Chiedi ad un amministratore di creare una libreria.", "AskAdminToCreateLibrary": "Chiedi ad un amministratore di creare una libreria.",
"AllowFfmpegThrottlingHelp": "Quando una transcodifica o un remux sono abbastanza avanti rispetto alla corrente posizione di riproduzione, pausa il processo così da consumare meno risorse. Questo è utile quando si guarda un video senza avanzare spesso durante la riproduzione. Disattiva questa opzione se stai avendo problemi di riproduzione.", "AllowFfmpegThrottlingHelp": "Quando una transcodifica o un remux sono abbastanza avanti rispetto alla corrente posizione di riproduzione, pausa il processo così da consumare meno risorse. Questo è utile quando si guarda un video senza avanzare spesso durante la riproduzione. Disattiva questa opzione se stai avendo problemi di riproduzione.",
"AllowFfmpegThrottling": "Acceleratore Transcodifica" "AllowFfmpegThrottling": "Acceleratore Transcodifica",
"PreferEmbeddedEpisodeInfosOverFileNames": "Preferisci le informazioni incorporate nell'episodio rispetto ai nomi dei file",
"PreferEmbeddedEpisodeInfosOverFileNamesHelp": "Questo utilizza le informazioni dell'episodio provenienti dai metadata incorporati, se disponibili.",
"ClientSettings": "Impostazioni del client"
} }

View file

@ -1467,5 +1467,8 @@
"PlaybackErrorNoCompatibleStream": "Houve um erro na criação de perfil do cliente e o servidor não está enviando um formato de mídia compatível.", "PlaybackErrorNoCompatibleStream": "Houve um erro na criação de perfil do cliente e o servidor não está enviando um formato de mídia compatível.",
"EnableFastImageFadeInHelp": "Habilitar animações rápidas de aparecimento para imagens carregadas", "EnableFastImageFadeInHelp": "Habilitar animações rápidas de aparecimento para imagens carregadas",
"LabelDroppedFrames": "Quadros caídos:", "LabelDroppedFrames": "Quadros caídos:",
"AllowFfmpegThrottlingHelp": "Quando uma transcodificação ou remux estiver suficientemente avançada da posição atual de reprodução, pause o processo para que consuma menos recursos. Isso é mais proveitoso para quando não há avanço ou retrocesso do vídeo com frequência. Desative se tiver problemas de reprodução." "AllowFfmpegThrottlingHelp": "Quando uma transcodificação ou remux estiver suficientemente avançada da posição atual de reprodução, pause o processo para que consuma menos recursos. Isso é mais proveitoso para quando não há avanço ou retrocesso do vídeo com frequência. Desative se tiver problemas de reprodução.",
"PreferEmbeddedEpisodeInfosOverFileNames": "Preferir as informações incorporadas nos arquivos dos episódios ao invés dos nomes",
"PreferEmbeddedEpisodeInfosOverFileNamesHelp": "Isso utiliza as informações dos episódios incorporadas nos metadados dos arquivos se estiverem disponíveis.",
"ClientSettings": "Configurações do cliente"
} }