mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Merge branch 'jellyfin:master' into master
This commit is contained in:
commit
2aecd89d6e
40 changed files with 1513 additions and 1241 deletions
20
.github/dependabot.yaml
vendored
20
.github/dependabot.yaml
vendored
|
@ -1,13 +1,13 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: npm
|
||||
directory: /
|
||||
schedule:
|
||||
interval: monthly
|
||||
open-pull-requests-limit: 10
|
||||
- package-ecosystem: npm
|
||||
directory: /
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 10
|
||||
|
||||
- package-ecosystem: github-actions
|
||||
directory: '/'
|
||||
schedule:
|
||||
interval: monthly
|
||||
open-pull-requests-limit: 10
|
||||
- package-ecosystem: github-actions
|
||||
directory: /
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 10
|
||||
|
|
6
.github/workflows/automation.yml
vendored
6
.github/workflows/automation.yml
vendored
|
@ -2,15 +2,19 @@ name: 'Automation'
|
|||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request_target:
|
||||
types:
|
||||
- synchronize
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
name: 'Merge conflict labeling'
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.repository == 'jellyfin/jellyfin-web' }}
|
||||
steps:
|
||||
- uses: eps1lon/actions-label-merge-conflict@v2.0.1
|
||||
if: ${{ github.repository == 'jellyfin/jellyfin-web' }}
|
||||
with:
|
||||
dirtyLabel: 'merge conflict'
|
||||
repoToken: ${{ secrets.JF_BOT_TOKEN }}
|
||||
|
|
6
.github/workflows/lint.yml
vendored
6
.github/workflows/lint.yml
vendored
|
@ -16,7 +16,7 @@ jobs:
|
|||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup node environment
|
||||
uses: actions/setup-node@v2.2.0
|
||||
uses: actions/setup-node@v2.4.0
|
||||
with:
|
||||
node-version: 12
|
||||
check-latest: true
|
||||
|
@ -51,7 +51,7 @@ jobs:
|
|||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup node environment
|
||||
uses: actions/setup-node@v2.2.0
|
||||
uses: actions/setup-node@v2.4.0
|
||||
with:
|
||||
node-version: 12
|
||||
check-latest: true
|
||||
|
@ -89,7 +89,7 @@ jobs:
|
|||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup node environment
|
||||
uses: actions/setup-node@v2.2.0
|
||||
uses: actions/setup-node@v2.4.0
|
||||
with:
|
||||
node-version: 12
|
||||
check-latest: true
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
- [danieladov](https://github.com/danieladov)
|
||||
- [Stephane Senart](https://github.com/ssenart)
|
||||
- [Ömer Erdinç Yağmurlu](https://github.com/omeryagmurlu)
|
||||
- [Keegan Dahm](https://github.com/keegandahm)
|
||||
|
||||
# Emby Contributors
|
||||
|
||||
|
|
2174
package-lock.json
generated
2174
package-lock.json
generated
File diff suppressed because it is too large
Load diff
62
package.json
62
package.json
|
@ -5,30 +5,30 @@
|
|||
"repository": "https://github.com/jellyfin/jellyfin-web",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.14.6",
|
||||
"@babel/eslint-parser": "^7.14.7",
|
||||
"@babel/core": "^7.15.0",
|
||||
"@babel/eslint-parser": "^7.15.0",
|
||||
"@babel/eslint-plugin": "^7.14.5",
|
||||
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
||||
"@babel/plugin-proposal-private-methods": "^7.14.5",
|
||||
"@babel/plugin-transform-modules-umd": "^7.14.5",
|
||||
"@babel/preset-env": "^7.14.7",
|
||||
"@babel/preset-env": "^7.15.0",
|
||||
"@babel/preset-react": "^7.14.5",
|
||||
"@babel/preset-typescript": "^7.14.5",
|
||||
"@typescript-eslint/eslint-plugin": "^4.28.1",
|
||||
"@typescript-eslint/parser": "^4.28.2",
|
||||
"@babel/preset-typescript": "^7.15.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.29.1",
|
||||
"@typescript-eslint/parser": "^4.29.1",
|
||||
"@uupaa/dynamic-import-polyfill": "^1.0.2",
|
||||
"autoprefixer": "^10.2.6",
|
||||
"autoprefixer": "^10.3.1",
|
||||
"babel-loader": "^8.2.2",
|
||||
"babel-plugin-dynamic-import-polyfill": "^1.0.0",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"confusing-browser-globals": "^1.0.10",
|
||||
"copy-webpack-plugin": "^9.0.1",
|
||||
"css-loader": "^5.2.6",
|
||||
"cssnano": "^5.0.6",
|
||||
"eslint": "^7.29.0",
|
||||
"eslint-plugin-compat": "^3.9.0",
|
||||
"cssnano": "^5.0.7",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-plugin-compat": "^3.12.0",
|
||||
"eslint-plugin-eslint-comments": "^3.2.0",
|
||||
"eslint-plugin-import": "^2.23.4",
|
||||
"eslint-plugin-import": "^2.24.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||
"eslint-plugin-promise": "^5.1.0",
|
||||
"eslint-plugin-react": "^7.24.0",
|
||||
|
@ -37,43 +37,43 @@
|
|||
"file-loader": "^6.2.0",
|
||||
"html-loader": "^2.1.2",
|
||||
"html-webpack-plugin": "^5.3.2",
|
||||
"postcss": "^8.3.5",
|
||||
"postcss": "^8.3.6",
|
||||
"postcss-loader": "^6.1.1",
|
||||
"postcss-preset-env": "^6.7.0",
|
||||
"sass": "^1.35.1",
|
||||
"sass": "^1.37.5",
|
||||
"sass-loader": "^12.1.0",
|
||||
"source-map-loader": "^3.0.0",
|
||||
"style-loader": "^3.0.0",
|
||||
"style-loader": "^3.2.1",
|
||||
"stylelint": "^13.13.1",
|
||||
"stylelint-config-rational-order": "^0.1.2",
|
||||
"stylelint-no-browser-hacks": "^1.2.1",
|
||||
"stylelint-order": "^4.1.0",
|
||||
"stylelint-scss": "^3.19.0",
|
||||
"ts-loader": "^9.2.3",
|
||||
"stylelint-scss": "^3.20.1",
|
||||
"ts-loader": "^9.2.5",
|
||||
"typescript": "^4.3.5",
|
||||
"webpack": "^5.43.0",
|
||||
"webpack": "^5.49.0",
|
||||
"webpack-cli": "^4.7.2",
|
||||
"webpack-dev-server": "^3.11.2",
|
||||
"webpack-merge": "^5.8.0",
|
||||
"workbox-webpack-plugin": "^6.1.5",
|
||||
"workbox-webpack-plugin": "^6.2.2",
|
||||
"worker-plugin": "^5.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource/noto-sans": "^4.4.5",
|
||||
"@fontsource/noto-sans-hk": "^4.4.5",
|
||||
"@fontsource/noto-sans-jp": "^4.4.5",
|
||||
"@fontsource/noto-sans-kr": "^4.4.5",
|
||||
"@fontsource/noto-sans-sc": "^4.4.5",
|
||||
"@fontsource/noto-sans": "^4.5.0",
|
||||
"@fontsource/noto-sans-hk": "^4.5.0",
|
||||
"@fontsource/noto-sans-jp": "^4.5.0",
|
||||
"@fontsource/noto-sans-kr": "^4.5.0",
|
||||
"@fontsource/noto-sans-sc": "^4.5.0",
|
||||
"blurhash": "^1.1.3",
|
||||
"classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz",
|
||||
"classnames": "^2.3.1",
|
||||
"core-js": "^3.15.2",
|
||||
"date-fns": "^2.22.1",
|
||||
"core-js": "^3.16.1",
|
||||
"date-fns": "^2.23.0",
|
||||
"epubjs": "^0.3.85",
|
||||
"fast-text-encoding": "^1.0.3",
|
||||
"flv.js": "^1.5.0",
|
||||
"flv.js": "^1.6.1",
|
||||
"headroom.js": "^0.12.0",
|
||||
"hls.js": "^0.14.17",
|
||||
"hls.js": "^1.0.8",
|
||||
"intersection-observer": "^0.12.0",
|
||||
"jellyfin-apiclient": "^1.8.0",
|
||||
"jquery": "^3.5.1",
|
||||
|
@ -89,12 +89,12 @@
|
|||
"react-dom": "^17.0.2",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"screenfull": "^5.1.0",
|
||||
"sortablejs": "^1.13.0",
|
||||
"swiper": "^6.7.5",
|
||||
"sortablejs": "^1.14.0",
|
||||
"swiper": "^6.8.1",
|
||||
"webcomponents.js": "^0.7.24",
|
||||
"whatwg-fetch": "^3.6.2",
|
||||
"workbox-core": "^5.1.4",
|
||||
"workbox-precaching": "^5.1.4"
|
||||
"workbox-core": "^6.2.2",
|
||||
"workbox-precaching": "^6.2.2"
|
||||
},
|
||||
"browserslist": [
|
||||
"last 2 Firefox versions",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { version as appVersion } from '../../package.json';
|
||||
import Package from '../../package.json';
|
||||
import appSettings from '../scripts/settings/appSettings';
|
||||
import browser from '../scripts/browser';
|
||||
import { Events } from 'jellyfin-apiclient';
|
||||
|
@ -33,7 +33,7 @@ function getDeviceProfile(item) {
|
|||
let profile;
|
||||
|
||||
if (window.NativeShell) {
|
||||
profile = window.NativeShell.AppHost.getDeviceProfile(profileBuilder, appVersion);
|
||||
profile = window.NativeShell.AppHost.getDeviceProfile(profileBuilder, Package.version);
|
||||
} else {
|
||||
const builderOpts = getBaseProfileOptions(item);
|
||||
profile = profileBuilder(builderOpts);
|
||||
|
@ -373,7 +373,7 @@ export const appHost = {
|
|||
},
|
||||
appVersion: function () {
|
||||
return window.NativeShell?.AppHost?.appVersion
|
||||
? window.NativeShell.AppHost.appVersion() : appVersion;
|
||||
? window.NativeShell.AppHost.appVersion() : Package.version;
|
||||
},
|
||||
getPushTokenInfo: function () {
|
||||
return {};
|
||||
|
|
|
@ -397,7 +397,7 @@ import ServerConnections from '../ServerConnections';
|
|||
|
||||
const itemsContainer = elem.querySelector('.itemsContainer');
|
||||
itemsContainer.fetchData = getItemsToResumeFn(mediaType, apiClient.serverId());
|
||||
itemsContainer.getItemsHtml = getItemsToResumeHtmlFn(userSettings.useEpisodeImagesInNextUpAndResume());
|
||||
itemsContainer.getItemsHtml = getItemsToResumeHtmlFn(userSettings.useEpisodeImagesInNextUpAndResume(), mediaType);
|
||||
itemsContainer.parentContainer = elem;
|
||||
}
|
||||
|
||||
|
@ -428,14 +428,14 @@ import ServerConnections from '../ServerConnections';
|
|||
};
|
||||
}
|
||||
|
||||
function getItemsToResumeHtmlFn(useEpisodeImages) {
|
||||
function getItemsToResumeHtmlFn(useEpisodeImages, mediaType) {
|
||||
return function (items) {
|
||||
const cardLayout = false;
|
||||
return cardBuilder.getCardsHtml({
|
||||
items: items,
|
||||
preferThumb: true,
|
||||
inheritThumb: !useEpisodeImages,
|
||||
defaultShape: getThumbShape(),
|
||||
shape: (mediaType === 'Book') ? getPortraitShape() : getThumbShape(),
|
||||
overlayText: false,
|
||||
showTitle: true,
|
||||
showParentTitle: true,
|
||||
|
|
|
@ -173,6 +173,15 @@ import layoutManager from './layoutManager';
|
|||
return Math.min(document.documentElement.clientHeight, document.body.clientHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns attribute value.
|
||||
* @param {string} attributeName - Attibute name.
|
||||
* @return {string} Attibute value.
|
||||
*/
|
||||
getAttribute(attributeName) {
|
||||
return document.body.getAttribute(attributeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns bounding client rect.
|
||||
* @return {Rect} Bounding client rect.
|
||||
|
@ -201,6 +210,21 @@ import layoutManager from './layoutManager';
|
|||
*/
|
||||
const documentScroller = new DocumentScroller();
|
||||
|
||||
const scrollerHints = {
|
||||
x: {
|
||||
nameScroll: 'scrollWidth',
|
||||
nameClient: 'clientWidth',
|
||||
nameStyle: 'overflowX',
|
||||
nameScrollMode: 'data-scroll-mode-x'
|
||||
},
|
||||
y: {
|
||||
nameScroll: 'scrollHeight',
|
||||
nameClient: 'clientHeight',
|
||||
nameStyle: 'overflowY',
|
||||
nameScrollMode: 'data-scroll-mode-y'
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns parent element that can be scrolled. If no such, returns document scroller.
|
||||
*
|
||||
|
@ -210,23 +234,28 @@ import layoutManager from './layoutManager';
|
|||
*/
|
||||
function getScrollableParent(element, vertical) {
|
||||
if (element) {
|
||||
let nameScroll = 'scrollWidth';
|
||||
let nameClient = 'clientWidth';
|
||||
let nameClass = 'scrollX';
|
||||
|
||||
if (vertical) {
|
||||
nameScroll = 'scrollHeight';
|
||||
nameClient = 'clientHeight';
|
||||
nameClass = 'scrollY';
|
||||
}
|
||||
const scrollerHint = vertical ? scrollerHints.y : scrollerHints.x;
|
||||
|
||||
let parent = element.parentElement;
|
||||
|
||||
while (parent) {
|
||||
// Skip 'emby-scroller' and 'emby-tabs' because they scroll by themselves
|
||||
if (!parent.classList.contains('emby-scroller') &&
|
||||
!parent.classList.contains('emby-tabs') &&
|
||||
parent[nameScroll] > parent[nameClient] && parent.classList.contains(nameClass)) {
|
||||
while (parent && parent !== document.body) {
|
||||
const scrollMode = parent.getAttribute(scrollerHint.nameScrollMode);
|
||||
|
||||
// Stop on self-scrolled containers
|
||||
if (scrollMode === 'custom') {
|
||||
return parent;
|
||||
}
|
||||
|
||||
const styles = window.getComputedStyle(parent);
|
||||
|
||||
// Stop on fixed parent
|
||||
if (styles.position === 'fixed') {
|
||||
return parent;
|
||||
}
|
||||
|
||||
const overflow = styles[scrollerHint.nameStyle];
|
||||
|
||||
if (overflow === 'scroll' || overflow === 'auto' && parent[scrollerHint.nameScroll] > parent[scrollerHint.nameClient]) {
|
||||
return parent;
|
||||
}
|
||||
|
||||
|
@ -242,6 +271,8 @@ import layoutManager from './layoutManager';
|
|||
* @property {number} scrollPos - Current scroll position.
|
||||
* @property {number} scrollSize - Scroll size.
|
||||
* @property {number} clientSize - Client size.
|
||||
* @property {string} mode - Scrolling mode.
|
||||
* @property {boolean} custom - Custom scrolling mode.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -258,12 +289,16 @@ import layoutManager from './layoutManager';
|
|||
data.scrollPos = scroller.scrollLeft;
|
||||
data.scrollSize = scroller.scrollWidth;
|
||||
data.clientSize = scroller.clientWidth;
|
||||
data.mode = scroller.getAttribute(scrollerHints.x.nameScrollMode);
|
||||
} else {
|
||||
data.scrollPos = scroller.scrollTop;
|
||||
data.scrollSize = scroller.scrollHeight;
|
||||
data.clientSize = scroller.clientHeight;
|
||||
data.mode = scroller.getAttribute(scrollerHints.y.nameScrollMode);
|
||||
}
|
||||
|
||||
data.custom = data.mode === 'custom';
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -348,9 +383,13 @@ import layoutManager from './layoutManager';
|
|||
const scrollBehavior = smooth ? 'smooth' : 'instant';
|
||||
|
||||
if (xScroller !== yScroller) {
|
||||
scrollToHelper(xScroller, {left: scrollX, behavior: scrollBehavior});
|
||||
scrollToHelper(yScroller, {top: scrollY, behavior: scrollBehavior});
|
||||
} else {
|
||||
if (xScroller) {
|
||||
scrollToHelper(xScroller, {left: scrollX, behavior: scrollBehavior});
|
||||
}
|
||||
if (yScroller) {
|
||||
scrollToHelper(yScroller, {top: scrollY, behavior: scrollBehavior});
|
||||
}
|
||||
} else if (xScroller) {
|
||||
scrollToHelper(xScroller, {left: scrollX, top: scrollY, behavior: scrollBehavior});
|
||||
}
|
||||
}
|
||||
|
@ -377,8 +416,8 @@ import layoutManager from './layoutManager';
|
|||
* @param {number} scrollY - Vertical coordinate.
|
||||
*/
|
||||
function animateScroll(xScroller, scrollX, yScroller, scrollY) {
|
||||
const ox = xScroller.scrollLeft;
|
||||
const oy = yScroller.scrollTop;
|
||||
const ox = xScroller ? xScroller.scrollLeft : scrollX;
|
||||
const oy = yScroller ? yScroller.scrollTop : scrollY;
|
||||
const dx = scrollX - ox;
|
||||
const dy = scrollY - oy;
|
||||
|
||||
|
@ -502,30 +541,51 @@ import layoutManager from './layoutManager';
|
|||
scrollCenterX = scrollCenterY = false;
|
||||
}
|
||||
|
||||
const xScroller = getScrollableParent(element, false);
|
||||
const yScroller = getScrollableParent(element, true);
|
||||
|
||||
const elementRect = element.getBoundingClientRect();
|
||||
let xScroller = getScrollableParent(element, false);
|
||||
let yScroller = getScrollableParent(element, true);
|
||||
|
||||
const xScrollerData = getScrollerData(xScroller, false);
|
||||
const yScrollerData = getScrollerData(yScroller, true);
|
||||
|
||||
const xPos = getScrollerChildPos(xScroller, element, false);
|
||||
const yPos = getScrollerChildPos(yScroller, element, true);
|
||||
|
||||
const scrollX = calcScroll(xScrollerData, xPos, elementRect.width, scrollCenterX);
|
||||
let scrollY = calcScroll(yScrollerData, yPos, elementRect.height, scrollCenterY);
|
||||
|
||||
// HACK: Scroll to top for top menu because it is hidden
|
||||
// FIXME: Need a marker to scroll top/bottom
|
||||
if (isFixed && elementRect.bottom < 0) {
|
||||
scrollY = 0;
|
||||
// Exit, since we have no control over scrolling in this container
|
||||
if (xScroller === yScroller && (xScrollerData.custom || yScrollerData.custom)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// HACK: Ensure we are at the top
|
||||
// FIXME: Need a marker to scroll top/bottom
|
||||
if (scrollY < minimumScrollY() && yScroller === documentScroller) {
|
||||
scrollY = 0;
|
||||
// Exit, since we have no control over scrolling in these containers
|
||||
if (xScrollerData.custom && yScrollerData.custom) {
|
||||
return;
|
||||
}
|
||||
|
||||
const elementRect = element.getBoundingClientRect();
|
||||
|
||||
let scrollX = 0;
|
||||
let scrollY = 0;
|
||||
|
||||
if (!xScrollerData.custom) {
|
||||
const xPos = getScrollerChildPos(xScroller, element, false);
|
||||
scrollX = calcScroll(xScrollerData, xPos, elementRect.width, scrollCenterX);
|
||||
} else {
|
||||
xScroller = null;
|
||||
}
|
||||
|
||||
if (!yScrollerData.custom) {
|
||||
const yPos = getScrollerChildPos(yScroller, element, true);
|
||||
scrollY = calcScroll(yScrollerData, yPos, elementRect.height, scrollCenterY);
|
||||
|
||||
// HACK: Scroll to top for top menu because it is hidden
|
||||
// FIXME: Need a marker to scroll top/bottom
|
||||
if (isFixed && elementRect.bottom < 0) {
|
||||
scrollY = 0;
|
||||
}
|
||||
|
||||
// HACK: Ensure we are at the top
|
||||
// FIXME: Need a marker to scroll top/bottom
|
||||
if (scrollY < minimumScrollY() && yScroller === documentScroller) {
|
||||
scrollY = 0;
|
||||
}
|
||||
} else {
|
||||
yScroller = null;
|
||||
}
|
||||
|
||||
doScroll(xScroller, scrollX, yScroller, scrollY, smooth);
|
||||
|
|
|
@ -1224,11 +1224,9 @@ function renderMoreFromArtist(view, item, apiClient) {
|
|||
};
|
||||
|
||||
if (item.Type === 'MusicArtist') {
|
||||
query.ContributingArtistIds = item.Id;
|
||||
} else if (apiClient.isMinServerVersion('3.4.1.18')) {
|
||||
query.AlbumArtistIds = item.AlbumArtists[0].Id;
|
||||
query.AlbumArtistIds = item.Id;
|
||||
} else {
|
||||
query.ArtistIds = item.AlbumArtists[0].Id;
|
||||
query.AlbumArtistIds = item.AlbumArtists[0].Id;
|
||||
}
|
||||
|
||||
apiClient.getItems(apiClient.getCurrentUserId(), query).then(function (result) {
|
||||
|
|
|
@ -260,9 +260,9 @@ import cardBuilder from '../../../components/cardbuilder/cardBuilder';
|
|||
|
||||
const apiClient = getApiClient();
|
||||
|
||||
apiClient.getQuickConnect('Status')
|
||||
.then(status => {
|
||||
if (status !== 'Unavailable') {
|
||||
apiClient.getQuickConnect('Enabled')
|
||||
.then(enabled => {
|
||||
if (enabled === true) {
|
||||
view.querySelector('.btnQuick').classList.remove('hide');
|
||||
}
|
||||
})
|
||||
|
|
|
@ -12,6 +12,15 @@
|
|||
</div>
|
||||
</a>
|
||||
|
||||
<a is="emby-linkbutton" data-ripple="false" href="#" style="display:block;padding:0;margin:0;" class="lnkQuickConnectPreferences listItem-border hide">
|
||||
<div class="listItem">
|
||||
<em class="material-icons listItemIcon listItemIcon-transparent">tap_and_play</em>
|
||||
<div class="listItemBody">
|
||||
<div class="listItemBodyText">${QuickConnect}</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a is="emby-linkbutton" data-ripple="false" href="#" style="display:block;padding:0;margin:0;" class="lnkDisplayPreferences listItem-border">
|
||||
<div class="listItem">
|
||||
<span class="material-icons listItemIcon listItemIcon-transparent tv"></span>
|
||||
|
@ -48,16 +57,6 @@
|
|||
</div>
|
||||
</a>
|
||||
|
||||
|
||||
<a is="emby-linkbutton" data-ripple="false" href="#" style="display:block;padding:0;margin:0;" class="lnkQuickConnectPreferences listItem-border hide">
|
||||
<div class="listItem">
|
||||
<em class="material-icons listItemIcon listItemIcon-transparent">tap_and_play</em>
|
||||
<div class="listItemBody">
|
||||
<div class="listItemBodyText">${QuickConnect}</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a is="emby-linkbutton" data-ripple="false" href="#" style="display:block;padding:0;margin:0;" class="clientSettings listItem-border">
|
||||
<div class="listItem">
|
||||
<span class="material-icons listItemIcon listItemIcon-transparent devices_other"></span>
|
||||
|
|
|
@ -38,16 +38,15 @@ export default function (view, params) {
|
|||
|
||||
page.querySelector('.lnkControlsPreferences').classList.toggle('hide', layoutManager.mobile);
|
||||
|
||||
ApiClient.getQuickConnect('Status')
|
||||
.then(status => {
|
||||
if (status !== 'Unavailable') {
|
||||
ApiClient.getQuickConnect('Enabled')
|
||||
.then(enabled => {
|
||||
if (enabled === true) {
|
||||
page.querySelector('.lnkQuickConnectPreferences').classList.remove('hide');
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
console.debug('Failed to get QuickConnect status');
|
||||
});
|
||||
|
||||
ApiClient.getUser(userId).then(function (user) {
|
||||
page.querySelector('.headerUsername').innerHTML = user.Name;
|
||||
if (user.Policy.IsAdministrator && !layoutManager.tv) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import globalize from '../../../scripts/globalize';
|
||||
import toast from '../../../components/toast/toast';
|
||||
import Dashboard from '../../../scripts/clientUtils';
|
||||
|
||||
export const authorize = (code) => {
|
||||
const url = ApiClient.getUrl('/QuickConnect/Authorize?Code=' + code);
|
||||
|
@ -16,22 +15,3 @@ export const authorize = (code) => {
|
|||
// prevent bubbling
|
||||
return false;
|
||||
};
|
||||
|
||||
export const activate = () => {
|
||||
const url = ApiClient.getUrl('/QuickConnect/Activate');
|
||||
return ApiClient.ajax({
|
||||
type: 'POST',
|
||||
url: url
|
||||
}).then(() => {
|
||||
toast(globalize.translate('QuickConnectActivationSuccessful'));
|
||||
return true;
|
||||
}).catch((e) => {
|
||||
console.error('Error activating quick connect. Error:', e);
|
||||
Dashboard.alert({
|
||||
title: globalize.translate('HeaderError'),
|
||||
message: globalize.translate('DefaultErrorMessage')
|
||||
});
|
||||
|
||||
throw e;
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,19 +1,15 @@
|
|||
<div id="quickConnectPreferencesPage" data-role="page" class="page libraryPage userPreferencesPage noSecondaryNavPage" data-title="${QuickConnect}" data-backbutton="true" style="margin: 0 auto; max-width: 54em">
|
||||
<div class="settingsContainer padded-left padded-right padded-bottom-page">
|
||||
<button is="emby-button" id="btnQuickConnectActivate" type="button" class="raised button-submit block">
|
||||
<span>${ButtonActivate}</span>
|
||||
</button>
|
||||
|
||||
<form class="quickConnectSettingsContainer">
|
||||
<div style="margin-bottom: 1em">
|
||||
${QuickConnectDescription}
|
||||
</div>
|
||||
<form class="quickConnectSettingsContainer">
|
||||
<div class="verticalSection">
|
||||
<h2 class="sectionTitle">${QuickConnect}</h2>
|
||||
<div>${QuickConnectDescription}</div>
|
||||
<br />
|
||||
<div class="inputContainer">
|
||||
<input is="emby-input" type="number" min="0" max="999999" required id="txtQuickConnectCode" label="${LabelQuickConnectCode}" autocomplete="off" />
|
||||
</div>
|
||||
<button id="btnQuickConnectAuthorize" is="emby-button" type="submit" class="raised button-submit block">
|
||||
<span>${Authorize}</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { activate, authorize } from './helper';
|
||||
import { authorize } from './helper';
|
||||
import globalize from '../../../scripts/globalize';
|
||||
import toast from '../../../components/toast/toast';
|
||||
|
||||
|
@ -6,52 +6,16 @@ export default function (view) {
|
|||
view.addEventListener('viewshow', function () {
|
||||
const codeElement = view.querySelector('#txtQuickConnectCode');
|
||||
|
||||
view.querySelector('#btnQuickConnectActivate').addEventListener('click', () => {
|
||||
activate().then(() => {
|
||||
renderPage();
|
||||
});
|
||||
});
|
||||
view.querySelector('.quickConnectSettingsContainer').addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
view.querySelector('#btnQuickConnectAuthorize').addEventListener('click', () => {
|
||||
if (!codeElement.validity.valid) {
|
||||
toast(globalize.translate('QuickConnectInvalidCode'));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const code = codeElement.value;
|
||||
authorize(code);
|
||||
authorize(codeElement.value);
|
||||
});
|
||||
|
||||
view.querySelector('.quickConnectSettingsContainer').addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
renderPage();
|
||||
});
|
||||
|
||||
function renderPage(forceActive = false) {
|
||||
ApiClient.getQuickConnect('Status').then((status) => {
|
||||
const btn = view.querySelector('#btnQuickConnectActivate');
|
||||
const container = view.querySelector('.quickConnectSettingsContainer');
|
||||
|
||||
// The activation button should only be visible when quick connect is unavailable (with the text replaced with an error) or when it is available (so it can be activated)
|
||||
// The authorization container is only usable when quick connect is active, so it should be hidden otherwise
|
||||
container.style.display = 'none';
|
||||
|
||||
if (status === 'Unavailable') {
|
||||
btn.textContent = globalize.translate('QuickConnectNotAvailable');
|
||||
btn.disabled = true;
|
||||
btn.classList.remove('button-submit');
|
||||
btn.classList.add('button');
|
||||
} else if (status === 'Active' || forceActive) {
|
||||
container.style.display = '';
|
||||
btn.style.display = 'none';
|
||||
}
|
||||
|
||||
return true;
|
||||
}).catch((e) => {
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -630,6 +630,8 @@ const scrollerFactory = function (frame, options) {
|
|||
//passive: true
|
||||
});
|
||||
|
||||
scrollSource.removeAttribute(`data-scroll-mode-${o.horizontal ? 'x' : 'y'}`);
|
||||
|
||||
// Reset initialized status and return the instance
|
||||
self.initialized = 0;
|
||||
return self;
|
||||
|
@ -751,6 +753,8 @@ const scrollerFactory = function (frame, options) {
|
|||
}
|
||||
}
|
||||
|
||||
scrollSource.setAttribute(`data-scroll-mode-${o.horizontal ? 'x' : 'y'}`, 'custom');
|
||||
|
||||
if (transform || layoutManager.tv) {
|
||||
// This can prevent others from being able to listen to mouse events
|
||||
dom.addEventListener(dragSourceElement, 'mousedown', dragInitSlidee, {
|
||||
|
|
|
@ -457,14 +457,14 @@ class HtmlAudioPlayer {
|
|||
setVolume(val) {
|
||||
const mediaElement = this._mediaElement;
|
||||
if (mediaElement) {
|
||||
mediaElement.volume = val / 100;
|
||||
mediaElement.volume = Math.pow(val / 100, 3);
|
||||
}
|
||||
}
|
||||
|
||||
getVolume() {
|
||||
const mediaElement = this._mediaElement;
|
||||
if (mediaElement) {
|
||||
return Math.min(Math.round(mediaElement.volume * 100), 100);
|
||||
return Math.min(Math.round(Math.pow(mediaElement.volume, 1 / 3) * 100), 100);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -385,7 +385,6 @@ function tryRemoveElement(elem) {
|
|||
return new Promise((resolve, reject) => {
|
||||
requireHlsPlayer(async () => {
|
||||
let maxBufferLength = 30;
|
||||
let maxMaxBufferLength = 600;
|
||||
|
||||
// Some browsers cannot handle huge fragments in high bitrate.
|
||||
// This issue usually happens when using HWA encoders with a high bitrate setting.
|
||||
|
@ -393,7 +392,6 @@ function tryRemoveElement(elem) {
|
|||
// https://github.com/video-dev/hls.js/issues/876
|
||||
if ((browser.chrome || browser.edgeChromium || browser.firefox) && playbackManager.getMaxStreamingBitrate(this) >= 25000000) {
|
||||
maxBufferLength = 6;
|
||||
maxMaxBufferLength = 6;
|
||||
}
|
||||
|
||||
const includeCorsCredentials = await getIncludeCorsCredentials();
|
||||
|
@ -401,7 +399,6 @@ function tryRemoveElement(elem) {
|
|||
const hls = new Hls({
|
||||
manifestLoadingTimeOut: 20000,
|
||||
maxBufferLength: maxBufferLength,
|
||||
maxMaxBufferLength: maxMaxBufferLength,
|
||||
xhrSetup(xhr) {
|
||||
xhr.withCredentials = includeCorsCredentials;
|
||||
}
|
||||
|
@ -1708,14 +1705,14 @@ function tryRemoveElement(elem) {
|
|||
setVolume(val) {
|
||||
const mediaElement = this.#mediaElement;
|
||||
if (mediaElement) {
|
||||
mediaElement.volume = val / 100;
|
||||
mediaElement.volume = Math.pow(val / 100, 3);
|
||||
}
|
||||
}
|
||||
|
||||
getVolume() {
|
||||
const mediaElement = this.#mediaElement;
|
||||
if (mediaElement) {
|
||||
return Math.min(Math.round(mediaElement.volume * 100), 100);
|
||||
return Math.min(Math.round(Math.pow(mediaElement.volume, 1 / 3) * 100), 100);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -103,6 +103,8 @@ function centerOnFocusVertical(e) {
|
|||
|
||||
export const centerFocus = {
|
||||
on: function (element, horizontal) {
|
||||
element.setAttribute(`data-scroll-mode-${horizontal ? 'x' : 'y'}`, 'custom');
|
||||
|
||||
if (horizontal) {
|
||||
dom.addEventListener(element, 'focus', centerOnFocusHorizontal, {
|
||||
capture: true,
|
||||
|
@ -116,6 +118,8 @@ export const centerFocus = {
|
|||
}
|
||||
},
|
||||
off: function (element, horizontal) {
|
||||
element.removeAttribute(`data-scroll-mode-${horizontal ? 'x' : 'y'}`);
|
||||
|
||||
if (horizontal) {
|
||||
dom.removeEventListener(element, 'focus', centerOnFocusHorizontal, {
|
||||
capture: true,
|
||||
|
|
|
@ -772,5 +772,42 @@
|
|||
"DirectPlayHelp": "El fitxer font és totalment compatible amb aquest client i la sessió rep el fitxer sense modificacions.",
|
||||
"DeleteDevicesConfirmation": "Esteu segur que voleu suprimir tots els dispositius? Es tancarà la sessió de la resta de sessions. Els dispositius tornaran a aparèixer la pròxima vegada que un usuari iniciï la sessió.",
|
||||
"DeleteAll": "Eliminar tots",
|
||||
"DeinterlaceMethodHelp": "Seleccioneu el mètode de desentrellaçat que voleu utilitzar quan transcodifiqueu el programari de contingut entrellaçat. Quan està activada l'acceleració de maquinari que admet el desentrellaçat de maquinari, s'utilitzarà el desentrellaçador de maquinari en lloc d'aquesta configuració."
|
||||
"DeinterlaceMethodHelp": "Seleccioneu el mètode de desentrellaçat que voleu utilitzar quan transcodifiqueu el programari de contingut entrellaçat. Quan està activada l'acceleració de maquinari que admet el desentrellaçat de maquinari, s'utilitzarà el desentrellaçador de maquinari en lloc d'aquesta configuració.",
|
||||
"HeaderDirectPlayProfileHelp": "Afegiu perfils de reproducció directa per indicar quins formats pot gestionar el dispositiu de forma nativa.",
|
||||
"HeaderDetectMyDevices": "Detectar els meus dispositius",
|
||||
"HeaderDeleteTaskTrigger": "Suprimir el disparador de tasques",
|
||||
"HeaderDeleteProvider": "Suprimeix el proveïdor",
|
||||
"HeaderDeleteItems": "Suprimeix els elements",
|
||||
"HeaderDeleteDevices": "Suprimir tots els dispositius",
|
||||
"HeaderDebugging": "Depuració i traceig",
|
||||
"HeaderContinueReading": "Continuar llegint",
|
||||
"HeaderConnectionFailure": "Error de connexió",
|
||||
"HeaderConfirmRevokeApiKey": "Revoca la clau de l'API",
|
||||
"HeaderConfirmPluginInstallation": "Confirmar la instal·lació de plugins",
|
||||
"HeaderConfigureRemoteAccess": "Configurar accés remot",
|
||||
"HeaderCodecProfileHelp": "Els perfils de codecs indiquen les limitacions d’un dispositiu quan es reprodueixen codecs específics. Si s'aplica una limitació, el material es transcodificarà, fins i tot si el còdec està configurat per a la reproducció directa.",
|
||||
"HeaderChapterImages": "Imatges del capítol",
|
||||
"HeaderChannelAccess": "Accés al canal",
|
||||
"HeaderBlockItemsWithNoRating": "Bloqueja els elements sense informació de classificació o no reconeguda:",
|
||||
"HeaderAutoDiscovery": "Descobriment de la xarxa",
|
||||
"HeaderAudioBooks": "Llibres d’àudio",
|
||||
"HeaderAppearsOn": "Apareix a",
|
||||
"HeaderApp": "App",
|
||||
"HeaderAllowMediaDeletionFrom": "Permetre la supressió de mitjans des de",
|
||||
"HeaderAlert": "Alerta",
|
||||
"HeaderAddUser": "Afegir usuari",
|
||||
"HeaderAddUpdateSubtitle": "Afegir/ Actualitzar subtítols",
|
||||
"H264CrfHelp": "El factor de velocitat constant (CRF) és el valor de qualitat predeterminat per als codificadors x264 i x265. Podeu definir els valors entre 0 i 51, on els valors més baixos donarien com a resultat una millor qualitat (a costa de mides de fitxer més altes). Els valors correctes oscil·len entre 18 i 28. El valor predeterminat per a x264 és 23 i per a x265 és 28, de manera que podeu utilitzar-lo com a punt de partida.",
|
||||
"GuideProviderSelectListings": "Seleccionar Llistats",
|
||||
"GroupVersions": "Grups de versions",
|
||||
"Framerate": "Framerate",
|
||||
"Filter": "Filtre",
|
||||
"FFmpegSavePathNotFound": "No podem localitzar FFmpeg mitjançant el camí que heu introduït. FFprobe també és obligatori i ha d’existir a la mateixa carpeta. Aquests components normalment s’agrupen en la mateixa descàrrega. Comproveu el camí i torneu-ho a provar.",
|
||||
"ExtractChapterImagesHelp": "L'extracció d'imatges de capítols permetrà als clients mostrar menús gràfics de selecció d'escena. El procés pot ser lent, intensiu en recursos i pot requerir diversos gigabytes d’espai. S’executa quan es descobreixen els vídeos i també com una tasca programada cada nit. La programació es pot configurar a l'àrea de tasques programades. No es recomana executar aquesta tasca durant les hores màximes d'ús.",
|
||||
"EveryXMinutes": "Cada {0} minuts",
|
||||
"EveryXHours": "Cada {0} hores",
|
||||
"EveryHour": "Cada hora",
|
||||
"EnableTonemapping": "Activa l'assignació de tons",
|
||||
"DisableCustomCss": "Desactiveu el CSS personalitzat proporcionat pel servidor",
|
||||
"Depressed": "Deprimit"
|
||||
}
|
||||
|
|
|
@ -1518,5 +1518,8 @@
|
|||
"LabelSlowResponseTime": "Čas v milisekundách, nad který je odezva považována za pomalou",
|
||||
"LabelSlowResponseEnabled": "Zaznamenat upozornění, pokud je odezva serveru pomalá",
|
||||
"UseEpisodeImagesInNextUpHelp": "Sekce Další a Pokračovat ve sledování použijí obrázky dílů jako náhledy místo primárního náhledu seriálů.",
|
||||
"UseEpisodeImagesInNextUp": "Použít obrázky dílů v sekcích Další a Pokračovat ve sledování"
|
||||
"UseEpisodeImagesInNextUp": "Použít obrázky dílů v sekcích Další a Pokračovat ve sledování",
|
||||
"LabelLocalCustomCss": "Úprava vzhledu prostřednictvím CSS, která se vztahuje pouze na tento klient. Možná bude potřeba vypnout CSS nabízené serverem.",
|
||||
"LabelDisableCustomCss": "Vypnout úpravy vzhledu prostřednictvím CSS nabízené serverem.",
|
||||
"DisableCustomCss": "Vypnout CSS nabízené serverem"
|
||||
}
|
||||
|
|
|
@ -1498,5 +1498,18 @@
|
|||
"MediaInfoColorTransfer": "Farveoverførsel",
|
||||
"MediaInfoColorSpace": "Farveområde",
|
||||
"MediaInfoColorPrimaries": "Primærfarver",
|
||||
"HeaderContinueReading": "Fortsæt med at læse"
|
||||
"HeaderContinueReading": "Fortsæt med at læse",
|
||||
"TonemappingAlgorithmHelp": "Tone-kortlægningen kan blive fin-justeret. Hvis du ikke er bekendt med disse muligheder, så lad dem være. Den anbefalet værdi er Hable.",
|
||||
"TextSent": "Tekst sendt.",
|
||||
"MessageSent": "Besked sendt.",
|
||||
"LabelTonemappingThreshold": "Tone-kortlægning tærskel grænse:",
|
||||
"LabelTonemappingRange": "Tone-kortlægnings rækkevidde:",
|
||||
"LabelTonemappingPeakHelp": "Bestem signal/nominel/reference spids med denne værdi. Brugbar når den indskrevne spids information i metadataen er upålidelig eller når tone kortlægning fra lave til store værdier. Den anbefalet- og standardværdi er 100 og 0.",
|
||||
"LabelTonemappingPeak": "Tone-kortlægningsspids:",
|
||||
"LabelTonemappingParamHelp": "Indstil tone-kortlægning algoritmen. Den anbefalet- og standardværdi er NaN. Som regel skal den stå tom.",
|
||||
"LabelSlowResponseTime": "Tid i millisekunder indtil en respons er betragtet som langsom",
|
||||
"LabelSlowResponseEnabled": "Log advarsler hvis server respons er langsom",
|
||||
"LabelLocalCustomCss": "Tilpasset CSS stil som kun bliver anvendt på denne klient. Overvej at slå tilpasset server CSS fra.",
|
||||
"LabelDisableCustomCss": "Slå tilpasset CSS temaer/branding forsynet fra serveren fra.",
|
||||
"DisableCustomCss": "Slå Server-Forsynet Tilpasset CSS fra"
|
||||
}
|
||||
|
|
|
@ -1518,5 +1518,8 @@
|
|||
"LabelSlowResponseEnabled": "Warnung loggen, falls die Serverantwort langsam war",
|
||||
"LabelSlowResponseTime": "Zeit in ms, nachdem eine Antwort als langsam eingestuft wird",
|
||||
"UseEpisodeImagesInNextUpHelp": "Die Abschnitte \"Als Nächstes\" und \"Weiterschauen\" verwenden Episodenbilder als Vorschaubilder anstelle des primären Vorschaubilds der Sendung.",
|
||||
"UseEpisodeImagesInNextUp": "Verwenden Sie Episodenbilder in den Bereichen \"Als Nächstes\" und \"Weiterschauen\""
|
||||
"UseEpisodeImagesInNextUp": "Verwenden Sie Episodenbilder in den Bereichen \"Als Nächstes\" und \"Weiterschauen\"",
|
||||
"LabelLocalCustomCss": "Benutzerdefiniertes CSS-Styling, das nur für diesen Client gilt. Möglicherweise möchten Sie das benutzerdefinierte CSS des Servers deaktivieren.",
|
||||
"LabelDisableCustomCss": "Vom Server bereitgestelltes benutzerdefiniertes CSS-Theme/Branding deaktivieren.",
|
||||
"DisableCustomCss": "Vom Server bereitgestelltes benutzerdefiniertes CSS deaktivieren"
|
||||
}
|
||||
|
|
|
@ -1519,5 +1519,23 @@
|
|||
"AllowVppTonemappingHelp": "Full hardware based tone mapping without using OpenCL filter. Currently works only when transcoding videos with embedded HDR10 metadata.",
|
||||
"Controls": "Controls",
|
||||
"LabelEnableGamepad": "Enable Gamepad",
|
||||
"EnableGamepadHelp": "Listen for input from any connected controllers."
|
||||
"EnableGamepadHelp": "Listen for input from any connected controllers.",
|
||||
"AudioCodecNotSupported": "The audio codec is not supported",
|
||||
"ContainerNotSupported": "The container is not supported",
|
||||
"SubtitleCodecNotSupported": "The subtitle codec is not supported",
|
||||
"VideoCodecNotSupported": "The video codec is not supported",
|
||||
"AudioBitrateNotSupported": "The audio's bitrate is not supported",
|
||||
"AudioChannelsNotSupported": "The number of audio channels is not supported",
|
||||
"VideoResolutionNotSupported": "The video's resolution is not supported",
|
||||
"AudioProfileNotSupported": "The audio codec's profile is not supported",
|
||||
"AudioSampleRateNotSupported": "The audio's sample rate is not supported",
|
||||
"AnamorphicVideoNotSupported": "Anamorphic video is not supported",
|
||||
"InterlacedVideoNotSupported": "Interlaced video is not supported",
|
||||
"SecondaryAudioNotSupported": "Secondary audio tracks are not supported",
|
||||
"RefFramesNotSupported": "Reference frames are not supported",
|
||||
"VideoBitDepthNotSupported": "The video's bit depth is not supported",
|
||||
"VideoFramerateNotSupported": "The video's framerate is not supported",
|
||||
"VideoLevelNotSupported": "The video codec's level is not supported",
|
||||
"VideoProfileNotSupported": "The video codec's profile is not supported",
|
||||
"AudioBitDepthNotSupported": "The audio's bit depth is not supported"
|
||||
}
|
||||
|
|
|
@ -949,7 +949,7 @@
|
|||
"Share": "Compartir",
|
||||
"ShowAdvancedSettings": "Mostrar opciones avanzadas",
|
||||
"ShowIndicatorsFor": "Mostrar indicaciones para:",
|
||||
"Shows": "Series de Televisión",
|
||||
"Shows": "Series",
|
||||
"Shuffle": "Mezclar",
|
||||
"SimultaneousConnectionLimitHelp": "Número máximo de transmisiones simultáneas permitidas. Pon 0 para no tener límite.",
|
||||
"SkipEpisodesAlreadyInMyLibrary": "No grabar episodios que ya están en mi biblioteca",
|
||||
|
@ -1304,9 +1304,9 @@
|
|||
"MessageSyncPlayGroupDoesNotExist": "No se pudo unir al grupo porque no existe.",
|
||||
"MessageSyncPlayPlaybackPermissionRequired": "Requiere permiso para reproducir.",
|
||||
"MessageSyncPlayNoGroupsAvailable": "No hay grupos disponibles. Reproduce algo primero.",
|
||||
"MessageSyncPlayGroupWait": "<b>{0}</b> se está cargando…",
|
||||
"MessageSyncPlayUserLeft": "<b>{0}</b> abandonó el grupo.",
|
||||
"MessageSyncPlayUserJoined": "<b>{0}</b> se ha unido al grupo.",
|
||||
"MessageSyncPlayGroupWait": "{0} se está cargando…",
|
||||
"MessageSyncPlayUserLeft": "{0} abandonó el grupo.",
|
||||
"MessageSyncPlayUserJoined": "{0} se ha unido al grupo.",
|
||||
"MessageSyncPlayDisabled": "SyncPlay inactivo.",
|
||||
"MessageSyncPlayEnabled": "SyncPlay activo.",
|
||||
"LabelSyncPlayAccess": "Acceso a SyncPlay",
|
||||
|
@ -1509,5 +1509,9 @@
|
|||
"EnablePlugin": "Habilitar",
|
||||
"Framerate": "Tasa de cuadros",
|
||||
"DirectPlayHelp": "El archivo origen es totalmente compatible con este cliente, y la sesión está recibiendo el archivo sin modificaciones.",
|
||||
"HeaderContinueReading": "Continuar Leyendo"
|
||||
"HeaderContinueReading": "Continuar Leyendo",
|
||||
"LabelEnableGamepad": "Habilitad Mando",
|
||||
"Controls": "Controles",
|
||||
"TextSent": "Texto enviado.",
|
||||
"MessageSent": "Mensaje enviado."
|
||||
}
|
||||
|
|
|
@ -1518,5 +1518,8 @@
|
|||
"LabelSlowResponseTime": "Tiempo en ms después de lo cual una respuesta es considerada lenta",
|
||||
"LabelSlowResponseEnabled": "Log de alarma si la respuesta del servidor fue lenta",
|
||||
"UseEpisodeImagesInNextUpHelp": "Las secciones Siguiente y Continuar viendo utilizaran imagenes del episodio como miniaturas en lugar de miniaturas del show.",
|
||||
"UseEpisodeImagesInNextUp": "Usar imágenes de los episodios en \"Siguiente\" y \"Continuar Viendo\""
|
||||
"UseEpisodeImagesInNextUp": "Usar imágenes de los episodios en \"Siguiente\" y \"Continuar Viendo\"",
|
||||
"LabelLocalCustomCss": "El CSS personalizado aplica solo a este cliente. Puede quieras deshabilitar el CSS del servidor.",
|
||||
"LabelDisableCustomCss": "Deshabilitar CSS personalizado de tema/marca del servidor.",
|
||||
"DisableCustomCss": "Deshabilitar CSS del servidor"
|
||||
}
|
||||
|
|
|
@ -602,7 +602,7 @@
|
|||
"LabelAllowedRemoteAddressesMode": "Type de filtre des adresses IP distantes :",
|
||||
"LabelAllowedRemoteAddresses": "Filtre d'adresse IP distante :",
|
||||
"LabelAbortedByServerShutdown": "(Annulé par l'arrêt du serveur)",
|
||||
"KnownProxiesHelp": "Liste séparée par des virgules d'adresses IP des proxies connus utilisés pour se connecter à l'instance Jellyfin. Ceci est nécessaire afin de pouvoir utiliser correctement les entêtes X-Forwarded-For. Nécessite un redémarrage après sauvegarde.",
|
||||
"KnownProxiesHelp": "Liste séparée par des virgules d'adresses IP ou de noms de domaine des proxies connus utilisés pour se connecter à l'instance Jellyfin. Ceci est nécessaire afin de pouvoir utiliser correctement les entêtes X-Forwarded-For. Nécessite un redémarrage après sauvegarde.",
|
||||
"LabelDropShadow": "Ombre portée :",
|
||||
"Raised": "Élevé",
|
||||
"TabRepositories": "Référentiels",
|
||||
|
@ -706,5 +706,9 @@
|
|||
"Subtitle": "Sous-titres",
|
||||
"Studios": "Studios",
|
||||
"StopRecording": "Arrêter d'enregistrer",
|
||||
"Sports": "Sports"
|
||||
"Sports": "Sports",
|
||||
"LabelEmbedAlbumArtDidl": "Intégrer la couverture d'album dans le Didl",
|
||||
"DisableCustomCss": "Désactiver le CSS personnalisé fourni par le serveur",
|
||||
"LabelDisableCustomCss": "Désactiver le thème CSS personnalisé/l'image de marque fournie par le serveur.",
|
||||
"HeaderContinueReading": "Continuer à lire"
|
||||
}
|
||||
|
|
|
@ -1518,5 +1518,8 @@
|
|||
"LabelSlowResponseTime": "Az az idő ms-ban, amely után a válasz lassúnak tekinthető",
|
||||
"LabelSlowResponseEnabled": "Naplófigyelmeztetés, ha a szerver válasza lassú volt",
|
||||
"UseEpisodeImagesInNextUpHelp": "A Következő rész és a Nézés folytatása szakaszok epizódképeket használnak indexképként a műsor elsődleges miniatűrje helyett.",
|
||||
"UseEpisodeImagesInNextUp": "Használjon epizódképeket a Következő rész és a Epizód folytatása szekciókban"
|
||||
"UseEpisodeImagesInNextUp": "Használjon epizódképeket a Következő rész és a Epizód folytatása szekciókban",
|
||||
"LabelLocalCustomCss": "Egyedi CSS stílus, amely csak erre az ügyfélre vonatkozik. Érdemes letiltani a szerver egyéni CSS -t.",
|
||||
"LabelDisableCustomCss": "Tiltsa le a szerverről biztosított egyéni CSS -tematizálást/márkázást.",
|
||||
"DisableCustomCss": "A szerver által biztosított egyéni CSS letiltása"
|
||||
}
|
||||
|
|
|
@ -198,7 +198,7 @@
|
|||
"Fullscreen": "Schermo Intero",
|
||||
"Genre": "Genere",
|
||||
"Genres": "Generi",
|
||||
"GroupBySeries": "Raggruppa per serie",
|
||||
"GroupBySeries": "Raggruppa per Serie TV",
|
||||
"GroupVersions": "Raggruppa versioni",
|
||||
"GuestStar": "Personaggio famoso",
|
||||
"Guide": "Guida",
|
||||
|
@ -543,7 +543,7 @@
|
|||
"LabelMaxChromecastBitrate": "Qualità streaming su Chromecast:",
|
||||
"LabelMaxParentalRating": "Massima classificazione per genitori consentita:",
|
||||
"LabelMaxResumePercentage": "Percentuale massima per la ripresa:",
|
||||
"LabelMaxResumePercentageHelp": "I film sono considerati visti se fermati dopo questo tempo.",
|
||||
"LabelMaxResumePercentageHelp": "I film sono considerati visti se riprodotti dopo questo tempo.",
|
||||
"LabelMaxScreenshotsPerItem": "Massimo numero di foto per oggetto:",
|
||||
"LabelMaxStreamingBitrate": "Massima qualità streaming:",
|
||||
"LabelMaxStreamingBitrateHelp": "Specifica il bitrate massimo per lo streaming.",
|
||||
|
@ -562,7 +562,7 @@
|
|||
"LabelMinResumeDuration": "Durata minima per il riprendi:",
|
||||
"LabelMinResumeDurationHelp": "La durata video più corta in secondi che salverà la locazione di riproduzione e ti permetterà di riprendere.",
|
||||
"LabelMinResumePercentage": "Percentuale minima per il riprendi:",
|
||||
"LabelMinResumePercentageHelp": "I film sono considerati non visti se fermati prima di questo tempo.",
|
||||
"LabelMinResumePercentageHelp": "I film sono considerati non visti se interrotti prima di questo tempo.",
|
||||
"LabelMinScreenshotDownloadWidth": "Larghezza minima screenshot scaricati:",
|
||||
"LabelModelDescription": "Descrizione Modello",
|
||||
"LabelModelName": "Nome Modello",
|
||||
|
@ -583,7 +583,7 @@
|
|||
"LabelNotificationEnabled": "Abilita questa notifica",
|
||||
"LabelNumber": "Numero:",
|
||||
"LabelNumberOfGuideDays": "Numero di giorni per i quali scaricare i dati della guida:",
|
||||
"LabelNumberOfGuideDaysHelp": "Scaricando più giorni si avrà la possibilità di pianificare in anticipo più programmi e vedere più liste, ma il tempo di download si allungherà. 'Auto': MB sceglierà automaticamente in base al numero di canali.",
|
||||
"LabelNumberOfGuideDaysHelp": "Scaricando più giorni si avrà la possibilità di pianificare in anticipo più programmi e vedere più liste, ma il tempo di download sarà più lungo. 'Auto' sceglierà automaticamente in base al numero di canali.",
|
||||
"LabelOptionalNetworkPath": "Cartella di rete condivisa:",
|
||||
"LabelOptionalNetworkPathHelp": "Se questa cartella è condivisa sulla rete, fornendo il percorso di condivisione di rete si può consentire ai client su altri dispositivi di accedere direttamente ai file multimediali. Ad esempio {0} oppure {1}.",
|
||||
"LabelOriginalAspectRatio": "Aspetto originale:",
|
||||
|
@ -759,7 +759,7 @@
|
|||
"MessageItemsAdded": "Elementi aggiunti.",
|
||||
"MessageLeaveEmptyToInherit": "Lascia vuoto per ereditare le impostazioni dall'elemento principale o il valore predefinito globale.",
|
||||
"MessageNoAvailablePlugins": "Nessun plugin disponibile.",
|
||||
"MessageNoMovieSuggestionsAvailable": "Nessun suggerimento di film attualmente disponibile. Iniziare a guardare e valutare i vostri film, e poi tornare per i suggerimenti.",
|
||||
"MessageNoMovieSuggestionsAvailable": "Nessun suggerimento di film attualmente disponibile. Inizia a guardare e valutare i tuoi film, e poi tornare per i suggerimenti.",
|
||||
"MessageNoPluginsInstalled": "Non hai plugin installati.",
|
||||
"MessageNoTrailersFound": "Installa il canale dei trailer per migliorare la tua esperienza cinematografica aggiungendo una libreria di trailer da internet.",
|
||||
"MessageNothingHere": "Non c'è niente qui.",
|
||||
|
@ -797,7 +797,7 @@
|
|||
"News": "Notizie",
|
||||
"Next": "Prossimo",
|
||||
"NoNewDevicesFound": "Non sono stati trovati nuovi dispositivi. Per aggiungere un nuovo sintonizzatore, chiudere questa finestra di dialogo e immettere manualmente le informazioni sul dispositivo.",
|
||||
"MessageNoNextUpItems": "Trovato niente. Inizia a guardare i tuoi programmi!",
|
||||
"MessageNoNextUpItems": "Non è stato trovato nulla. Inizia a guardare le tue serie tv!",
|
||||
"MessageNoPluginConfiguration": "Questo Plugin non ha impostazioni da configurare.",
|
||||
"NoSubtitleSearchResultsFound": "Nessun risultato.",
|
||||
"NoSubtitlesHelp": "I sottotitoli non verranno caricati per impostazione predefinita.Possono essere ancora caricati manualmente durante la riproduzione.",
|
||||
|
@ -826,8 +826,8 @@
|
|||
"OptionAllowUserToManageServer": "Consenti a questo utente di accedere alle impostazioni del server",
|
||||
"OptionAllowVideoPlaybackRemuxing": "Consenti la riproduzione di video che necessitano di conversione ma non di ricodifica",
|
||||
"OptionAllowVideoPlaybackTranscoding": "Abilita la riproduzione di video che necessita di transcodifica",
|
||||
"OptionAutomaticallyGroupSeries": "Fondi automaticamente le serie sparse su più cartelle",
|
||||
"OptionAutomaticallyGroupSeriesHelp": "Le Serie TV distribuite su più cartelle di questa libreria saranno automaticamente combinate in un'unica Serie TV.",
|
||||
"OptionAutomaticallyGroupSeries": "Unisci automaticamente le Serie TV sparse su più cartelle",
|
||||
"OptionAutomaticallyGroupSeriesHelp": "Le Serie TV distribuite su più cartelle di questa libreria saranno automaticamente unite in un'unica Serie TV.",
|
||||
"OptionCommunityRating": "Voto del pubblico",
|
||||
"OptionCriticRating": "Voto della critica",
|
||||
"OptionCustomUsers": "Personalizza",
|
||||
|
@ -997,7 +997,7 @@
|
|||
"ShowIndicatorsFor": "Mostra indicatori per:",
|
||||
"ShowTitle": "Mostra titolo",
|
||||
"ShowYear": "Mostra anno",
|
||||
"Shows": "Programmi",
|
||||
"Shows": "Serie TV",
|
||||
"Shuffle": "Casuale",
|
||||
"SimultaneousConnectionLimitHelp": "Numero massimo di streaming simultanei permessi. Inserisci 0 per nessun limite.",
|
||||
"SkipEpisodesAlreadyInMyLibrary": "Non registrare gli espisodi che sono già in libreria",
|
||||
|
@ -1096,7 +1096,7 @@
|
|||
"Writer": "Scrittore",
|
||||
"XmlDocumentAttributeListHelp": "Questi attributi vengono applicati all'elemento radice di ogni risposta XML.",
|
||||
"XmlTvKidsCategoriesHelp": "I programmi con queste categorie saranno visualizzati come programmi per i bambini. Separa multipli con '|'.",
|
||||
"XmlTvMovieCategoriesHelp": "I programmi con queste categorie saranno visualizzati come filmati. Separa multipli con '|'.",
|
||||
"XmlTvMovieCategoriesHelp": "I programmi con queste categorie saranno visualizzati come film. Separa multipli con '|'.",
|
||||
"XmlTvNewsCategoriesHelp": "I programmi con queste categorie saranno visualizzati come programmi di news. Separa multipli con '|'.",
|
||||
"XmlTvPathHelp": "Un percorso di un file XMLTV. Jellyfin leggerà questo file e controlla periodicamente per gli aggiornamenti. Sei responsabile della creazione e dell'aggiornamento del file.",
|
||||
"XmlTvSportsCategoriesHelp": "I programmi con queste categorie saranno visualizzati come programmi sportivi. Separa multipli con '|'.",
|
||||
|
@ -1518,5 +1518,8 @@
|
|||
"UseEpisodeImagesInNextUpHelp": "Le sezioni Prossimo e Continua a guardare useranno le immagini dell'episodio come miniature al posto della miniatura principale dello spettacolo.",
|
||||
"UseEpisodeImagesInNextUp": "Usa le immagini dell'episodio nelle sezioni Prossimo e Continua a guardare",
|
||||
"LabelSlowResponseTime": "Tempo in ms dopo il quale una risposta è considerata lenta",
|
||||
"LabelSlowResponseEnabled": "Logga un avviso se la risposta del server è troppo lenta"
|
||||
"LabelSlowResponseEnabled": "Logga un avviso se la risposta del server è troppo lenta",
|
||||
"DisableCustomCss": "Disattiva il CSS Personalizzato Fornito dal Server",
|
||||
"LabelLocalCustomCss": "Stile CSS personalizzato che si applica solo a questo client. Potresti voler disabilitare il CSS personalizzato del server.",
|
||||
"LabelDisableCustomCss": "Disattiva il CSS personalizzato per i temi/branding fornito dal server."
|
||||
}
|
||||
|
|
|
@ -1519,5 +1519,8 @@
|
|||
"LabelSlowResponseTime": "Jauap baiau bolyp sanalatyn uaqyt, ms",
|
||||
"LabelSlowResponseEnabled": "Server jauaby baiau bolğan jağdaida jurnalğa eskertu jazu",
|
||||
"UseEpisodeImagesInNextUpHelp": "Kezektı jäne Qaraudy jalğastyru bölımınderınde telebölım suretterı körsetımnıñ negızgı surettıñ ornyna nobai retınde paidalanylady.",
|
||||
"UseEpisodeImagesInNextUp": "Telebölım suretterın Kezektı jäne Qaraudy jalğastyru bölımderınde paidalanu"
|
||||
"UseEpisodeImagesInNextUp": "Telebölım suretterın Kezektı jäne Qaraudy jalğastyru bölımderınde paidalanu",
|
||||
"LabelLocalCustomCss": "Tek osy tūtynğyşta qoldanılatın teñşeulı CSS. Serverde teñşeulı CSS öşıruiñız mümkın.",
|
||||
"LabelDisableCustomCss": "Serverden jetkızıletın taqyryptyq/brendiñtık teñşeulı CSS öşıru.",
|
||||
"DisableCustomCss": "Serverde teñşeulı CSS öşıru"
|
||||
}
|
||||
|
|
|
@ -801,7 +801,7 @@
|
|||
"Disconnect": "Atvienot",
|
||||
"DirectStreamHelp2": "Tiešās straumēšanas patērētā jauda ir pārsvarā atkarīga no audio profila. Tikai video straume ir bezzuduma.",
|
||||
"DirectStreamHelp1": "Video avots ir saderīgs ar šo ierīci, bet tam ir nesaderīgs audio formāts (DTS, TRUEHD utt.) vai audio kanālu skaits. Video tiks pārpakots bez zudumiem pirms tas tiks pārsūtīts uz ierīci. Tikai audio tiks pārkodēts.",
|
||||
"Descending": "Disltošs",
|
||||
"Descending": "Dilstošs",
|
||||
"Depressed": "Atspiests",
|
||||
"DeleteUserConfirmation": "Vai tu tiešām vēlies izdzēst šo lietotāju?",
|
||||
"DeleteUser": "Dzēst Lietotāju",
|
||||
|
@ -1070,5 +1070,24 @@
|
|||
"EnableDetailsBanner": "Informācijas reklāmkarogs",
|
||||
"ButtonPlayer": "Atskaņotājs",
|
||||
"ButtonCast": "Raidīt",
|
||||
"AllowTonemappingHelp": "Toņu kartēšana var pārveidot video dinamisko diapazonu no HDR uz SDR, saglabājot attēla detaļas un krāsas, kas ir ļoti svarīga informācija, lai attēlotu sākotnējo ainu. Pašlaik strādā tikai, kad tiek pārkodēti video ar iegultiem HDR10 vai HLG metadatiem. Ja atskaņošana nav vienmērīga vai tā neizdotas, lūdzu, apsveriet atbilstošā aparatūras dekodētāja izslēģsanu."
|
||||
"AllowTonemappingHelp": "Toņu kartēšana var pārveidot video dinamisko diapazonu no HDR uz SDR, saglabājot attēla detaļas un krāsas, kas ir ļoti svarīga informācija, lai attēlotu sākotnējo ainu. Pašlaik strādā tikai, kad tiek pārkodēti video ar iegultiem HDR10 vai HLG metadatiem. Ja atskaņošana nav vienmērīga vai tā neizdotas, lūdzu, apsveriet atbilstošā aparatūras dekodētāja izslēģsanu.",
|
||||
"LabelChromecastVersion": "Chromecast Versija",
|
||||
"HeaderUploadSubtitle": "Augšupielādēt Subtitrus",
|
||||
"HeaderRemoteAccessSettings": "Attālinātas Pieejas Iestatījumi",
|
||||
"HeaderPortRanges": "Ugunsmūra un Starpniekservera Iestatījumi",
|
||||
"HeaderNewRepository": "Jauna Krātuve",
|
||||
"HeaderNetworking": "IP Protokoli",
|
||||
"HeaderHttpsSettings": "HTTPS Iestatījumi",
|
||||
"HeaderDeleteDevices": "Izdzēst Visas Ierīces",
|
||||
"HeaderDebugging": "Atkļūdošana un problēmu izsekošana",
|
||||
"HeaderContinueReading": "Turpināt lasīt",
|
||||
"HeaderAddUser": "Pievienot Lietotāju",
|
||||
"HeaderAddUpdateSubtitle": "Pievienot/Atjaunot Subtitrus",
|
||||
"Framerate": "Kadri sekundē",
|
||||
"FastForward": "Ātri uz priekšu",
|
||||
"Extras": "Ekstras",
|
||||
"DisablePlugin": "Izslēgt",
|
||||
"DisableCustomCss": "Izslēgt servera definēto CSS",
|
||||
"EnablePlugin": "Ieslēgt",
|
||||
"MusicVideos": "Mūzikas video"
|
||||
}
|
||||
|
|
|
@ -1514,5 +1514,8 @@
|
|||
"LabelSlowResponseTime": "മില്ലിസെക്കൻഡിൽ സമയം മന്ദഗതിയിൽ കണക്കാക്കുന്നു",
|
||||
"LabelSlowResponseEnabled": "സെർവർ പ്രതികരണം മന്ദഗതിയിലാണെങ്കിൽ ലോഗ് മുന്നറിയിപ്പ്",
|
||||
"UseEpisodeImagesInNextUpHelp": "ഷോയുടെ പ്രാഥമിക ലഘുചിത്രത്തിനുപകരം അടുത്തതും തുടർന്നും കാണൽ വിഭാഗങ്ങൾ എപ്പിസോഡ് ഇമേജുകൾ ലഘുചിത്രങ്ങളായി ഉപയോഗിക്കും.",
|
||||
"UseEpisodeImagesInNextUp": "അടുത്തതിലേക്ക് എപ്പിസോഡ് ഇമേജുകൾ ഉപയോഗിക്കുക, കാണുന്നത് തുടരുക വിഭാഗങ്ങൾ"
|
||||
"UseEpisodeImagesInNextUp": "അടുത്തതിലേക്ക് എപ്പിസോഡ് ഇമേജുകൾ ഉപയോഗിക്കുക, കാണുന്നത് തുടരുക വിഭാഗങ്ങൾ",
|
||||
"LabelLocalCustomCss": "ഇഷ്ടാനുസൃത CSS സ്റ്റൈലിംഗ് ഈ ക്ലയന്റിന് മാത്രം ബാധകമാണ്. സെർവർ കസ്റ്റം CSS പ്രവർത്തനരഹിതമാക്കാൻ നിങ്ങൾ ആഗ്രഹിച്ചേക്കാം.",
|
||||
"LabelDisableCustomCss": "സെർവറിൽ നിന്ന് നൽകിയ ഇച്ഛാനുസൃത CSS തീമിംഗ്/ബ്രാൻഡിംഗ് പ്രവർത്തനരഹിതമാക്കുക.",
|
||||
"DisableCustomCss": "സെർവർ നൽകുന്ന കസ്റ്റം CSS പ്രവർത്തനരഹിതമാക്കുക"
|
||||
}
|
||||
|
|
|
@ -1518,5 +1518,8 @@
|
|||
"LabelSlowResponseTime": "Время, после которого ответ считается медленным, мс",
|
||||
"LabelSlowResponseEnabled": "Записывать в журнал предупреждение, если ответ сервера был медленным",
|
||||
"UseEpisodeImagesInNextUpHelp": "В разделах «Очередное» и «Продолжить просмотр» как бегунки будут использоваться рисунки эпизодов вместо головного рисунка сериала.",
|
||||
"UseEpisodeImagesInNextUp": "Использовать рисунки эпизодов в разделах \"Очередное\" и \"Продолжить просмотр\""
|
||||
"UseEpisodeImagesInNextUp": "Использовать рисунки эпизодов в разделах \"Очередное\" и \"Продолжить просмотр\"",
|
||||
"LabelLocalCustomCss": "Настраиваемые стили CSS, применимые только к этому клиенту. Вы можете отключить настраиваемые CSS сервера.",
|
||||
"LabelDisableCustomCss": "Отключаются настраиваемые CSS для темы/брендирования, предоставляемые с сервера.",
|
||||
"DisableCustomCss": "Отключить настраиваемый CSS, предоставляемый сервером"
|
||||
}
|
||||
|
|
|
@ -1533,5 +1533,8 @@
|
|||
"LabelSlowResponseTime": "மில்லி விநாடிகளில் நேரம், அதன் பிறகு பதில் மெதுவாக கருதப்படுகிறது",
|
||||
"LabelSlowResponseEnabled": "சேவையக பதில் மெதுவாக இருந்தால் பதிவு எச்சரிக்கை",
|
||||
"UseEpisodeImagesInNextUpHelp": "அடுத்தது மற்றும் தொடர்ந்து பார்ப்பது பிரிவுகள் நிகழ்ச்சியின் முதன்மை சிறுபடத்திற்கு பதிலாக எபிசோட் படங்களை சிறுபடங்களாகப் பயன்படுத்தும்.",
|
||||
"UseEpisodeImagesInNextUp": "எபிசோட் படங்களை அடுத்த மற்றும் தொடர்ந்து பார்ப்பது பிரிவுகளில் பயன்படுத்தவும்"
|
||||
"UseEpisodeImagesInNextUp": "எபிசோட் படங்களை அடுத்த மற்றும் தொடர்ந்து பார்ப்பது பிரிவுகளில் பயன்படுத்தவும்",
|
||||
"LabelLocalCustomCss": "தனிப்பயன் CSS ஸ்டைலிங் இந்த வாடிக்கையாளருக்கு மட்டுமே பொருந்தும். நீங்கள் சேவையக தனிப்பயன் CSS ஐ முடக்க விரும்பலாம்.",
|
||||
"LabelDisableCustomCss": "சேவையகத்திலிருந்து வழங்கப்பட்ட தனிப்பயன் CSS தீமிங்/பிராண்டிங்கை முடக்கவும்.",
|
||||
"DisableCustomCss": "சேவையகம் வழங்கும் தனிப்பயன் CSS ஐ முடக்கவும்"
|
||||
}
|
||||
|
|
|
@ -187,7 +187,7 @@
|
|||
"Playlists": "Çalma listeleri",
|
||||
"Shows": "Diziler",
|
||||
"Songs": "Şarkılar",
|
||||
"Sync": "Eşitle",
|
||||
"Sync": "Eşzamanlama",
|
||||
"AllChannels": "Tüm kanallar",
|
||||
"AllComplexFormats": "Tüm karmaşık formatlar (ASS, SSA, VOBSUB, PGS, SUB/IDX, vb.)",
|
||||
"AllEpisodes": "Tüm bölümler",
|
||||
|
|
|
@ -1518,5 +1518,8 @@
|
|||
"LabelSlowResponseTime": "Thời gian tính bằng mili giây sau đó phản hồi được coi là chậm",
|
||||
"LabelSlowResponseEnabled": "Cảnh báo ghi nhật ký nếu phản hồi của máy chủ chậm",
|
||||
"UseEpisodeImagesInNextUpHelp": "Phần Tiếp theo và Xem tiếp sẽ sử dụng hình ảnh của tập làm hình thu nhỏ thay vì hình thu nhỏ chính của chương trình.",
|
||||
"UseEpisodeImagesInNextUp": "Sử dụng hình ảnh tập trong phần Tiếp theo và Xem tiếp"
|
||||
"UseEpisodeImagesInNextUp": "Sử dụng hình ảnh tập trong phần Tiếp theo và Xem tiếp",
|
||||
"LabelLocalCustomCss": "Kiểu CSS tùy chỉnh chỉ áp dụng cho máy khách này. Bạn có thể muốn tắt CSS tùy chỉnh của máy chủ.",
|
||||
"LabelDisableCustomCss": "Tắt nhãn hiệu/chủ đề CSS tùy chỉnh được cung cấp từ máy chủ.",
|
||||
"DisableCustomCss": "Tắt CSS tùy chỉnh do máy chủ cung cấp"
|
||||
}
|
||||
|
|
|
@ -1518,5 +1518,8 @@
|
|||
"LabelSlowResponseTime": "响应缓慢判断时间(单位毫秒)",
|
||||
"LabelSlowResponseEnabled": "如果服务器响应缓慢,则记录警告",
|
||||
"UseEpisodeImagesInNextUpHelp": "下一步和继续观看模块将使用剧集图像作为缩略图,而不是节目的主缩略图。",
|
||||
"UseEpisodeImagesInNextUp": "在下一步和继续观看模块中使用剧集图片"
|
||||
"UseEpisodeImagesInNextUp": "在下一步和继续观看模块中使用剧集图片",
|
||||
"LabelLocalCustomCss": "自定义 CSS 样式并仅应用于本客户端。您可能想要禁用服务器自定义 CSS。",
|
||||
"LabelDisableCustomCss": "禁用由服务器提供的自定义 CSS 主题/品牌。",
|
||||
"DisableCustomCss": "禁用服务器提供的自定义 CSS"
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ module.exports = {
|
|||
})
|
||||
],
|
||||
output: {
|
||||
filename: '[name].bundle.js',
|
||||
filename: '[name].jellyfin.bundle.js',
|
||||
chunkFilename: '[name].[contenthash].chunk.js',
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
publicPath: ''
|
||||
|
|
|
@ -12,11 +12,13 @@ module.exports = merge(common, {
|
|||
rules: [
|
||||
{
|
||||
test: /\.(js|jsx)$/,
|
||||
exclude: /node_modules/,
|
||||
enforce: 'pre',
|
||||
use: ['source-map-loader']
|
||||
},
|
||||
{
|
||||
test: /\.(ts|tsx)$/,
|
||||
exclude: /node_modules/,
|
||||
enforce: 'pre',
|
||||
use: ['source-map-loader']
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue