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 jassub

This commit is contained in:
Cas 2023-03-30 13:50:25 +02:00 committed by GitHub
commit 4c7c2067f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
116 changed files with 1269 additions and 982 deletions

View file

@ -64,7 +64,9 @@ module.exports = {
'no-var': ['error'],
'no-void': ['error', { 'allowAsStatement': true }],
'no-warning-comments': ['warn', { 'terms': ['fixme', 'hack', 'xxx'] }],
'object-curly-spacing': ['error', 'always'],
'one-var': ['error', 'never'],
'operator-linebreak': ['error', 'before', { overrides: { '?': 'after', ':': 'after', '=': 'after' } }],
'padded-blocks': ['error', 'never'],
'prefer-const': ['error', { 'destructuring': 'all' }],
'quotes': ['error', 'single', { 'avoidEscape': true, 'allowTemplateLiterals': false }],
@ -267,7 +269,6 @@ module.exports = {
'no-useless-constructor': ['off'],
'@typescript-eslint/no-useless-constructor': ['error'],
'max-params': ['error', 7],
'sonarjs/cognitive-complexity': ['warn']
}
}

View file

@ -19,13 +19,13 @@ jobs:
language: [ 'javascript' ]
steps:
- name: Checkout repository
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0
uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0
- name: Initialize CodeQL
uses: github/codeql-action/init@168b99b3c22180941ae7dbdd5f5c9678ede476ba # v2.2.7
uses: github/codeql-action/init@04df1262e6247151b5ac09cd2c303ac36ad3f62b # v2.2.9
with:
languages: ${{ matrix.language }}
queries: +security-extended
- name: Autobuild
uses: github/codeql-action/autobuild@168b99b3c22180941ae7dbdd5f5c9678ede476ba # v2.2.7
uses: github/codeql-action/autobuild@04df1262e6247151b5ac09cd2c303ac36ad3f62b # v2.2.9
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@168b99b3c22180941ae7dbdd5f5c9678ede476ba # v2.2.7
uses: github/codeql-action/analyze@04df1262e6247151b5ac09cd2c303ac36ad3f62b # v2.2.9

View file

@ -18,7 +18,7 @@ jobs:
comment-id: ${{ github.event.comment.id }}
reactions: '+1'
- name: Checkout the latest code
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0
uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0
with:
token: ${{ secrets.JF_BOT_TOKEN }}
fetch-depth: 0

View file

@ -13,7 +13,7 @@ jobs:
steps:
- name: Check out Git repository
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0
uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0
- name: Setup node environment
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
@ -37,7 +37,7 @@ jobs:
steps:
- name: Check out Git repository
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0
uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0
- name: Setup node environment
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
@ -58,7 +58,7 @@ jobs:
steps:
- name: Check out Git repository
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0
uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0
- name: Setup node environment
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
@ -82,7 +82,7 @@ jobs:
steps:
- name: Check out Git repository
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0
uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0
- name: Setup node environment
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0

View file

@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
if: ${{ contains(github.repository, 'jellyfin/') }}
steps:
- uses: actions/stale@6f05e4244c9a0b2ed3401882b05d701dd0a7289b # v7.0.0
- uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 # v8.0.0
with:
repo-token: ${{ secrets.JF_BOT_TOKEN }}
operations-per-run: 75
@ -37,7 +37,7 @@ jobs:
runs-on: ubuntu-latest
if: ${{ contains(github.repository, 'jellyfin/') }}
steps:
- uses: actions/stale@6f05e4244c9a0b2ed3401882b05d701dd0a7289b # v7.0.0
- uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 # v8.0.0
with:
repo-token: ${{ secrets.JF_BOT_TOKEN }}
operations-per-run: 75

View file

@ -13,7 +13,7 @@ jobs:
steps:
- name: Check out Git repository
uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0
uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0
- name: Setup node environment
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0

1125
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -5,8 +5,8 @@
"repository": "https://github.com/jellyfin/jellyfin-web",
"license": "GPL-2.0-or-later",
"devDependencies": {
"@babel/core": "7.21.0",
"@babel/eslint-parser": "7.19.1",
"@babel/core": "7.21.3",
"@babel/eslint-parser": "7.21.3",
"@babel/eslint-plugin": "7.19.1",
"@babel/plugin-proposal-class-properties": "7.18.6",
"@babel/plugin-proposal-private-methods": "7.18.6",
@ -16,13 +16,13 @@
"@babel/preset-typescript": "7.21.0",
"@types/escape-html": "1.0.2",
"@types/loadable__component": "5.13.4",
"@types/lodash-es": "4.17.6",
"@types/lodash-es": "4.17.7",
"@types/react": "17.0.53",
"@types/react-dom": "17.0.19",
"@typescript-eslint/eslint-plugin": "5.54.1",
"@typescript-eslint/parser": "5.54.1",
"@typescript-eslint/eslint-plugin": "5.56.0",
"@typescript-eslint/parser": "5.56.0",
"@uupaa/dynamic-import-polyfill": "1.0.2",
"autoprefixer": "10.4.13",
"autoprefixer": "10.4.14",
"babel-loader": "9.1.2",
"babel-plugin-dynamic-import-polyfill": "1.0.0",
"clean-webpack-plugin": "4.0.0",
@ -32,7 +32,7 @@
"css-loader": "6.7.3",
"cssnano": "5.1.15",
"es-check": "7.1.0",
"eslint": "8.35.0",
"eslint": "8.36.0",
"eslint-plugin-compat": "4.1.2",
"eslint-plugin-eslint-comments": "3.2.0",
"eslint-plugin-import": "2.27.5",
@ -40,29 +40,29 @@
"eslint-plugin-promise": "6.1.1",
"eslint-plugin-react": "7.32.2",
"eslint-plugin-react-hooks": "4.6.0",
"eslint-plugin-sonarjs": "0.18.0",
"expose-loader": "4.0.0",
"eslint-plugin-sonarjs": "0.19.0",
"expose-loader": "4.1.0",
"html-loader": "4.2.0",
"html-webpack-plugin": "5.5.0",
"mini-css-extract-plugin": "2.7.3",
"mini-css-extract-plugin": "2.7.5",
"postcss": "8.4.21",
"postcss-loader": "7.0.2",
"postcss-loader": "7.1.0",
"postcss-preset-env": "8.0.1",
"postcss-scss": "4.0.6",
"sass": "1.58.3",
"sass-loader": "13.2.0",
"sass": "1.59.3",
"sass-loader": "13.2.1",
"source-map-loader": "4.0.1",
"style-loader": "3.3.1",
"stylelint": "15.2.0",
"style-loader": "3.3.2",
"stylelint": "15.3.0",
"stylelint-config-rational-order": "0.1.2",
"stylelint-no-browser-hacks": "1.2.1",
"stylelint-order": "6.0.3",
"stylelint-scss": "4.4.0",
"stylelint-scss": "4.5.0",
"ts-loader": "9.4.2",
"typescript": "4.9.5",
"webpack": "5.76.0",
"typescript": "5.0.2",
"webpack": "5.76.3",
"webpack-cli": "5.0.1",
"webpack-dev-server": "4.11.1",
"webpack-dev-server": "4.13.1",
"webpack-merge": "5.8.0",
"workbox-webpack-plugin": "6.5.4",
"worker-loader": "3.0.8"
@ -79,10 +79,10 @@
"blurhash": "2.0.5",
"classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz",
"classnames": "2.3.2",
"core-js": "3.29.0",
"core-js": "3.29.1",
"date-fns": "2.29.3",
"dompurify": "3.0.1",
"epubjs": "0.4.2",
"epubjs": "0.3.93",
"escape-html": "1.0.3",
"event-target-polyfill": "github:ThaUnknown/event-target-polyfill",
"fast-text-encoding": "1.0.6",
@ -93,17 +93,17 @@
"intersection-observer": "0.12.2",
"jassub": "1.5.12",
"jellyfin-apiclient": "1.10.0",
"jquery": "3.6.3",
"jquery": "3.6.4",
"jstree": "3.3.15",
"libarchive.js": "1.3.0",
"lodash-es": "4.17.21",
"marked": "4.2.12",
"marked": "4.3.0",
"material-design-icons-iconfont": "6.7.0",
"native-promise-only": "0.8.1",
"pdfjs-dist": "2.16.105",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-router-dom": "6.8.2",
"react-router-dom": "6.9.0",
"resize-observer-polyfill": "1.5.1",
"screenfull": "6.0.2",
"sortablejs": "1.15.0",

View file

@ -366,20 +366,20 @@ export const appHost = {
};
},
deviceName: function () {
return window.NativeShell?.AppHost?.deviceName
? window.NativeShell.AppHost.deviceName() : getDeviceName();
return window.NativeShell?.AppHost?.deviceName ?
window.NativeShell.AppHost.deviceName() : getDeviceName();
},
deviceId: function () {
return window.NativeShell?.AppHost?.deviceId
? window.NativeShell.AppHost.deviceId() : getDeviceId();
return window.NativeShell?.AppHost?.deviceId ?
window.NativeShell.AppHost.deviceId() : getDeviceId();
},
appName: function () {
return window.NativeShell?.AppHost?.appName
? window.NativeShell.AppHost.appName() : appName;
return window.NativeShell?.AppHost?.appName ?
window.NativeShell.AppHost.appName() : appName;
},
appVersion: function () {
return window.NativeShell?.AppHost?.appVersion
? window.NativeShell.AppHost.appVersion() : Package.version;
return window.NativeShell?.AppHost?.appVersion ?
window.NativeShell.AppHost.appVersion() : Package.version;
},
getPushTokenInfo: function () {
return {};

View file

@ -26,8 +26,8 @@ import Events from '../utils/events.ts';
function canPlayNativeHls() {
const media = document.createElement('video');
return !!(media.canPlayType('application/x-mpegURL').replace(/no/, '') ||
media.canPlayType('application/vnd.apple.mpegURL').replace(/no/, ''));
return !!(media.canPlayType('application/x-mpegURL').replace(/no/, '')
|| media.canPlayType('application/vnd.apple.mpegURL').replace(/no/, ''));
}
export function enableHlsJsPlayer(runTimeTicks, mediaType) {
@ -201,8 +201,8 @@ import Events from '../utils/events.ts';
.catch((e) => {
const errorName = (e.name || '').toLowerCase();
// safari uses aborterror
if (errorName === 'notallowederror' ||
errorName === 'aborterror') {
if (errorName === 'notallowederror'
|| errorName === 'aborterror') {
// swallow this error because the user can still click the play button on the video element
return Promise.resolve();
}

View file

@ -25,7 +25,7 @@ import toast from '../toast/toast';
import alert from '../alert';
import template from './mediaLibraryCreator.template.html';
function onAddLibrary() {
function onAddLibrary(e) {
if (isCreating) {
return false;
}
@ -62,7 +62,7 @@ import template from './mediaLibraryCreator.template.html';
isCreating = false;
loading.hide();
});
return false;
e.preventDefault();
}
function getCollectionTypeOptionsHtml(collectionTypeOptions) {
@ -96,7 +96,7 @@ import template from './mediaLibraryCreator.template.html';
$('.collectionTypeFieldDescription', dlg).html(folderOption?.message || '');
});
page.querySelector('.btnAddFolder').addEventListener('click', onAddButtonClick);
page.querySelector('.btnSubmit').addEventListener('click', onAddLibrary);
page.querySelector('.addLibraryForm').addEventListener('submit', onAddLibrary);
page.querySelector('.folderList').addEventListener('click', onRemoveClick);
}

View file

@ -1,3 +1,4 @@
<form class="addLibraryForm" style="max-width:100%;">
<div class="formDialogHeader">
<button type="button" is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1" title="${ButtonBack}"><span class="material-icons arrow_back" aria-hidden="true"></span></button>
<h3 class="formDialogHeaderTitle">${ButtonAddMediaLibrary}</h3>
@ -31,7 +32,8 @@
</div>
<div class="formDialogFooter">
<button is="emby-button" type="button" class="raised btnSubmit button-submit block formDialogFooterItem">
<button is="emby-button" type="submit" class="raised btnSubmit button-submit block formDialogFooterItem">
<span>${ButtonOk}</span>
</button>
</div>
</form>

View file

@ -588,12 +588,12 @@ import template from './metadataEditor.template.html';
hideElement('#collapsibleSpecialEpisodeInfo', context);
}
if (item.Type === 'Person' ||
item.Type === 'Genre' ||
item.Type === 'Studio' ||
item.Type === 'MusicGenre' ||
item.Type === 'TvChannel' ||
item.Type === 'Book') {
if (item.Type === 'Person'
|| item.Type === 'Genre'
|| item.Type === 'Studio'
|| item.Type === 'MusicGenre'
|| item.Type === 'TvChannel'
|| item.Type === 'Book') {
hideElement('#peopleCollapsible', context);
} else {
showElement('#peopleCollapsible', context);

View file

@ -4,7 +4,8 @@ import Events from '../../utils/events.ts';
import layoutManager from '../layoutManager';
import { playbackManager } from '../playback/playbackmanager';
import playMethodHelper from '../playback/playmethodhelper';
import SyncPlay from '../../plugins/syncPlay/core';
import { pluginManager } from '../pluginManager';
import { PluginType } from '../../types/plugin.ts';
import './playerstats.scss';
import ServerConnections from '../ServerConnections';
@ -325,6 +326,12 @@ import ServerConnections from '../ServerConnections';
}
function getSyncPlayStats() {
const SyncPlay = pluginManager.firstOfType(PluginType.SyncPlay)?.instance;
if (!SyncPlay?.Manager.isSyncPlayEnabled()) {
return [];
}
const syncStats = [];
const stats = SyncPlay.Manager.getStats();
@ -422,10 +429,10 @@ import ServerConnections from '../ServerConnections';
name: globalize.translate('LabelOriginalMediaInfo')
});
const apiClient = ServerConnections.getApiClient(playbackManager.currentItem(player).ServerId);
if (SyncPlay.Manager.isSyncPlayEnabled() && apiClient.isMinServerVersion('10.6.0')) {
const syncPlayStats = getSyncPlayStats();
if (syncPlayStats.length > 0) {
categories.push({
stats: getSyncPlayStats(),
stats: syncPlayStats,
name: globalize.translate('LabelSyncPlayInfo')
});
}

View file

@ -4,10 +4,12 @@ import dialogHelper from '../dialogHelper/dialogHelper';
import loading from '../loading/loading';
import layoutManager from '../layoutManager';
import { playbackManager } from '../playback/playbackmanager';
import SyncPlay from '../../plugins/syncPlay/core';
import { pluginManager } from '../pluginManager';
import * as userSettings from '../../scripts/settings/userSettings';
import { appRouter } from '../appRouter';
import globalize from '../../scripts/globalize';
import { PluginType } from '../../types/plugin.ts';
import '../../elements/emby-button/emby-button';
import '../../elements/emby-input/emby-input';
import '../../elements/emby-button/paper-icon-button-light';
@ -117,10 +119,12 @@ import ServerConnections from '../ServerConnections';
};
const apiClient = ServerConnections.getApiClient(currentServerId);
const SyncPlay = pluginManager.firstOfType(PluginType.SyncPlay)?.instance;
apiClient.getItems(apiClient.getCurrentUserId(), options).then(result => {
let html = '';
if ((editorOptions.enableAddToPlayQueue !== false && playbackManager.isPlaying()) || SyncPlay.Manager.isSyncPlayEnabled()) {
if ((editorOptions.enableAddToPlayQueue !== false && playbackManager.isPlaying()) || SyncPlay?.Manager.isSyncPlayEnabled()) {
html += `<option value="queue">${globalize.translate('AddToPlayQueue')}</option>`;
}

View file

@ -119,9 +119,14 @@ class PluginManager {
}
ofType(type) {
return this.pluginsList.filter((o) => {
return o.type === type;
});
return this.pluginsList.filter(plugin => plugin.type === type);
}
firstOfType(type) {
// Get all plugins of the specified type
return this.ofType(type)
// Return the plugin with the "highest" (lowest numeric value) priority
.sort((p1, p2) => (p1.priority || 0) - (p2.priority || 0))[0];
}
#mapRoute(plugin, route) {

View file

@ -85,8 +85,8 @@ const SearchFields: FunctionComponent<SearchFieldsProps> = ({ onSearch = () => {
dangerouslySetInnerHTML={createInputElement()}
/>
</div>
{layoutManager.tv && !browser.tv &&
<AlphaPicker onAlphaPicked={onAlphaPicked} />
{layoutManager.tv && !browser.tv
&& <AlphaPicker onAlphaPicked={onAlphaPicked} />
}
</div>
);

View file

@ -94,9 +94,9 @@ function init(instance) {
subtitleSyncSlider.getBubbleHtml = function (value) {
const newOffset = getOffsetFromPercentage(value);
return '<h1 class="sliderBubbleText">' +
(newOffset > 0 ? '+' : '') + parseFloat(newOffset) + 's' +
'</h1>';
return '<h1 class="sliderBubbleText">'
+ (newOffset > 0 ? '+' : '') + parseFloat(newOffset) + 's'
+ '</h1>';
};
subtitleSyncCloseButton.addEventListener('click', function () {

View file

@ -253,6 +253,13 @@
</label>
<div class="fieldDescription checkboxFieldDescription">${EnableFallbackFontHelp}</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label>
<input is="emby-checkbox" type="checkbox" id="chkEnableAudioVbr" />
<span>${LabelEnableAudioVbr}</span>
</label>
<div class="fieldDescription checkboxFieldDescription">${LabelEnableAudioVbrHelp}</div>
</div>
<div class="inputContainer">
<input is="emby-input" type="number" id="txtDownMixAudioBoost" pattern="[0-9]*" required="required" min=".5" max="3" step=".1" label="${LabelDownMixAudioScale}" />
<div class="fieldDescription">${LabelDownMixAudioScaleHelp}</div>

View file

@ -22,6 +22,7 @@ import alert from '../../components/alert';
page.querySelector('#chkAllowHevcEncoding').checked = config.AllowHevcEncoding;
$('#selectVideoDecoder', page).val(config.HardwareAccelerationType);
$('#selectThreadCount', page).val(config.EncodingThreadCount);
page.querySelector('#chkEnableAudioVbr').checked = config.EnableAudioVbr;
$('#txtDownMixAudioBoost', page).val(config.DownMixAudioBoost);
$('#selectStereoDownmixAlgorithm').val(config.DownMixStereoAlgorithm || 'None');
page.querySelector('#txtMaxMuxingQueueSize').value = config.MaxMuxingQueueSize || '';
@ -78,6 +79,7 @@ import alert from '../../components/alert';
const onDecoderConfirmed = function () {
loading.show();
ApiClient.getNamedConfiguration('encoding').then(function (config) {
config.EnableAudioVbr = form.querySelector('#chkEnableAudioVbr').checked;
config.DownMixAudioBoost = $('#txtDownMixAudioBoost', form).val();
config.DownMixStereoAlgorithm = $('#selectStereoDownmixAlgorithm', form).val() || 'None';
config.MaxMuxingQueueSize = form.querySelector('#txtMaxMuxingQueueSize').value;

View file

@ -1,6 +1,5 @@
import escapeHtml from 'escape-html';
import { playbackManager } from '../../../components/playback/playbackmanager';
import SyncPlay from '../../../plugins/syncPlay/core';
import browser from '../../../scripts/browser';
import dom from '../../../scripts/dom';
import inputManager from '../../../scripts/inputManager';
@ -25,6 +24,8 @@ import SubtitleSync from '../../../components/subtitlesync/subtitlesync';
import { appRouter } from '../../../components/appRouter';
import LibraryMenu from '../../../scripts/libraryMenu';
import { setBackdropTransparency, TRANSPARENCY_LEVEL } from '../../../components/backdrop/backdrop';
import { pluginManager } from '../../../components/pluginManager';
import { PluginType } from '../../../types/plugin.ts';
/* eslint-disable indent */
const TICKS_PER_MINUTE = 600000000;
@ -896,8 +897,8 @@ import { setBackdropTransparency, TRANSPARENCY_LEVEL } from '../../../components
const state = playbackManager.getPlayerState(player);
// show subtitle offset feature only if player and media support it
const showSubOffset = playbackManager.supportSubtitleOffset(player) &&
playbackManager.canHandleOffsetOnCurrentSubtitle(player);
const showSubOffset = playbackManager.supportSubtitleOffset(player)
&& playbackManager.canHandleOffsetOnCurrentSubtitle(player);
playerSettingsMenu.show({
mediaType: 'Video',
@ -1774,20 +1775,20 @@ import { setBackdropTransparency, TRANSPARENCY_LEVEL } from '../../../components
}, iconVisibilityTime);
};
Events.on(SyncPlay.Manager, 'enabled', (event, enabled) => {
if (enabled) {
// SyncPlay enabled
} else {
const SyncPlay = pluginManager.firstOfType(PluginType.SyncPlay)?.instance;
if (SyncPlay) {
Events.on(SyncPlay.Manager, 'enabled', (_event, enabled) => {
if (!enabled) {
const syncPlayIcon = view.querySelector('#syncPlayIcon');
syncPlayIcon.style.visibility = 'hidden';
}
});
Events.on(SyncPlay.Manager, 'notify-osd', (event, action) => {
Events.on(SyncPlay.Manager, 'notify-osd', (_event, action) => {
showIcon(action);
});
Events.on(SyncPlay.Manager, 'group-state-update', (event, state, reason) => {
Events.on(SyncPlay.Manager, 'group-state-update', (_event, state, reason) => {
if (state === 'Playing' && reason === 'Unpause') {
showIcon('schedule-play');
} else if (state === 'Playing' && reason === 'Ready') {
@ -1807,5 +1808,6 @@ import { setBackdropTransparency, TRANSPARENCY_LEVEL } from '../../../components
}
});
}
}
/* eslint-enable indent */

View file

@ -229,8 +229,8 @@ const Scroller: FC<ScrollerProps> = ({
return (
<>
{
showControls && scrollState.scrollWidth > scrollState.scrollSize + 20 &&
<ScrollButtons
showControls && scrollState.scrollWidth > scrollState.scrollSize + 20
&& <ScrollButtons
scrollRef={scrollRef}
scrollerFactoryRef={scrollerFactoryRef}
scrollState={scrollState}

View file

@ -17,15 +17,31 @@ import '../../elements/emby-button/paper-icon-button-light';
import html from './template.html';
import './style.scss';
const THEMES = {
'dark': { 'body': { 'color': '#d8dadc', 'background': '#000', 'font-size': 'medium' } },
'sepia': { 'body': { 'color': '#d8a262', 'background': '#000', 'font-size': 'medium' } },
'light': { 'body': { 'color': '#000', 'background': '#fff', 'font-size': 'medium' } }
};
const THEME_ORDER = ['dark', 'sepia', 'light'];
const FONT_SIZES = ['x-small', 'small', 'medium', 'large', 'x-large'];
export class BookPlayer {
constructor() {
this.name = 'Book Player';
this.type = PluginType.MediaPlayer;
this.id = 'bookplayer';
this.priority = 1;
if (!userSettings.theme() || userSettings.theme() === 'dark') {
this.theme = 'dark';
} else {
this.theme = 'light';
}
this.fontSize = 'medium';
this.onDialogClosed = this.onDialogClosed.bind(this);
this.openTableOfContents = this.openTableOfContents.bind(this);
this.rotateTheme = this.rotateTheme.bind(this);
this.increaseFontSize = this.increaseFontSize.bind(this);
this.decreaseFontSize = this.decreaseFontSize.bind(this);
this.previous = this.previous.bind(this);
this.next = this.next.bind(this);
this.onWindowKeyUp = this.onWindowKeyUp.bind(this);
@ -164,6 +180,9 @@ export class BookPlayer {
elem.querySelector('#btnBookplayerExit').addEventListener('click', this.onDialogClosed, { once: true });
elem.querySelector('#btnBookplayerToc').addEventListener('click', this.openTableOfContents);
elem.querySelector('#btnBookplayerFullscreen').addEventListener('click', this.toggleFullscreen);
elem.querySelector('#btnBookplayerRotateTheme').addEventListener('click', this.rotateTheme);
elem.querySelector('#btnBookplayerIncreaseFontSize').addEventListener('click', this.increaseFontSize);
elem.querySelector('#btnBookplayerDecreaseFontSize').addEventListener('click', this.decreaseFontSize);
elem.querySelector('#btnBookplayerPrev')?.addEventListener('click', this.previous);
elem.querySelector('#btnBookplayerNext')?.addEventListener('click', this.next);
}
@ -184,6 +203,9 @@ export class BookPlayer {
elem.querySelector('#btnBookplayerExit').removeEventListener('click', this.onDialogClosed);
elem.querySelector('#btnBookplayerToc').removeEventListener('click', this.openTableOfContents);
elem.querySelector('#btnBookplayerFullscreen').removeEventListener('click', this.toggleFullscreen);
elem.querySelector('#btnBookplayerRotateTheme').removeEventListener('click', this.rotateTheme);
elem.querySelector('#btnBookplayerIncreaseFontSize').removeEventListener('click', this.increaseFontSize);
elem.querySelector('#btnBookplayerDecreaseFontSize').removeEventListener('click', this.decreaseFontSize);
elem.querySelector('#btnBookplayerPrev')?.removeEventListener('click', this.previous);
elem.querySelector('#btnBookplayerNext')?.removeEventListener('click', this.next);
}
@ -214,6 +236,31 @@ export class BookPlayer {
}
}
rotateTheme() {
if (this.loaded) {
const newTheme = THEME_ORDER[(THEME_ORDER.indexOf(this.theme) + 1) % THEME_ORDER.length];
this.rendition.themes.register('default', THEMES[newTheme]);
this.rendition.themes.update('default');
this.theme = newTheme;
}
}
increaseFontSize() {
if (this.loaded && this.fontSize !== FONT_SIZES[FONT_SIZES.length - 1]) {
const newFontSize = FONT_SIZES[(FONT_SIZES.indexOf(this.fontSize) + 1)];
this.rendition.themes.fontSize(newFontSize);
this.fontSize = newFontSize;
}
}
decreaseFontSize() {
if (this.loaded && this.fontSize !== FONT_SIZES[0]) {
const newFontSize = FONT_SIZES[(FONT_SIZES.indexOf(this.fontSize) - 1)];
this.rendition.themes.fontSize(newFontSize);
this.fontSize = newFontSize;
}
}
previous(e) {
e?.preventDefault();
if (this.rendition) {
@ -296,11 +343,8 @@ export class BookPlayer {
this.currentSrc = downloadHref;
this.rendition = rendition;
rendition.themes.register('dark', { 'body': { 'color': '#fff' } });
if (userSettings.theme(undefined) === 'dark' || userSettings.theme(undefined) === null) {
rendition.themes.select('dark');
}
rendition.themes.register('default', THEMES[this.theme]);
rendition.themes.select('default');
return rendition.display().then(() => {
const epubElem = document.querySelector('.epub-container');

View file

@ -11,6 +11,15 @@
<button is="paper-icon-button-light" id="btnBookplayerExit" class="autoSize bookplayerButton hide-mouse-idle-tv" tabindex="-1">
<span class="material-icons bookplayerButtonIcon close" aria-hidden="true"></span>
</button>
<button is="paper-icon-button-light" id="btnBookplayerRotateTheme" class="autoSize bookplayerButton hide-mouse-idle-tv" tabindex="-1">
<span class="material-icons bookplayerButtonIcon remove_red_eye" aria-hidden="true"></span>
</button>
<button is="paper-icon-button-light" id="btnBookplayerDecreaseFontSize" class="autoSize bookplayerButton hide-mouse-idle-tv" tabindex="-1">
<span class="material-icons bookplayerButtonIcon text_decrease" aria-hidden="true"></span>
</button>
<button is="paper-icon-button-light" id="btnBookplayerIncreaseFontSize" class="autoSize bookplayerButton hide-mouse-idle-tv" tabindex="-1">
<span class="material-icons bookplayerButtonIcon text_increase" aria-hidden="true"></span>
</button>
<button is="paper-icon-button-light" id="btnBookplayerFullscreen" class="autoSize bookplayerButton hide-mouse-idle-tv" tabindex="-1">
<span class="material-icons bookplayerButtonIcon fullscreen" aria-hidden="true"></span>
</button>

View file

@ -133,9 +133,9 @@ class PlaybackCore {
*/
async sendBufferingRequest(isBuffering = true) {
const playerWrapper = this.manager.getPlayerWrapper();
const currentPosition = (playerWrapper.currentTimeAsync
? await playerWrapper.currentTimeAsync()
: playerWrapper.currentTime());
const currentPosition = (playerWrapper.currentTimeAsync ?
await playerWrapper.currentTimeAsync() :
playerWrapper.currentTime());
const currentPositionTicks = Math.round(currentPosition * Helper.TicksPerMillisecond);
const isPlaying = playerWrapper.isPlaying();
@ -172,11 +172,11 @@ class PlaybackCore {
*/
async applyCommand(command) {
// Check if duplicate.
if (this.lastCommand &&
this.lastCommand.When.getTime() === command.When.getTime() &&
this.lastCommand.PositionTicks === command.PositionTicks &&
this.lastCommand.Command === command.Command &&
this.lastCommand.PlaylistItemId === command.PlaylistItemId
if (this.lastCommand
&& this.lastCommand.When.getTime() === command.When.getTime()
&& this.lastCommand.PositionTicks === command.PositionTicks
&& this.lastCommand.Command === command.Command
&& this.lastCommand.PlaylistItemId === command.PlaylistItemId
) {
// Duplicate command found, check playback state and correct if needed.
console.debug('SyncPlay applyCommand: duplicate command received!', command);
@ -192,9 +192,9 @@ class PlaybackCore {
} else {
// Check if playback state matches requested command.
const playerWrapper = this.manager.getPlayerWrapper();
const currentPositionTicks = Math.round((playerWrapper.currentTimeAsync
? await playerWrapper.currentTimeAsync()
: playerWrapper.currentTime()) * Helper.TicksPerMillisecond);
const currentPositionTicks = Math.round((playerWrapper.currentTimeAsync ?
await playerWrapper.currentTimeAsync() :
playerWrapper.currentTime()) * Helper.TicksPerMillisecond);
const isPlaying = playerWrapper.isPlaying();
switch (command.Command) {
@ -279,9 +279,9 @@ class PlaybackCore {
const playAtTimeLocal = this.timeSyncCore.remoteDateToLocal(playAtTime);
const playerWrapper = this.manager.getPlayerWrapper();
const currentPositionTicks = (playerWrapper.currentTimeAsync
? await playerWrapper.currentTimeAsync()
: playerWrapper.currentTime()) * Helper.TicksPerMillisecond;
const currentPositionTicks = (playerWrapper.currentTimeAsync ?
await playerWrapper.currentTimeAsync() :
playerWrapper.currentTime()) * Helper.TicksPerMillisecond;
if (playAtTimeLocal > currentTime) {
const playTimeout = playAtTimeLocal - currentTime;

View file

@ -174,9 +174,9 @@ class QueueCore {
const currentTime = new Date();
const now = this.manager.timeSyncCore.localDateToRemote(currentTime);
const currentPosition = (playerWrapper.currentTimeAsync
? await playerWrapper.currentTimeAsync()
: playerWrapper.currentTime());
const currentPosition = (playerWrapper.currentTimeAsync ?
await playerWrapper.currentTimeAsync() :
playerWrapper.currentTime());
const currentPositionTicks = Math.round(currentPosition * Helper.TicksPerMillisecond);
const isPlaying = playerWrapper.isPlaying();

View file

@ -12,6 +12,7 @@ class SyncPlayPlugin implements Plugin {
id: string;
type: string;
priority: number;
instance: typeof SyncPlay;
constructor() {
this.name = 'SyncPlay Plugin';
@ -21,6 +22,8 @@ class SyncPlayPlugin implements Plugin {
this.type = PluginType.SyncPlay;
this.priority = 1;
this.instance = SyncPlay;
this.init();
}

View file

@ -1,11 +1,12 @@
import SyncPlay from '../core';
import SyncPlaySettingsEditor from './settings/SettingsEditor';
import loading from '../../../components/loading/loading';
import toast from '../../../components/toast/toast';
import actionsheet from '../../../components/actionSheet/actionSheet';
import globalize from '../../../scripts/globalize';
import playbackPermissionManager from './playbackPermissionManager';
import { pluginManager } from '../../../components/pluginManager';
import ServerConnections from '../../../components/ServerConnections';
import { PluginType } from '../../../types/plugin.ts';
import Events from '../../../utils/events.ts';
import './groupSelectionMenu.scss';
@ -17,11 +18,25 @@ class GroupSelectionMenu {
constructor() {
// Register to SyncPlay events.
this.syncPlayEnabled = false;
Events.on(SyncPlay.Manager, 'enabled', (e, enabled) => {
this.SyncPlay = pluginManager.firstOfType(PluginType.SyncPlay)?.instance;
if (this.SyncPlay) {
Events.on(this.SyncPlay.Manager, 'enabled', (_event, enabled) => {
this.syncPlayEnabled = enabled;
});
}
Events.on(pluginManager, 'registered', (_event0, plugin) => {
if (plugin.type === PluginType.SyncPlay) {
this.SyncPlay = plugin.instance;
Events.on(plugin.instance.Manager, 'enabled', (_event1, enabled) => {
this.syncPlayEnabled = enabled;
});
}
});
}
/**
* Used when user needs to join a group.
* @param {HTMLElement} button - Element where to place the menu.
@ -103,10 +118,11 @@ class GroupSelectionMenu {
* @param {Object} apiClient - ApiClient.
*/
showLeaveGroupSelection(button, user, apiClient) {
const groupInfo = SyncPlay.Manager.getGroupInfo();
const groupInfo = this.SyncPlay?.Manager.getGroupInfo();
const menuItems = [];
if (!SyncPlay.Manager.isPlaylistEmpty() && !SyncPlay.Manager.isPlaybackActive()) {
if (!this.SyncPlay?.Manager.isPlaylistEmpty()
&& !this.SyncPlay?.Manager.isPlaybackActive()) {
menuItems.push({
name: globalize.translate('LabelSyncPlayResumePlayback'),
icon: 'play_circle_filled',
@ -114,7 +130,7 @@ class GroupSelectionMenu {
selected: false,
secondaryText: globalize.translate('LabelSyncPlayResumePlaybackDescription')
});
} else if (SyncPlay.Manager.isPlaybackActive()) {
} else if (this.SyncPlay?.Manager.isPlaybackActive()) {
menuItems.push({
name: globalize.translate('LabelSyncPlayHaltPlayback'),
icon: 'pause_circle_filled',
@ -149,15 +165,15 @@ class GroupSelectionMenu {
border: true
};
actionsheet.show(menuOptions).then(function (id) {
actionsheet.show(menuOptions).then((id) => {
if (id == 'resume-playback') {
SyncPlay.Manager.resumeGroupPlayback(apiClient);
this.SyncPlay?.Manager.resumeGroupPlayback(apiClient);
} else if (id == 'halt-playback') {
SyncPlay.Manager.haltGroupPlayback(apiClient);
this.SyncPlay?.Manager.haltGroupPlayback(apiClient);
} else if (id == 'leave-group') {
apiClient.leaveSyncPlayGroup();
} else if (id == 'settings') {
new SyncPlaySettingsEditor(apiClient, SyncPlay.Manager.getTimeSyncCore(), { groupInfo: groupInfo })
new SyncPlaySettingsEditor(apiClient, this.SyncPlay?.Manager.getTimeSyncCore(), { groupInfo: groupInfo })
.embed()
.catch(error => {
if (error) {

View file

@ -3,13 +3,14 @@
* @module components/syncPlay/settings/SettingsEditor
*/
import SyncPlay from '../../core';
import { setSetting } from '../../core/Settings';
import dialogHelper from '../../../../components/dialogHelper/dialogHelper';
import layoutManager from '../../../../components/layoutManager';
import { pluginManager } from '../../../../components/pluginManager';
import loading from '../../../../components/loading/loading';
import toast from '../../../../components/toast/toast';
import globalize from '../../../../scripts/globalize';
import { PluginType } from '../../../../types/plugin.ts';
import Events from '../../../../utils/events.ts';
import 'material-design-icons-iconfont';
@ -36,6 +37,7 @@ class SettingsEditor {
this.apiClient = apiClient;
this.timeSyncCore = timeSyncCore;
this.options = options;
this.SyncPlay = pluginManager.firstOfType(PluginType.SyncPlay)?.instance;
}
async embed() {
@ -95,14 +97,14 @@ class SettingsEditor {
async initEditor() {
const { context } = this;
context.querySelector('#txtExtraTimeOffset').value = SyncPlay.Manager.timeSyncCore.extraTimeOffset;
context.querySelector('#chkSyncCorrection').checked = SyncPlay.Manager.playbackCore.enableSyncCorrection;
context.querySelector('#txtMinDelaySpeedToSync').value = SyncPlay.Manager.playbackCore.minDelaySpeedToSync;
context.querySelector('#txtMaxDelaySpeedToSync').value = SyncPlay.Manager.playbackCore.maxDelaySpeedToSync;
context.querySelector('#txtSpeedToSyncDuration').value = SyncPlay.Manager.playbackCore.speedToSyncDuration;
context.querySelector('#txtMinDelaySkipToSync').value = SyncPlay.Manager.playbackCore.minDelaySkipToSync;
context.querySelector('#chkSpeedToSync').checked = SyncPlay.Manager.playbackCore.useSpeedToSync;
context.querySelector('#chkSkipToSync').checked = SyncPlay.Manager.playbackCore.useSkipToSync;
context.querySelector('#txtExtraTimeOffset').value = this.SyncPlay?.Manager.timeSyncCore.extraTimeOffset;
context.querySelector('#chkSyncCorrection').checked = this.SyncPlay?.Manager.playbackCore.enableSyncCorrection;
context.querySelector('#txtMinDelaySpeedToSync').value = this.SyncPlay?.Manager.playbackCore.minDelaySpeedToSync;
context.querySelector('#txtMaxDelaySpeedToSync').value = this.SyncPlay?.Manager.playbackCore.maxDelaySpeedToSync;
context.querySelector('#txtSpeedToSyncDuration').value = this.SyncPlay?.Manager.playbackCore.speedToSyncDuration;
context.querySelector('#txtMinDelaySkipToSync').value = this.SyncPlay?.Manager.playbackCore.minDelaySkipToSync;
context.querySelector('#chkSpeedToSync').checked = this.SyncPlay?.Manager.playbackCore.useSpeedToSync;
context.querySelector('#chkSkipToSync').checked = this.SyncPlay?.Manager.playbackCore.useSkipToSync;
}
onSubmit() {
@ -139,7 +141,7 @@ class SettingsEditor {
setSetting('useSpeedToSync', useSpeedToSync);
setSetting('useSkipToSync', useSkipToSync);
Events.trigger(SyncPlay.Manager, 'settings-update');
Events.trigger(this.SyncPlay?.Manager, 'settings-update');
}
}

View file

@ -19,8 +19,8 @@ const Search: FunctionComponent = () => {
className='mainAnimatedPage libraryPage allLibraryPage noSecondaryNavPage'
>
<SearchFields onSearch={setQuery} />
{!query &&
<SearchSuggestions
{!query
&& <SearchSuggestions
parentId={searchParams.get('parentId')}
/>
}

View file

@ -187,25 +187,25 @@ function supportsCssAnimation(allowPrefix) {
const uaMatch = function (ua) {
ua = ua.toLowerCase();
const match = /(edg)[ /]([\w.]+)/.exec(ua) ||
/(edga)[ /]([\w.]+)/.exec(ua) ||
/(edgios)[ /]([\w.]+)/.exec(ua) ||
/(edge)[ /]([\w.]+)/.exec(ua) ||
/(opera)[ /]([\w.]+)/.exec(ua) ||
/(opr)[ /]([\w.]+)/.exec(ua) ||
/(chrome)[ /]([\w.]+)/.exec(ua) ||
/(safari)[ /]([\w.]+)/.exec(ua) ||
/(firefox)[ /]([\w.]+)/.exec(ua) ||
ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
[];
const match = /(edg)[ /]([\w.]+)/.exec(ua)
|| /(edga)[ /]([\w.]+)/.exec(ua)
|| /(edgios)[ /]([\w.]+)/.exec(ua)
|| /(edge)[ /]([\w.]+)/.exec(ua)
|| /(opera)[ /]([\w.]+)/.exec(ua)
|| /(opr)[ /]([\w.]+)/.exec(ua)
|| /(chrome)[ /]([\w.]+)/.exec(ua)
|| /(safari)[ /]([\w.]+)/.exec(ua)
|| /(firefox)[ /]([\w.]+)/.exec(ua)
|| ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua)
|| [];
const versionMatch = /(version)[ /]([\w.]+)/.exec(ua);
let platform_match = /(ipad)/.exec(ua) ||
/(iphone)/.exec(ua) ||
/(windows)/.exec(ua) ||
/(android)/.exec(ua) ||
[];
let platform_match = /(ipad)/.exec(ua)
|| /(iphone)/.exec(ua)
|| /(windows)/.exec(ua)
|| /(android)/.exec(ua)
|| [];
let browser = match[1] || '';

View file

@ -17,11 +17,11 @@ import browser from './browser';
}
// hevc main level 4.0
return !!videoTestElement.canPlayType &&
(videoTestElement.canPlayType('video/mp4; codecs="hvc1.1.L120"').replace(/no/, '') ||
videoTestElement.canPlayType('video/mp4; codecs="hev1.1.L120"').replace(/no/, '') ||
videoTestElement.canPlayType('video/mp4; codecs="hvc1.1.0.L120"').replace(/no/, '') ||
videoTestElement.canPlayType('video/mp4; codecs="hev1.1.0.L120"').replace(/no/, ''));
return !!videoTestElement.canPlayType
&& (videoTestElement.canPlayType('video/mp4; codecs="hvc1.1.L120"').replace(/no/, '')
|| videoTestElement.canPlayType('video/mp4; codecs="hev1.1.L120"').replace(/no/, '')
|| videoTestElement.canPlayType('video/mp4; codecs="hvc1.1.0.L120"').replace(/no/, '')
|| videoTestElement.canPlayType('video/mp4; codecs="hev1.1.0.L120"').replace(/no/, ''));
}
let _supportsTextTracks;
@ -53,8 +53,8 @@ import browser from './browser';
}
const media = document.createElement('video');
return !!(media.canPlayType('application/x-mpegURL').replace(/no/, '') ||
media.canPlayType('application/vnd.apple.mpegURL').replace(/no/, ''));
return !!(media.canPlayType('application/x-mpegURL').replace(/no/, '')
|| media.canPlayType('application/vnd.apple.mpegURL').replace(/no/, ''));
}
function canPlayHlsWithMSE() {
@ -96,8 +96,8 @@ import browser from './browser';
}
if (videoTestElement.canPlayType) {
return videoTestElement.canPlayType('application/x-mpegurl; codecs="avc1.42E01E, ac-3"').replace(/no/, '') ||
videoTestElement.canPlayType('application/vnd.apple.mpegURL; codecs="avc1.42E01E, ac-3"').replace(/no/, '');
return videoTestElement.canPlayType('application/x-mpegurl; codecs="avc1.42E01E, ac-3"').replace(/no/, '')
|| videoTestElement.canPlayType('application/vnd.apple.mpegURL; codecs="avc1.42E01E, ac-3"').replace(/no/, '');
}
return false;
@ -146,8 +146,8 @@ import browser from './browser';
return true;
}
if (videoTestElement.canPlayType('video/x-matroska').replace(/no/, '') ||
videoTestElement.canPlayType('video/mkv').replace(/no/, '')) {
if (videoTestElement.canPlayType('video/x-matroska').replace(/no/, '')
|| videoTestElement.canPlayType('video/mkv').replace(/no/, '')) {
return true;
}
@ -815,19 +815,19 @@ export function canPlaySecondaryAudio(videoTestElement) {
let maxH264Level = 42;
let h264Profiles = 'high|main|baseline|constrained baseline';
if (browser.tizen || browser.web0s ||
videoTestElement.canPlayType('video/mp4; codecs="avc1.640833"').replace(/no/, '')) {
if (browser.tizen || browser.web0s
|| videoTestElement.canPlayType('video/mp4; codecs="avc1.640833"').replace(/no/, '')) {
maxH264Level = 51;
}
// Support H264 Level 52 (Tizen 5.0) - app only
if ((browser.tizenVersion >= 5 && window.NativeShell) ||
videoTestElement.canPlayType('video/mp4; codecs="avc1.640834"').replace(/no/, '')) {
if ((browser.tizenVersion >= 5 && window.NativeShell)
|| videoTestElement.canPlayType('video/mp4; codecs="avc1.640834"').replace(/no/, '')) {
maxH264Level = 52;
}
if ((browser.tizen ||
videoTestElement.canPlayType('video/mp4; codecs="avc1.6e0033"').replace(/no/, ''))
if ((browser.tizen
|| videoTestElement.canPlayType('video/mp4; codecs="avc1.6e0033"').replace(/no/, ''))
// These tests are passing in safari, but playback is failing
&& !browser.safari && !browser.iOS && !browser.web0s && !browser.edge && !browser.mobile
) {
@ -838,28 +838,28 @@ export function canPlaySecondaryAudio(videoTestElement) {
let hevcProfiles = 'main';
// hevc main level 4.1
if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.1.4.L123"').replace(/no/, '') ||
videoTestElement.canPlayType('video/mp4; codecs="hev1.1.4.L123"').replace(/no/, '')) {
if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.1.4.L123"').replace(/no/, '')
|| videoTestElement.canPlayType('video/mp4; codecs="hev1.1.4.L123"').replace(/no/, '')) {
maxHevcLevel = 123;
}
// hevc main10 level 4.1
if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L123"').replace(/no/, '') ||
videoTestElement.canPlayType('video/mp4; codecs="hev1.2.4.L123"').replace(/no/, '')) {
if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L123"').replace(/no/, '')
|| videoTestElement.canPlayType('video/mp4; codecs="hev1.2.4.L123"').replace(/no/, '')) {
maxHevcLevel = 123;
hevcProfiles = 'main|main 10';
}
// hevc main10 level 5.1
if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L153"').replace(/no/, '') ||
videoTestElement.canPlayType('video/mp4; codecs="hev1.2.4.L153"').replace(/no/, '')) {
if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L153"').replace(/no/, '')
|| videoTestElement.canPlayType('video/mp4; codecs="hev1.2.4.L153"').replace(/no/, '')) {
maxHevcLevel = 153;
hevcProfiles = 'main|main 10';
}
// hevc main10 level 6.1
if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L183"').replace(/no/, '') ||
videoTestElement.canPlayType('video/mp4; codecs="hev1.2.4.L183"').replace(/no/, '')) {
if (videoTestElement.canPlayType('video/mp4; codecs="hvc1.2.4.L183"').replace(/no/, '')
|| videoTestElement.canPlayType('video/mp4; codecs="hev1.2.4.L183"').replace(/no/, '')) {
maxHevcLevel = 183;
hevcProfiles = 'main|main 10';
}

View file

@ -1,5 +1,5 @@
import { playbackManager } from '../components/playback/playbackmanager';
import SyncPlay from '../plugins/syncPlay/core';
import { pluginManager } from '../components/pluginManager';
import inputManager from '../scripts/inputManager';
import focusManager from '../components/focusManager';
import { appRouter } from '../components/appRouter';
@ -7,6 +7,7 @@ import ServerConnections from '../components/ServerConnections';
import toast from '../components/toast/toast';
import alert from '../components/alert';
import Events from '../utils/events.ts';
import { PluginType } from '../types/plugin.ts';
const serverNotifications = {};
@ -140,6 +141,8 @@ function processGeneralCommand(cmd, apiClient) {
function onMessageReceived(e, msg) {
const apiClient = this;
const SyncPlay = pluginManager.firstOfType(PluginType.SyncPlay)?.instance;
if (msg.MessageType === 'Play') {
notifyApp();
const serverId = apiClient.serverInfo().Id;
@ -186,9 +189,9 @@ function onMessageReceived(e, msg) {
}
}
} else if (msg.MessageType === 'SyncPlayCommand') {
SyncPlay.Manager.processCommand(msg.Data, apiClient);
SyncPlay?.Manager.processCommand(msg.Data, apiClient);
} else if (msg.MessageType === 'SyncPlayGroupUpdate') {
SyncPlay.Manager.processGroupUpdate(msg.Data, apiClient);
SyncPlay?.Manager.processGroupUpdate(msg.Data, apiClient);
} else {
Events.trigger(serverNotifications, msg.MessageType, [apiClient, msg.Data]);
}

19
src/strings/bn.json Normal file
View file

@ -0,0 +1,19 @@
{
"Favorites": "পছন্দসমূহ",
"Albums": "অ্যালবামসমূহ",
"Artists": "শিল্পীগণ",
"Books": "পুস্তকসমূহ",
"Channels": "চ্যানেলসমূহ",
"Collections": "সংগ্রহশালা",
"Folders": "ফোল্ডারসমূহ",
"Genres": "শৈলীধারাসমূহ",
"HeaderAlbumArtists": "অ্যালবাম শিল্পীবৃন্দ",
"HeaderContinueWatching": "দেখতে থাকুন",
"Movies": "চলচ্চিত্রসমূহ",
"MusicVideos": "সঙ্গীত ভিডিয়ো সমূহ",
"Photos": "চিত্রসমূহ",
"Playlists": "প্লে লিস্ট সমূহ",
"Songs": "সঙ্গীতসমূহ",
"Sync": "সমলয় স্থাপন",
"ValueSpecialEpisodeName": "বিশেষ পর্ব - {0}"
}

View file

@ -14,10 +14,10 @@
"AspectRatio": "Relació d'aspecte",
"Audio": "Àudio",
"MessageBrowsePluginCatalog": "Consulteu el nostre catàleg per veure els complements disponibles.",
"ButtonAddMediaLibrary": "Afegir Biblioteca Multimèdia",
"ButtonAddMediaLibrary": "Afegir biblioteca de mitjans",
"ButtonAddScheduledTaskTrigger": "Afegir Disparador",
"ButtonAddServer": "Afegeix Servidor",
"ButtonAddUser": "Afegir Usuari",
"ButtonAddUser": "Afegir usuari",
"ButtonArrowLeft": "Esquerra",
"ButtonArrowRight": "Dreta",
"ButtonBack": "Darrera",
@ -38,7 +38,7 @@
"ButtonQuickStartGuide": "Guia d'inici ràpid",
"ButtonRefreshGuideData": "Actualitza les dades de la guia",
"ButtonRemove": "Elimina",
"ButtonResetEasyPassword": "Reinicia el codi PIN senzill",
"ButtonResetEasyPassword": "Restabliu el codi Easy PIN",
"ButtonResume": "Reprèn",
"ButtonSelectDirectory": "Selecciona el directori",
"ButtonSend": "Envia",
@ -61,7 +61,7 @@
"DeleteImage": "Esborra Imatge",
"DeleteImageConfirmation": "Esteu segur que voleu suprimir aquesta imatge?",
"DeleteMedia": "Esborra",
"DeleteUser": "Esborra Usuari",
"DeleteUser": "Esborrar usuari",
"Desktop": "Escriptori",
"DeviceAccessHelp": "Això només s'aplica a dispositius que poden ser identificats i no previndrà l'accés des del navegador. Filtrant l'accés de dispositius a l'usuari previndrà l'ús de nous dispositius fins que hagin estat aprovats aquí.",
"Disconnect": "Desconnecta",
@ -233,7 +233,7 @@
"LabelDay": "Dia de la setmana:",
"LabelDeathDate": "Data de defunció:",
"LabelDefaultUser": "Usuari per defecte:",
"LabelDefaultUserHelp": "Determinar quina biblioteca d'usuari s'hauria de mostrar als dispositius connectats. Es pot anul·lar per a cada dispositiu emprant perfils.",
"LabelDefaultUserHelp": "Determina quina biblioteca d'usuari s'hauria de mostrar als dispositius connectats. Es pot anul·lar per a cada dispositiu emprant perfils.",
"LabelDeviceDescription": "Descripció del dispositiu:",
"LabelDiscNumber": "Disc:",
"LabelDisplayLanguage": "Idioma de visualització:",
@ -300,7 +300,7 @@
"LabelModelDescription": "Descripció del model:",
"LabelModelName": "Nom del model:",
"LabelModelNumber": "Nombre de model:",
"LabelMonitorUsers": "Supervisar activitat de:",
"LabelMonitorUsers": "Supervisar l'activitat de:",
"LabelMovieRecordingPath": "Directori de gravació de pel·lícules:",
"LabelName": "Nom:",
"LabelNewName": "Nou nom:",
@ -371,7 +371,7 @@
"Live": "Directe",
"MarkPlayed": "Marca com a reproduït",
"MarkUnplayed": "Marca com a no reproduït",
"MaxParentalRatingHelp": "El contingut amb una valoració superior no serà mostrat a l'usuari.",
"MaxParentalRatingHelp": "El contingut amb una classificació superior no serà mostrat a l'usuari.",
"MediaInfoAspectRatio": "Relació d'aspecte",
"MediaInfoChannels": "Canals",
"MediaInfoDefault": "Per defecte",
@ -402,7 +402,7 @@
"Mobile": "Mòbil",
"Monday": "Dilluns",
"MoreFromValue": "Més de {0}",
"MoreUsersCanBeAddedLater": "Podeu afegir més usuaris des del tauler de control després.",
"MoreUsersCanBeAddedLater": "Es poden afegir més usuaris des del Tauler de control.",
"MoveLeft": "Moure a l'esquerra",
"MoveRight": "Moure a la dreta",
"Mute": "Silencia",
@ -431,7 +431,7 @@
"OptionAllowRemoteControlOthers": "Permetre el control remot d'altres usuaris",
"OptionAllowRemoteSharedDevices": "Permetre el control remot dels dispositius compartits",
"OptionAllowRemoteSharedDevicesHelp": "Els dispositius DLNA es consideren compartits fins que un usuari comença a controlar-los.",
"OptionAllowUserToManageServer": "Permet aquest usuari gestionar el servidor",
"OptionAllowUserToManageServer": "Permet a aquest usuari gestionar el servidor",
"OptionCommunityRating": "Valoració de la Comunitat",
"OptionCriticRating": "Valoració dels Crítics",
"OptionDaily": "Diari",
@ -439,7 +439,7 @@
"OptionDateAddedImportTime": "Empra la data d'escaneig",
"OptionDatePlayed": "Data de Reproducció",
"OptionDisableUser": "Desactiva aquest usuari",
"OptionDisableUserHelp": "El servidor no permetrà cap connexió daquest usuari. Les connexions existents es tancaran bruscament.",
"OptionDisableUserHelp": "El servidor no permetrà cap connexió daquest usuari. Les connexions existents es tancaran immediatament.",
"OptionDislikes": "No m'agrada",
"OptionEmbedSubtitles": "Incrusta dins el contenidor",
"OptionEnableAccessFromAllDevices": "Habilita l'accés des de tots els dispositius",
@ -647,7 +647,7 @@
"BoxRear": "Caixa (posterior)",
"BoxSet": "Col·leció",
"Box": "Caixa",
"BookLibraryHelp": "L'àudio i els llibres de text són compatibles. Reviseu la {0} guia de denominació de llibres {1}.",
"BookLibraryHelp": "Els audiollibres i els llibres son compatibles. Reviseu la {0} guia de denominació de llibres {1}.",
"Backdrops": "Fons",
"Backdrop": "Fons",
"Artist": "Artista",
@ -663,14 +663,14 @@
"CopyStreamURL": "Copia l'URL de reproducció",
"ContinueWatching": "Continuar mirant",
"ConfirmEndPlayerSession": "Vols tancar Jellyfin a {0}?",
"ConfirmDeleteItems": "L'esborrat d'aquests elements els eliminarà del sistema de fitxers i de la biblioteca multimèdia. Estàs segur que vols continuar?",
"ConfirmDeleteItem": "L'esborrat d'aquest element l'eliminarà del sistema de fitxers i de la biblioteca multimèdia. Estàs segur que vols continuar?",
"ConfirmDeleteItems": "L'esborrat d'aquests elements els eliminarà del sistema de fitxers i de la biblioteca de mitjans. Esteu segurs que voleu continuar?",
"ConfirmDeleteItem": "L'esborrat d'aquest element l'eliminarà del sistema de fitxers i de la biblioteca multimèdia. Esteu segurs que voleu continuar?",
"ConfigureDateAdded": "Configureu com es determinen les metadades de la \"Data d'afegit\" al Tauler > Biblioteques > Configuració de l'NFO",
"CommunityRating": "Ràting comunitari",
"ColorTransfer": "Transferència de color",
"ColorSpace": "Espai de color",
"ColorPrimaries": "Colors primaris",
"DefaultMetadataLangaugeDescription": "Aquests són els teus valors per defecte i poden ser personalitats per cada biblioteca.",
"DefaultMetadataLangaugeDescription": "Aquests son els vostres valors per defecte i poden ser personalitzats per a cada biblioteca.",
"Default": "Per defecte",
"DatePlayed": "Data reproduït",
"DateAdded": "Data d'addició",
@ -716,7 +716,7 @@
"EnableBackdropsHelp": "Mostra imatges al fons d'algunes pàgines mentre navegueu per la biblioteca.",
"EnableAutoCast": "Establir com a defecte",
"EditMetadata": "Edita les metadades",
"EasyPasswordHelp": "El vostre codi PIN fàcil s'utilitza per accedir fora de línia als clients compatibles i també es pot utilitzar per iniciar la sessió a la xarxa fàcilment.",
"EasyPasswordHelp": "El vostre codi Easy PIN s'utilitza per accedir fora de línia als clients compatibles i també es pot utilitzar per iniciar la sessió a la xarxa fàcilment.",
"DrmChannelsNotImported": "Els canals amb DRM no simportaran.",
"DownloadsValue": "{0} descàrregues",
"DisplayMissingEpisodesWithinSeasonsHelp": "Això també s'ha d'activar per a les biblioteques de TV a la configuració del servidor.",
@ -731,7 +731,7 @@
"DirectPlaying": "Reproducció directe",
"DetectingDevices": "Detectant dispositius",
"Descending": "Descendent",
"DeleteUserConfirmation": "Esteu segur que voleu eliminar aquest usuari?",
"DeleteUserConfirmation": "Esteu segurs que voleu eliminar aquest usuari?",
"DeleteDeviceConfirmation": "Esteu segurs que voleu suprimir aquest dispositiu? Tornarà a aparèixer la propera vegada que un usuari iniciï la sessió amb ell.",
"Data": "Dades",
"ButtonUseQuickConnect": "Utilitzar Quick Connect",
@ -770,7 +770,7 @@
"EnablePlugin": "Activar",
"DirectStreamHelp1": "El flux de vídeo és compatible amb el dispositiu, però té un format d'àudio incompatible (DTS, Dolby TrueHD, etc.) o un nombre de canals d'àudio. El flux de vídeo es tornarà a empaquetar sense pèrdues sobre la marxa abans d'enviar-lo al dispositiu. Només es transcodificarà el flux d'àudio.",
"DirectPlayHelp": "El fitxer font és totalment compatible amb aquest client i la sessió rep el fitxer sense modificacions.",
"DeleteDevicesConfirmation": "Esteu segurs 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ó.",
"DeleteDevicesConfirmation": "Esteu segurs que voleu suprimir tots els dispositius? Es tancaran 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ó.",
"HeaderDirectPlayProfileHelp": "Afegiu perfils de reproducció directa per indicar quins formats pot gestionar el dispositiu de forma nativa.",
@ -922,7 +922,7 @@
"TabLogs": "Registres",
"SystemDlnaProfilesHelp": "Perfils de el sistema són de només lectura. Els canvis en un perfil de sistema seran emmagatzemades a un nou perfil personalitzat.",
"SyncPlayGroupDefaultTitle": "Grup {0}'s",
"SyncPlayAccessHelp": "La funció SyncPlay permet sincronitzar la reproducció amb altres dispositius. Seleccioneu el nivell d'accés que té aquest usuari a SyncPlay.",
"SyncPlayAccessHelp": "La funció SyncPlay permet sincronitzar la reproducció amb altres dispositius. Seleccioneu el nivell d'accés a SyncPlay que té aquest usuari.",
"SubtitleVerticalPositionHelp": "Número de línia on apareix el text. Els nombres positius indiquen dalt a baix. Els nombres negatius indiquen dalt a baix.",
"SubtitleOffset": "Subtítol Offset",
"SubtitleDownloadersHelp": "Activa i classificar les seves descarregadors de subtítols preferits en ordre de prioritat.",
@ -989,7 +989,7 @@
"MessageUnableToConnectToServer": "No es pot connectar amb el servidor seleccionat en aquest moment. Assegureu-vos que està funcionant i torni a intentar-ho.",
"MessageTheFollowingLocationWillBeRemovedFromLibrary": "Les ubicacions següents mitjans de comunicació seran eliminats de la biblioteca:",
"MessageSyncPlayUserLeft": "{0} ha deixat el grup.",
"MessageSyncPlayUserJoined": "{0} s'ha unit a el grup.",
"MessageSyncPlayUserJoined": "{0} s'ha unit al grup.",
"MessageSyncPlayPlaybackPermissionRequired": "Permís de reproducció requerit.",
"MessageSyncPlayNoGroupsAvailable": "No hi ha grups disponibles. Comença a jugar alguna cosa primer.",
"MessageSyncPlayLibraryAccessDenied": "L'accés a aquest contingut està restringit.",
@ -1012,13 +1012,13 @@
"MessagePluginConfigurationRequiresLocalAccess": "Connecteu-vos amb el servidor local directament per configurar aquest complement.",
"MessagePleaseWait": "Si us plau, espereu. Això pot trigar un minut.",
"MessagePlayAccessRestricted": "La reproducció d'aquest contingut està restringit actualment. Poseu-vos en contacte amb l'administrador de servidor per obtenir més informació.",
"MessagePasswordResetForUsers": "Els següents usuaris han tingut restablir les seves contrasenyes. Ara poden accedir als codis PIN que es van utilitzar per realitzar el restabliment.",
"MessagePasswordResetForUsers": "S'han restablert contrasenyes dels següents usuaris. Ara poden accedir amb codis Easy PIN que van utilitzar per realitzar el restabliment.",
"MessageNoServersAvailable": "No hi ha servidors han estat trobats usant el descobriment automàtic de servidor.",
"MessageNoRepositories": "No hi ha repositoris.",
"MessageNoGenresAvailable": "Permetre alguns proveïdors de metadades per tirar dels gèneres a través d'Internet.",
"MessageNoCollectionsAvailable": "Les col·leccions us permeten gaudir d'agrupacions personalitzades de pel·lícules, sèries i àlbums. Feu clic al botó '+' per començar a crear col·leccions.",
"MessageLeaveEmptyToInherit": "Deixar en blanc per Heretar configuració d'un element principal o el valor predeterminat global.",
"MessageInvalidUser": "Nom d'usuari o contrasenya incorrectes. Torni-ho a provar.",
"MessageInvalidUser": "Nom d'usuari o contrasenya incorrectes. Torneu-ho a provar.",
"MessageInvalidForgotPasswordPin": "S'ha introduït un codi PIN no vàlid o caducat. Torni-ho a provar.",
"MessageImageTypeNotSelected": "Seleccioneu un tipus d'imatge al menú desplegable.",
"MessageImageFileTypeAllowed": "Només els arxius JPEG i PNG són compatibles.",
@ -1026,7 +1026,7 @@
"MessageForgotPasswordInNetworkRequired": "Torneu a iniciar el procés de restabliment de contrasenya des de dins de la seva xarxa domèstica.",
"MessageForgotPasswordFileCreated": "El següent arxiu s'ha creat en el seu servidor i conté instruccions sobre com procedir:",
"MessageFileReadError": "Hi ha hagut un error a llegint l'arxiu. Torni-ho a provar.",
"MessageDirectoryPickerLinuxInstruction": "Per a Linux amb Arch Linux, CentOS, Debian, Fedora, openSUSE, o Ubuntu, ha de concedir a l'usuari del servei al menys l'accés de lectura als llocs d'emmagatzematge.",
"MessageDirectoryPickerLinuxInstruction": "Per a Linux amb Arch Linux, CentOS, Debian, Fedora, openSUSE, o Ubuntu, ha de concedir a l'usuari del servei com a mínim l'accés de lectura als llocs d'emmagatzematge.",
"MessageDirectoryPickerBSDInstruction": "Per BSD, pot ser que hagi de configurar l'emmagatzematge dins del seu presó FreeNAS pel Jellyfin pot accedir als mitjans de comunicació.",
"MessageDeleteTaskTrigger": "Esteu segur que voleu eliminar aquest disparador tasca?",
"MessageCreateAccountAt": "Crear un compte a {0}",
@ -1090,9 +1090,9 @@
"LabelVaapiDeviceHelp": "Aquest és el \"render node\" que s'utilitza per a l'acceleració de maquinari.",
"LabelVaapiDevice": "Dispositiu VA-API:",
"LabelUserRemoteClientBitrateLimitHelp": "Substituir el valor global predeterminat establert a la configuració del servidor, vegeu Tauler de control > Reproducció > Streaming.",
"LabelUserMaxActiveSessions": "nombre màxim de sessions simultànies d'usuaris:",
"LabelUserLoginAttemptsBeforeLockout": "Intents de connexió fallits abans que l'usuari està bloquejat:",
"LabelUserLibraryHelp": "Seleccioneu el qual la biblioteca d'usuaris per visualitzar al dispositiu. Deixar en blanc per heretar la configuració predeterminada.",
"LabelUserMaxActiveSessions": "Nombre màxim de sessions simultànies d'usuaris:",
"LabelUserLoginAttemptsBeforeLockout": "Intents de connexió fallits abans que l'usuari sigui bloquejat:",
"LabelUserLibraryHelp": "Seleccioneu quina biblioteca d'usuari es visualitza al dispositiu. Deixeu-ho en blanc per heretar la configuració predeterminada.",
"LabelUserAgent": "Agent d'usuari:",
"LabelUnstable": "Inestable",
"LabelUDPPortRangeHelp": "Restringir Jellyfin utilitzar aquest rang de ports a fer les connexions UDP. (Per defecte és 1024-65535) Nota <br/>: Certes funcions requereixen ports que poden estar fora d'aquest rang fix ..",
@ -1135,7 +1135,7 @@
"LabelSyncPlayLeaveGroup": "Marxar del grup",
"LabelSyncPlayHaltPlaybackDescription": "I ignorar les actualitzacions de llista de reproducció actual",
"LabelSyncPlayHaltPlayback": "Aturar la reproducció local",
"LabelSyncPlayAccessNone": "Desactivat per aquest usuari",
"LabelSyncPlayAccessNone": "Desactivat per a aquest usuari",
"LabelSyncPlayAccessJoinGroups": "Permetre als usuaris a unir-se als grups",
"LabelSyncPlayAccessCreateAndJoinGroups": "Permetre a l'usuari crear i unir-se a grups",
"LabelSyncPlayAccess": "Accés SyncPlay:",
@ -1237,8 +1237,8 @@
"LabelLibraryPageSizeHelp": "Estableix la quantitat d'elements a mostrar en una pàgina de la biblioteca. Es posa a 0 per tal de desactivar la paginació.",
"LabelLibraryPageSize": "Mida de pàgina de la biblioteca:",
"LabelLanNetworks": "Xarxes LAN:",
"LabelKodiMetadataUserHelp": "Guardar dades de visionat als arxius NFO de manera que altres aplicacions les puguin utilitzar.",
"LabelKodiMetadataUser": "Guardar les dades de vigilància d'usuari a arxius NFO per:",
"LabelKodiMetadataUserHelp": "Guarda les dades de visionat en arxius NFO de manera que altres aplicacions les puguin utilitzar.",
"LabelKodiMetadataUser": "Guardar les dades de visualització d'usuari en arxius NFO per a:",
"LabelKodiMetadataSaveImagePathsHelp": "Això es recomana si vostè té els noms d'arxiu d'imatge que no s'ajusten a les directrius de Kodi.",
"LabelKodiMetadataEnableExtraThumbsHelp": "Quan es descarreguin imatges, es poden guardar tant a \"extrafanart\" i \"extrathumbs\" per assegurar la màxima compatibilitat amb els skins del Kodi.",
"LabelKodiMetadataEnableExtraThumbs": "Còpia extrafanart a el camp extrathumbs",
@ -1262,7 +1262,7 @@
"LabelH265Crf": "H.265 codifica CRF:",
"LabelH264Crf": "H.264 codifica CRF:",
"LabelFormat": "Format:",
"LabelForgotPasswordUsernameHelp": "Introdueix el nom d'usuari, si ho recordi.",
"LabelForgotPasswordUsernameHelp": "Introduïu el nom d'usuari, si el recordeu.",
"LabelFont": "Font:",
"LabelFolder": "Carpeta:",
"LabelFileOrUrl": "Arxiu o URL:",
@ -1453,7 +1453,7 @@
"OptionMaxActiveSessionsHelp": "Un valor de 0 desactivarà la funció.",
"OptionMaxActiveSessions": "Establir el nombre màxim de sessions simultànies d'usuaris.",
"OptionMax": "Max",
"OptionLoginAttemptsBeforeLockoutHelp": "Un valor de 0 significa que hereten el valor per defecte de 3 intents per a usuaris normals i 5 pels administradors. Establir a -1 desactiva la funció.",
"OptionLoginAttemptsBeforeLockoutHelp": "Un valor de 0 significa que s'hereten els valors per defecte: 3 intents per als usuaris normals i 5 per als administradors. Establir a -1 desactiva la funció.",
"OptionLoginAttemptsBeforeLockout": "Determina el nombre d'intents d'inici de sessió incorrectes que es poden fer abans que es bloquegi.",
"OptionIsSD": "SD",
"OptionIsHD": "HD",
@ -1480,7 +1480,7 @@
"OptionAllowVideoPlaybackRemuxing": "Permet la reproducció de vídeo que requereix una conversió sense recodificació",
"OptionAllowSyncTranscoding": "Permet la descàrrega i la sincronització dels mitjans que requereixen transcodificació",
"OptionAllowMediaPlaybackTranscodingHelp": "La restricció de l'accés a la transcodificació pot provocar errors de reproducció en els clients a causa dels formats de mitjans compatibles.",
"OptionAllowContentDownloadHelp": "Els usuaris poden descarregar els mitjans de comunicació i emmagatzemar-la en els seus dispositius. Això no és el mateix que una funció de sincronització. biblioteques de llibres requereixen aquesta habilitat per funcionar.",
"OptionAllowContentDownloadHelp": "Els usuaris poden descarregar els mitjans i emmagatzemar-los als seus dispositius. Això no és el mateix que una funció de sincronització. Les biblioteques de llibres ho requereixen per funcionar.",
"OptionAllowContentDownload": "Permetre la descàrrega dels mitjans",
"OptionAllowAudioPlaybackTranscoding": "Permet la reproducció d'àudio que requereix la transcodificació",
"Option3D": "3D",
@ -1715,5 +1715,6 @@
"SubtitleRed": "Vermell",
"SubtitleYellow": "Groc",
"StereoDownmixAlgorithmHelp": "Algoritme utilitzat per barrejar àudio multicanal a estèreo.",
"DownloadAll": "Descarrega-ho tot"
"DownloadAll": "Descarrega-ho tot",
"LabelEnableAudioVbr": "Activar la codificació d'àudio VBR"
}

View file

@ -1719,5 +1719,7 @@
"Short": "Krátký film",
"HeaderPerformance": "Výkon",
"LabelParallelImageEncodingLimit": "Počet paralelních kódování obrázků",
"LabelParallelImageEncodingLimitHelp": "Maximální počet kódování obrázků, které mohou běžet zároveň. Nastavením na 0 bude limit nastaven dle parametrů systému."
"LabelParallelImageEncodingLimitHelp": "Maximální počet kódování obrázků, které mohou běžet zároveň. Nastavením na 0 bude limit nastaven dle parametrů systému.",
"LabelEnableAudioVbr": "Povolit kódování zvuku VBR",
"LabelEnableAudioVbrHelp": "Proměnlivý bitový tok (VBR) nabízí lepší poměr mezi kvalitou a průměrným bitovým tokem, ale někdy může způsobit dodatečné načítání či problémy s kompatibilitou."
}

View file

@ -80,8 +80,8 @@
"Composer": "Komponist",
"ConfigureDateAdded": "Konfigurer hvordan metadata for 'tilføjet' dato bestemmes, under Kontrolpanel > Biblioteker > NFO indstillinger",
"ConfirmDeleteImage": "Slet billede?",
"ConfirmDeleteItem": "Hvis dette element slettes, fjernes det både fra dit filsystem samt din mediebibliotek. Er du sikker på du ønsker at fortsætte?",
"ConfirmDeleteItems": "Sletning af disse emner vil både fjerne dem fra filsystemet og dit mediebibliotek. Er du sikker på at du vil fortsætte?",
"ConfirmDeleteItem": "Hvis dette element slettes, fjernes det fra både dit filsystem og dit mediebibliotek. Er du sikker på at fortsætte?",
"ConfirmDeleteItems": "Sletning af disse emner vil fjerne dem fra både filsystemet og dit mediebibliotek. Er du sikker på at du vil fortsætte?",
"ConfirmDeletion": "Bekræft sletning",
"Connect": "Forbind",
"Continuing": "Forsættes",
@ -136,7 +136,7 @@
"FileReadError": "Der opstod en fejl i forsøget på at læse filen.",
"Friday": "Fredag",
"Fullscreen": "Fuldskærm",
"General": "Generel",
"General": "Generelt",
"Genres": "Genrer",
"GroupVersions": "Grupér versioner",
"GuestStar": "Gæsteskuespiller",
@ -272,7 +272,7 @@
"HeaderSendMessage": "Send besked",
"HeaderSeriesOptions": "Serieindstillinger",
"HeaderServerSettings": "Serverindstillinger",
"HeaderSetupLibrary": "Opsæt dine mediebiblioteker",
"HeaderSetupLibrary": "Konfigurer dine mediebiblioteker",
"HeaderSortBy": "Sorter Efter",
"HeaderSortOrder": "Sorteringsorden",
"HeaderSpecialEpisodeInfo": "Information om specialepisoder",
@ -404,7 +404,7 @@
"LabelFriendlyName": "System venligt navn:",
"LabelServerNameHelp": "Dette navn bruges til at identificere serveren. Som udgangspunkt anvendes computerens navn.",
"LabelGroupMoviesIntoCollections": "Grupper film i samlinger",
"LabelGroupMoviesIntoCollectionsHelp": "Film i samlinger vil blive vist som en samlet enhed i filmlister.",
"LabelGroupMoviesIntoCollectionsHelp": "Film i samlinger vil blive vist som en samlet visning i filmlister.",
"LabelH264Crf": "H.264-kodning CRF:",
"LabelEncoderPreset": "Forudindstilling for kodning:",
"LabelHardwareAccelerationType": "Hardwareacceleration:",
@ -451,9 +451,9 @@
"LabelMessageText": "Beskedtekst:",
"LabelMessageTitle": "Titel på besked:",
"LabelMetadataDownloadLanguage": "Foretrukket sprog for nedhentning:",
"LabelMetadataDownloadersHelp": "Aktiver og ranger dine fortrukne metadata downloadere i en prioriteret rækkefølge. Lavt rangerende downloadere bliver kun benyttet til at udfylde manglende information.",
"LabelMetadataDownloadersHelp": "Aktiver og ranger dine foretrukne metadata kilder i prioriteret rækkefølge. Lavt rangerende kilder vil kun blive benyttet til at udfylde manglende information.",
"LabelMetadataPath": "Metadatasti:",
"LabelMetadataPathHelp": "Angiv en brugerdefineret lokation til downloadet grafik og metadata.",
"LabelMetadataPathHelp": "Angiv en brugerdefineret lokation til hentet grafik og metadata.",
"LabelMetadataReaders": "Metadata aflæsere:",
"LabelMetadataReadersHelp": "Ranger dine fortrukne lokale metadatakilder i prioriteret rækkefølge. Den først fundne fil vil blive aflæst.",
"LabelMetadataSavers": "Metadata-gemmer:",
@ -546,7 +546,7 @@
"LabelStartWhenPossible": "Start når muligt:",
"LabelStopWhenPossible": "Stop når muligt:",
"LabelStopping": "Standser",
"LabelSubtitleDownloaders": "undertekst downloadere:",
"LabelSubtitleDownloaders": "Kilder til undertekster:",
"LabelSubtitleFormatHelp": "F. eks: srt",
"LabelSubtitlePlaybackMode": "Underteksttilstand:",
"LabelSupportedMediaTypes": "Understøttede medieformater:",
@ -561,7 +561,7 @@
"LabelTriggerType": "Udløsertype:",
"LabelTunerIpAddress": "IP-adresse for Tuner:",
"LabelTunerType": "Tunertype:",
"LabelTypeMetadataDownloaders": "Metadata downloadere ({0}):",
"LabelTypeMetadataDownloaders": "Kilder for metadata ({0}):",
"LabelTypeText": "Tekst",
"LabelUseNotificationServices": "Brug følgende tjenester:",
"LabelUser": "Bruger:",
@ -622,7 +622,7 @@
"MessageDeleteTaskTrigger": "Er du sikker på du ønsker at slette denne task trigger?",
"MessageDirectoryPickerBSDInstruction": "For BSD skal du muligvis konfigurere lager i dit 'FreeNAS Jail', så Jellyfin kan tilgå dine medie filer.",
"MessageDirectoryPickerLinuxInstruction": "For Linux på Arch Linux, CentOS, Debian, Fedora, openSUSE eller Ubuntu, skal du give servicebrugeren mindst læseadgang til dine lagerpladser.",
"MessageDownloadQueued": "Download sat i kø.",
"MessageDownloadQueued": "Hent sat i kø.",
"MessageEnablingOptionLongerScans": "Aktivering af denne indstilling kan resultere i væsentlig længere biblioteks skan.",
"MessageFileReadError": "Der opstod en fejl i forsøget på at læse filen.",
"MessageForgotPasswordFileCreated": "Den følgende fil er blevet oprettet på din server og indeholder instruktioner vedrørende hvordan du skal fortsætte:",
@ -638,7 +638,7 @@
"MessageNoTrailersFound": "Installer forfilm kanalen for at tilføje et bibliotek med forfilm hentet fra internettet.",
"MessageNothingHere": "Her er ingenting.",
"MessagePasswordResetForUsers": "Følgende brugere har fået nulstillet deres adgangskoder. De kan nu logge på med de pinkoder, der blev brugt til at udføre nulstillingen.",
"MessagePleaseEnsureInternetMetadata": "Sørg venligst for at hentning af metadata fra internettet er aktiveret.",
"MessagePleaseEnsureInternetMetadata": "Venligst sikre at hentning af metadata fra internettet er aktiveret.",
"MessagePleaseWait": "Vent venligst. Dette kan tage et minut.",
"MessagePluginConfigurationRequiresLocalAccess": "For at opsætte dette plugin log da venligst direkte ind på din lokale server.",
"MessagePluginInstallDisclaimer": "Plugins fremstillet af medlemmer fra fællesskabet er en alle tiders måde at forbedre din oplevelse med yderligere features og fordele. Før installation, bedes du venligst være opmærksom på de effekter de kan have på din server; så som lange scantider på biblioteker, yderligere baggrundsbehandling og forringet systemstabilitet.",
@ -688,7 +688,7 @@
"OptionAllowRemoteControlOthers": "Tillad fjernstyring af andre brugere",
"OptionAllowRemoteSharedDevices": "Tillad fjernstyring af delte enheder",
"OptionAllowRemoteSharedDevicesHelp": "DLNA-enheder betragtes som delt, indtil en bruger begynder at kontrollere dem.",
"OptionAllowSyncTranscoding": "Tillad medie hentning og synkronisering der kræver omkodning",
"OptionAllowSyncTranscoding": "Tillad at hente medier og synkronisering der kræver omkodning",
"OptionAllowUserToManageServer": "Tillad denne bruger at administrere serveren",
"OptionAllowVideoPlaybackRemuxing": "Tillad videoafspilning som kræver konvertering uden omkodning",
"OptionAllowVideoPlaybackTranscoding": "Tillad videoafspilning der kræver transkodning",
@ -706,7 +706,7 @@
"OptionDisableUserHelp": "Serveren vil ikke tillade forbindelser fra denne bruger. Eksisterende forbindelser vil blive afbrudt øjeblikkeligt.",
"OptionDislikes": "Ikke-Lide",
"OptionDisplayFolderView": "Få vist en mappevisning til at se enkle mediemapper",
"OptionDisplayFolderViewHelp": "Vis mapper sammen med dine andre mediebiblioteker. Dette kan være nyttigt, hvis du gerne vil have en almindelig mappevisning.",
"OptionDisplayFolderViewHelp": "Vis mapper sammen med dine andre mediebiblioteker. Dette kan være nyttigt, hvis du gerne vil have en simpel mappevisning.",
"OptionDownloadImagesInAdvance": "Download billeder på forhånd",
"OptionDownloadImagesInAdvanceHelp": "Som standard downloades de fleste billeder kun, når de anmodes fra en Jellyfin-app. Aktivér denne mulighed for at downloade alle billeder på forhånd, da nye medier importeres. Dette kan forårsage betydeligt længere biblioteksscanninger.",
"OptionDvd": "DVD",
@ -746,7 +746,7 @@
"OptionReleaseDate": "Udgivelsesdato",
"OptionReportByteRangeSeekingWhenTranscoding": "Angiv at serveren understøtter bytes øgning nrdeå r transkodes",
"OptionReportByteRangeSeekingWhenTranscodingHelp": "Dette er krævet for nogle enheder der ikke er særligt gode til tidssøgning.",
"OptionRequirePerfectSubtitleMatch": "Download kun undertekster der er perfekte matches for videofiler",
"OptionRequirePerfectSubtitleMatch": "Hent kun undertekster der er perfekte matches for videofiler",
"OptionResumable": "Kan genoptages",
"OptionSaveMetadataAsHidden": "Gem metadata og billeder som skjulte filer",
"OptionSaveMetadataAsHiddenHelp": "Ændring af dette vil blive anvendt på nyt metadata gemt fremadrettet. Allerede eksisterende metadata-filer opdateres næste gang de gemmes af serveren.",
@ -835,7 +835,7 @@
"ServerNameIsRestarting": "Serveren bag {0} genstarter.",
"ServerNameIsShuttingDown": "Serveren bag {0} lukker ned.",
"ServerRestartNeededAfterPluginInstall": "Jellyfin skal genstartes efter installation af en tilføjelse.",
"ServerUpdateNeeded": "Denne server bør opdateres. For at hente den nyeste version besøg venligst {0}",
"ServerUpdateNeeded": "Denne server bør opdateres. For at hente den nyeste version, besøg venligst {0}",
"Settings": "Indstillinger",
"SettingsSaved": "Indstillinger er gemt.",
"SettingsWarning": "Ændring af disse værdier kan resultere i instabilitet eller forbindelsesfejl. Hvis du oplever fejl, anbefaler vi at du skifter til standardværdier.",
@ -851,16 +851,16 @@
"Sports": "Sport",
"StopRecording": "Stop optagelse",
"Studios": "Studier",
"SubtitleDownloadersHelp": "Aktiver og ranger dine prefererede undertekst hentere i priotets orden.",
"SubtitleDownloadersHelp": "Aktiver og ranger dine foretrukne kilder for undertekster i prioriteret rækkefølge.",
"Subtitles": "Undertekster",
"Sunday": "Søndag",
"Sync": "Synk",
"Sync": "Synkroniser",
"SystemDlnaProfilesHelp": "Systemprofiler kan ikke overskrives. Ændringer i en systemprofil vil blive gemt i en ny brugerdefineret profil.",
"TabAccess": "Adgang",
"TabAdvanced": "Avanceret",
"TabCatalog": "Katalog",
"TabContainers": "Containere",
"TabDashboard": "Betjeningspanel",
"TabDashboard": "Dashboard",
"TabDirectPlay": "Direkte afspilning",
"TabLatest": "Nyligt tilføjet",
"TabMusic": "Musik",
@ -920,13 +920,13 @@
"XmlTvSportsCategoriesHelp": "Programmer med disse kategorier bliver vist som sportsprogrammer. Adskil flere med '|'.",
"Yesterday": "I går",
"AirDate": "Udgivelsesdato",
"Albums": "Albummer",
"Albums": "Album",
"Artists": "Kunstnere",
"Books": "Bøger",
"Collections": "Samlinger",
"Favorites": "Favoritter",
"Folders": "Mapper",
"HeaderAlbumArtists": "Albumkunstner",
"HeaderAlbumArtists": "Albums kunstnere",
"Absolute": "Absolut",
"AccessRestrictedTryAgainLater": "Adgang er begrænset lige nu. Prøv venligst igen senere.",
"Aired": "Udgivet",
@ -1057,7 +1057,7 @@
"LabelMetadata": "Metadata:",
"LabelModelUrl": "Model URL:",
"LabelPreferredSubtitleLanguage": "Foretrukket undertekst sprog:",
"LabelProfileCodecs": "Codecs:",
"LabelProfileCodecs": "Kodeks:",
"LabelProfileContainer": "Beholder:",
"LabelProfileVideoCodecs": "Video Codec:",
"LabelReasonForTranscoding": "Grund til omkodning:",
@ -1121,10 +1121,10 @@
"OptionProtocolHls": "HTTP Live Streaming (HLS)",
"OptionProtocolHttp": "Web",
"OptionRegex": "Regex",
"OptionRequirePerfectSubtitleMatchHelp": "At påkræve en perfekt match vil filtrere undertekster så kun dem der er testet og tjekket der passer nøjagtigt til din video fil vil blive inkluderet. At fravælge denne vil forøge chancerne for at undertekster bliver hentet, men vil også forøge risikoen for ikke-passende og ukorrekte undertekster.",
"OptionRequirePerfectSubtitleMatchHelp": "At påkræve et perfekt match, vil filtrere undertekster så kun dem der er testet og tjekket at de passer nøjagtigt til din video fil, vil blive inkluderet. Hvis du fravælger vil det forøge chancerne for at undertekster bliver hentet, men vil også forøge risikoen for ikke-passende og ukorrekte undertekster.",
"OptionResElement": "'res' element",
"PerfectMatch": "Perfekt match",
"Photos": "Fotoer",
"Photos": "Fotos",
"PlayCount": "Afspilninger",
"PlayNext": "Afspil næste",
"PlayNextEpisodeAutomatically": "Afspil næste afsnit automatisk",
@ -1233,8 +1233,8 @@
"DashboardServerName": "Server: {0}",
"DashboardVersionNumber": "Version: {0}",
"LabelTranscodingProgress": "Transkodnings forløb:",
"LabelTranscodingFramerate": "Transcoding framerate:",
"LabelTranscodes": "Transcodes:",
"LabelTranscodingFramerate": "Omkodnings opdateringshastighed:",
"LabelTranscodes": "Omkodede filer:",
"LabelTranscodePath": "Transkodnings sti:",
"LabelStreamType": "Streamtype:",
"LabelSonyAggregationFlags": "Sony aggregering flag:",
@ -1325,7 +1325,7 @@
"HeaderPortRanges": "Brandmur og Proxy indstillinger",
"HeaderNewRepository": "Nyt arkiv",
"HeaderNetworking": "IP Protokoller",
"HeaderDVR": "Digital optager",
"HeaderDVR": "DVR",
"HeaderDeleteDevices": "Fjern alle enheder",
"HeaderDebugging": "Fejlfinding og sporing",
"HeaderAutoDiscovery": "Netværksopdagelse",
@ -1381,8 +1381,8 @@
"Other": "Andet",
"OptionMaxActiveSessionsHelp": "En værdi på 0 vil deaktivere denne funktion.",
"OptionMaxActiveSessions": "Angiv det maksimale antal samtidige bruger sessioner.",
"OptionAllowContentDownloadHelp": "Brugere kan hente media og gemme det på deres enheder. Dette er ikke det samme som en sync funktion. Bog biblioteker kræver dette aktiveres for at fungere ordentlig.",
"OptionAllowContentDownload": "Tillad hentning af media",
"OptionAllowContentDownloadHelp": "Brugere kan hente materiale og gemme det på deres enheder. Dette er ikke det samme som en synk funktion. Bog biblioteker kræver at dette er aktiveret for at fungere korrekt.",
"OptionAllowContentDownload": "Tillad at hente media",
"NextTrack": "Spring til næste",
"MusicVideos": "Musikvideoer",
"MillisecondsUnit": "ms",
@ -1609,7 +1609,7 @@
"AllowEmbeddedSubtitlesAllowImageOption": "Tillad billede",
"AllowEmbeddedSubtitlesAllowNoneOption": "Tillad ingen",
"AllowEmbeddedSubtitlesAllowAllOption": "Tillad alle",
"AllowEmbeddedSubtitlesHelp": "Deaktiver undertekster som er pakket i medie. Kræver en komplet biblioteksopdatering.",
"AllowEmbeddedSubtitlesHelp": "Deaktiver undertekster som er pakket i mediet. Kræver en komplet biblioteksopdatering.",
"OtherArtist": "Anden artist",
"OriginalAirDate": "Original sendedato",
"NextChapter": "Næste kapitel",
@ -1665,5 +1665,40 @@
"SubtitleGreen": "Grøn",
"SubtitleLightGray": "lysegrå",
"SubtitleRed": "Rød",
"Short": "Kort"
"Short": "Kort",
"Featurette": "Klip",
"PreferEmbeddedExtrasTitlesOverFileNamesHelp": "Ekstramateriale har ofte det samme indlejrede navn som det oprindelige materiale. Brug denne for at bruge den indlejrede titel alligevel.",
"MediaInfoDoViTitle": "DV titel",
"OptionDateEpisodeAdded": "Dato episoden blev tilføjet",
"PreferEmbeddedExtrasTitlesOverFileNames": "Foretræk indlejrede titler fremfor filnavne på ekstramateriale",
"LabelTextWeight": "Tekst vægt:",
"RememberSubtitleSelectionsHelp": "Forsøg at vælge undertekst ud fra tætteste match af foregående video.",
"SaveRecordingImages": "Gem optagelsens EPG billeder",
"HomeVideosPhotos": "Hjemmevideoer og -billeder",
"IgnoreDtsHelp": "Deaktivering af denne indstilling kan muligvis løse udfordringer såsom manglende lydkanal med separate lyd- og videospor.",
"EnableSplashScreen": "Vis opstarts skærm",
"LabelStereoDownmixAlgorithm": "",
"LabelMaxVideoResolution": "Max opløsning af video omkodnings opløsning",
"HeaderRecordingMetadataSaving": "Optager metadata",
"LabelChapterImageResolutionHelp": "Opløsningen af det udtrukne kapitelbillede.",
"MessageRenameMediaFolder": "Omdøbning af et mediebibliotek sletter al tilhørende metadata. Fortsæt med forsigtighed.",
"StereoDownmixAlgorithmHelp": "Algoritme brugt til at nedskalere flerkanals lyd til stereo.",
"IgnoreDts": "Ignorer DTS (afkodning af tidsstempel)",
"LabelDummyChapterDuration": "Interval:",
"LabelDummyChapterDurationHelp": "Interval i sekunder for udtræk af kapitelbilleder.",
"LabelDummyChapterCount": "Begrænsning:",
"LabelDummyChapterCountHelp": "Det maksimum antal kapitelbilleder der udtrækkes for hver mediefil.",
"MediaInfoDvProfile": "DV profil",
"LabelParallelImageEncodingLimit": "Parallel billedkodning grænese",
"LabelParallelImageEncodingLimitHelp": "Max antal af billedkodninger, som er tilladt at køre parallelt. Ved at sætte denne til 0, vil der blive valgt et max ud fra dit system.",
"MessageNoItemsAvailable": "Ingen elementer er tilgængelige i øjeblikket.",
"MessageNoFavoritesAvailable": "Ingen favoritter er tilgængelige i øjeblikket.",
"OptionDateShowAdded": "Dato serien blev tilføjet",
"RememberAudioSelections": "Vælg lydspor baseret på foregående element",
"RememberAudioSelectionsHelp": "Forsøg at vælge lydspor ud fra tætteste match ud fra foregående video.",
"RememberSubtitleSelections": "Vælg undertekst baseret på foregående element",
"EnableCardLayout": "Vis visuel CardBox",
"ResolutionMatchSource": "Match kilde",
"SubtitleCyan": "Cyan",
"SubtitleMagenta": "Magenta"
}

View file

@ -637,6 +637,8 @@
"LabelEasyPinCode": "Easy PIN code:",
"LabelEmbedAlbumArtDidl": "Embed album art in DIDL",
"LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for getting the album art. Others may fail to play with this option enabled.",
"LabelEnableAudioVbr": "Enable VBR audio encoding",
"LabelEnableAudioVbrHelp": "Variable bitrate offers better quality to average bitrate ratio, but in some rare cases may cause buffering and compatibility issues.",
"LabelEnableAutomaticPortMap": "Enable automatic port mapping",
"LabelEnableAutomaticPortMapHelp": "Automatically forward public ports on your router to local ports on your server via UPnP. This may not work with some router models or network configurations. Changes will not apply until after a server restart.",
"LabelEnableBlastAliveMessages": "Blast alive messages",

View file

@ -1719,5 +1719,7 @@
"Short": "Court-métrage",
"HeaderPerformance": "Performance",
"LabelParallelImageEncodingLimit": "Limite de parallélisation de l'encodage d'image",
"LabelParallelImageEncodingLimitHelp": "Nombre maximal dencodages dimage autorisés à sexécuter en parallèle. Si vous définissez cette valeur sur 0, vous choisirez une limite en fonction des spécifications de votre système."
"LabelParallelImageEncodingLimitHelp": "Nombre maximal dencodages dimage autorisés à sexécuter en parallèle. Si vous définissez cette valeur sur 0, vous choisirez une limite en fonction des spécifications de votre système.",
"LabelEnableAudioVbr": "Activer lencodage audio VBR",
"LabelEnableAudioVbrHelp": "Le débit binaire variable offre une qualité supérieure à la moyenne mais peut, dans de rares cas, causer des problèmes de mise en mémoire tampon et de compatibilité."
}

View file

@ -148,5 +148,6 @@
"Songs": "गाने",
"Larger": "और बड़ा",
"ListPaging": "{2} का {0}-{1}",
"Shows": "शो"
"Shows": "शो",
"ValueSpecialEpisodeName": "विशेष"
}

View file

@ -1614,7 +1614,7 @@
"ContainerBitrateExceedsLimit": "A videó bitrátája meghaladja a limitet",
"SelectAll": "Összes kiválasztása",
"ButtonExitApp": "Kilépés az alkalmazásból",
"Clip": "Rövidfilm",
"Clip": "Klip",
"ThemeVideo": "Téma Videó",
"ThemeSong": "Főcímdal",
"Sample": "Minta",
@ -1711,5 +1711,10 @@
"LabelDummyChapterCount": "Határvonal:",
"LabelChapterImageResolution": "Felbontás:",
"LabelChapterImageResolutionHelp": "A kinyert fejezetképek felbontása.",
"HeaderPerformance": "Teljesítmény"
"HeaderPerformance": "Teljesítmény",
"Short": "Rövidfilm",
"Featurette": "Mellékfilm",
"LabelParallelImageEncodingLimitHelp": "Maximálisan engedélyezett egyidejűleg futó képkódolások száma. 0-ra állítva a rendszer specifikációja alapján lesz kiválasztva a limit.",
"ResolutionMatchSource": "Forrásnak megfelelő",
"LabelParallelImageEncodingLimit": "Egyidejű képkódolási limit"
}

View file

@ -127,7 +127,7 @@
"Sunday": "Duminică",
"TabAccess": "Acces",
"TabAdvanced": "Avansat",
"TabLatest": "Cele mai recente",
"TabLatest": "Adăugate recent",
"TabMusic": "Muzică",
"TabMyPlugins": "Plugin-urile mele",
"TabNetworks": "Trusturi TV",
@ -946,7 +946,7 @@
"List": "Listă",
"LeaveBlankToNotSetAPassword": "Puteți lăsa acest câmp necompletat pentru a nu seta o parolă.",
"LearnHowYouCanContribute": "Aflați cum puteți contribui.",
"LatestFromLibrary": "Ultimele {0}",
"LatestFromLibrary": "Ultimele adăugate {0}",
"Large": "Mare",
"LanNetworksHelp": "Lista separată de virgule a adreselor IP sau a intrărilor de tip IP/mască de rețea pentru rețelele care vor fi luate în considerare în rețeaua locală atunci când se aplică restricțiile de lățime de bandă. Dacă este setat, toate celelalte adrese IP vor fi considerate a fi în rețeaua externă și vor fi supuse restricțiilor de lățime de bandă externe. Dacă este lăsat necompletat, numai subnetul serverului este considerat a fi în rețeaua locală.",
"LabelffmpegPathHelp": "Calea către executabilul FFmpeg sau dosarul care conține FFmpeg.",
@ -1614,7 +1614,7 @@
"DeletedScene": "Scene șterse",
"BehindTheScenes": "În spatele scenei",
"Trailer": "Trailer",
"Clip": "Featurette",
"Clip": "Clip",
"SelectAll": "Selectează Tot",
"DirectPlayError": "A apărut o eroare la pornirea redării directe",
"UnknownAudioStreamInfo": "Informațiile fluxului audio sunt necunoscute",
@ -1663,7 +1663,7 @@
"IgnoreDts": "Ignoră DTS (marca de timp a decodării)",
"DownloadAll": "Descărcați tot",
"MessageNoItemsAvailable": "Niciun articol nu este valabil în momentul actual.",
"MessageRenameMediaFolder": "Redenumirea unei biblioteci va cauza toate metadatele să fie pierdute, continuați cu grijă.",
"MessageRenameMediaFolder": "Redenumirea unei biblioteci va șterge toate fisierele metadata, continuați cu grijă.",
"OptionDateEpisodeAdded": "Dată Adăugare Episod",
"OptionDateShowAdded": "Dată Adăugare Serial",
"MessageNoFavoritesAvailable": "Niciun favorit nu este valabil în momentul actual.",
@ -1680,5 +1680,6 @@
"LabelParallelImageEncodingLimit": "Limita encodărilor simultane",
"LabelParallelImageEncodingLimitHelp": "Numărul maxim de encodări ale imaginilor care sunt permise să ruleze simultan. Setarea acestei valori la 0 va alege automat o limită bazată pe specificațiile tehnice ale sistemului.",
"HeaderDummyChapter": "Imaginile Capitolelor",
"HeaderRecordingMetadataSaving": "Înregistrarea Metadatelor"
"HeaderRecordingMetadataSaving": "Înregistrarea Metadatelor",
"EnableSplashScreen": "Activează ecranul splash"
}

View file

@ -1662,7 +1662,7 @@
"RememberAudioSelectionsHelp": "Cố gắng đặt bản âm thanh phù hợp nhất với video cuối cùng.",
"RememberAudioSelections": "Đặt bản nhạc dựa trên mục trước đó",
"LabelMaxVideoResolution": "Độ Phân Giải Chuyển Mã Video Tối Đa Được Phép",
"VideoRangeTypeNotSupported": "Loại phạm vi của video không được hỗ trợ",
"VideoRangeTypeNotSupported": "Không hỗ trợ loại dải động của video",
"Interview": "Phỏng vấn",
"Sample": "Mẫu",
"Trailer": "",
@ -1709,5 +1709,8 @@
"LabelParallelImageEncodingLimitHelp": "Lượng mã hóa hình ảnh tối đa được phép chạy song song. Đặt giá trị này thành 0 sẽ chọn giới hạn dựa trên thông số kỹ thuật hệ thống của bạn.",
"SecondarySubtitles": "Phụ đề phụ",
"HeaderPerformance": "Hiệu suất",
"LabelParallelImageEncodingLimit": "Giới hạn mã hóa hình ảnh song song"
"LabelParallelImageEncodingLimit": "Giới hạn mã hóa hình ảnh song song",
"MediaInfoDvBlSignalCompatibilityId": "Id tương thích tính hiệu DV bl",
"LabelEnableAudioVbr": "Bật mã hóa âm thanh VBR",
"LabelEnableAudioVbrHelp": "Tốc độ bit thay đổi mang lại chất lượng tốt hơn so với tỷ lệ bit trung bình, nhưng trong một số trường hợp hiếm gặp, có thể gây ra sự cố về khả năng tương thích và bộ đệm."
}

View file

@ -1380,10 +1380,10 @@
"Preview": "预览",
"SubtitleVerticalPositionHelp": "文字出现的行号。正数表示由上到下,负数表示由下到上。",
"LabelSubtitleVerticalPosition": "垂直位置:",
"PreviousTrack": "上一",
"PreviousTrack": "上一",
"MessageGetInstalledPluginsError": "获取已安装插件列表时出现错误。",
"MessagePluginInstallError": "安装插件时出现错误。",
"NextTrack": "下一",
"NextTrack": "下一",
"LabelUnstable": "不稳定",
"PlaybackRate": "播放速度",
"LabelMaxMuxingQueueSize": "最大混合器队列大小:",
@ -1719,5 +1719,7 @@
"Short": "短片",
"LabelParallelImageEncodingLimitHelp": "允许并行运行的图像编码的最大数量。设为 0 以根据您的系统配置自动设置。",
"HeaderPerformance": "性能",
"LabelParallelImageEncodingLimit": "并行图像编码限制"
"LabelParallelImageEncodingLimit": "并行图像编码限制",
"LabelEnableAudioVbr": "启用 VBR 音频编码",
"LabelEnableAudioVbrHelp": "可变比特率VBR相比平均比特率ABR可以提供更好的质量但在少见情况中可能造成缓冲和兼容性问题。"
}

View file

@ -9,5 +9,5 @@ export interface Plugin {
name: string
id: string
type: PluginType | string
priority: number
priority?: number
}