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 relax-hevc-safari

This commit is contained in:
Nyanmisaka 2024-02-07 22:30:52 +08:00 committed by GitHub
commit 8a52518c79
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 243 additions and 201 deletions

View file

@ -21,7 +21,7 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup node environment
uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: 20
check-latest: true
@ -39,7 +39,7 @@ jobs:
mv dist/config.tmp.json dist/config.json
- name: Upload artifact
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with:
name: jellyfin-web__prod
path: |
@ -62,7 +62,7 @@ jobs:
echo $PR_SHA > PR_sha
- name: Upload PR number as artifact
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with:
name: PR_context
path: |

View file

@ -22,13 +22,13 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Initialize CodeQL
uses: github/codeql-action/init@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v3.23.2
uses: github/codeql-action/init@e8893c57a1f3a2b659b6b55564fdfdbbd2982911 # v3.24.0
with:
languages: javascript
queries: +security-extended
- name: Autobuild
uses: github/codeql-action/autobuild@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v3.23.2
uses: github/codeql-action/autobuild@e8893c57a1f3a2b659b6b55564fdfdbbd2982911 # v3.24.0
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v3.23.2
uses: github/codeql-action/analyze@e8893c57a1f3a2b659b6b55564fdfdbbd2982911 # v3.24.0

View file

@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Notify as seen
uses: peter-evans/create-or-update-comment@23ff15729ef2fc348714a3bb66d2f655ca9066f2 # v3.1.0
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
with:
token: ${{ secrets.JF_BOT_TOKEN }}
comment-id: ${{ github.event.comment.id }}
@ -28,7 +28,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.JF_BOT_TOKEN }}
- name: Comment on failure
if: failure()
uses: peter-evans/create-or-update-comment@23ff15729ef2fc348714a3bb66d2f655ca9066f2 # v3.1.0
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
with:
token: ${{ secrets.JF_BOT_TOKEN }}
issue-number: ${{ github.event.issue.number }}

View file

@ -22,7 +22,7 @@ jobs:
ref: ${{ github.event.pull_request.head.sha }}
- name: Setup node environment
uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: 20
check-latest: true

View file

@ -20,7 +20,7 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup node environment
uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: 20
check-latest: true
@ -44,7 +44,7 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup node environment
uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: 20
check-latest: true
@ -56,8 +56,8 @@ jobs:
- name: Run eslint
run: npx eslint --quiet "."
run-stylelint-css:
name: Run stylelint (css)
run-stylelint:
name: Run stylelint
runs-on: ubuntu-latest
steps:
@ -65,7 +65,7 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup node environment
uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: 20
check-latest: true
@ -78,31 +78,7 @@ jobs:
run: npm ci --no-audit
- name: Run stylelint
run: npm run stylelint:css
run-stylelint-scss:
name: Run stylelint (scss)
runs-on: ubuntu-latest
steps:
- name: Check out Git repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup node environment
uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
with:
node-version: 20
check-latest: true
cache: npm
- name: Set up stylelint matcher
uses: xt0rted/stylelint-problem-matcher@34db1b874c0452909f0696aedef70b723870a583 # tag=v1
- name: Install Node.js dependencies
run: npm ci --no-audit
- name: Run stylelint
run: npm run stylelint:scss
run: npm run stylelint
run-tsc:
name: Run TypeScript build check
@ -113,7 +89,7 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup node environment
uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: 20
check-latest: true
@ -134,7 +110,7 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup node environment
uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: 20
check-latest: true

View file

@ -143,5 +143,20 @@
"value-list-comma-space-after": "always-single-line",
"value-list-comma-space-before": "never",
"value-list-max-empty-lines": 0
},
"overrides": [
{
"files": [
"*.scss",
"**/*.scss"
],
"customSyntax": "postcss-scss",
"plugins": [ "stylelint-scss" ],
"rules": {
"at-rule-no-unknown": null,
"scss/at-rule-no-unknown": true,
"plugin/no-browser-hacks": null
}
}
]
}

View file

@ -1,10 +0,0 @@
{
"extends": [ "./.stylelintrc.json" ],
"customSyntax": "postcss-scss",
"plugins": [ "stylelint-scss" ],
"rules": {
"at-rule-no-unknown": null,
"scss/at-rule-no-unknown": true,
"plugin/no-browser-hacks": null
}
}

View file

@ -78,6 +78,7 @@
- [DinuD](https://github.com/DinuD)
- [Kevin Tan (Valius)](https://github.com/valius)
- [Rasmus Krämer](https://github.com/rasmuslos)
- [ntarelix](https://github.com/ntarelix)
## Emby Contributors

66
package-lock.json generated
View file

@ -29,7 +29,7 @@
"blurhash": "2.0.5",
"classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz",
"classnames": "2.5.1",
"core-js": "3.35.0",
"core-js": "3.35.1",
"date-fns": "2.30.0",
"dompurify": "3.0.1",
"epubjs": "0.3.93",
@ -78,7 +78,7 @@
"@typescript-eslint/eslint-plugin": "5.62.0",
"@typescript-eslint/parser": "5.62.0",
"@uupaa/dynamic-import-polyfill": "1.0.2",
"autoprefixer": "10.4.16",
"autoprefixer": "10.4.17",
"babel-loader": "9.1.3",
"babel-plugin-dynamic-import-polyfill": "1.0.0",
"clean-webpack-plugin": "4.0.0",
@ -106,7 +106,7 @@
"postcss-loader": "7.3.4",
"postcss-preset-env": "9.3.0",
"postcss-scss": "4.0.9",
"sass": "1.69.7",
"sass": "1.70.0",
"sass-loader": "13.3.3",
"source-map-loader": "4.0.2",
"speed-measure-webpack-plugin": "1.5.0",
@ -5873,9 +5873,9 @@
}
},
"node_modules/autoprefixer": {
"version": "10.4.16",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz",
"integrity": "sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==",
"version": "10.4.17",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz",
"integrity": "sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==",
"dev": true,
"funding": [
{
@ -5892,9 +5892,9 @@
}
],
"dependencies": {
"browserslist": "^4.21.10",
"caniuse-lite": "^1.0.30001538",
"fraction.js": "^4.3.6",
"browserslist": "^4.22.2",
"caniuse-lite": "^1.0.30001578",
"fraction.js": "^4.3.7",
"normalize-range": "^0.1.2",
"picocolors": "^1.0.0",
"postcss-value-parser": "^4.2.0"
@ -6546,9 +6546,9 @@
"dev": true
},
"node_modules/caniuse-lite": {
"version": "1.0.30001574",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001574.tgz",
"integrity": "sha512-BtYEK4r/iHt/txm81KBudCUcTy7t+s9emrIaHqjYurQ10x71zJ5VQ9x1dYPcz/b+pKSp4y/v1xSI67A+LzpNyg==",
"version": "1.0.30001579",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001579.tgz",
"integrity": "sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==",
"dev": true,
"funding": [
{
@ -7173,9 +7173,9 @@
}
},
"node_modules/core-js": {
"version": "3.35.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.35.0.tgz",
"integrity": "sha512-ntakECeqg81KqMueeGJ79Q5ZgQNR+6eaE8sxGCx62zMbAIj65q+uYvatToew3m6eAGdU4gNZwpZ34NMe4GYswg==",
"version": "3.35.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.35.1.tgz",
"integrity": "sha512-IgdsbxNyMskrTFxa9lWHyMwAJU5gXOPP+1yO+K59d50VLVAIDAbs7gIv705KzALModfK3ZrSZTPNpC0PQgIZuw==",
"hasInstallScript": true,
"funding": {
"type": "opencollective",
@ -16930,9 +16930,9 @@
"dev": true
},
"node_modules/sass": {
"version": "1.69.7",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.69.7.tgz",
"integrity": "sha512-rzj2soDeZ8wtE2egyLXgOOHQvaC2iosZrkF6v3EUG+tBwEvhqUCzm0VP3k9gHF9LXbSrRhT5SksoI56Iw8NPnQ==",
"version": "1.70.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.70.0.tgz",
"integrity": "sha512-uUxNQ3zAHeAx5nRFskBnrWzDUJrrvpCPD5FNAoRvTi0WwremlheES3tg+56PaVtCs5QDRX5CBLxxKMDJMEa1WQ==",
"dev": true,
"dependencies": {
"chokidar": ">=3.0.0 <4.0.0",
@ -26824,14 +26824,14 @@
"dev": true
},
"autoprefixer": {
"version": "10.4.16",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz",
"integrity": "sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==",
"version": "10.4.17",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.17.tgz",
"integrity": "sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==",
"dev": true,
"requires": {
"browserslist": "^4.21.10",
"caniuse-lite": "^1.0.30001538",
"fraction.js": "^4.3.6",
"browserslist": "^4.22.2",
"caniuse-lite": "^1.0.30001578",
"fraction.js": "^4.3.7",
"normalize-range": "^0.1.2",
"picocolors": "^1.0.0",
"postcss-value-parser": "^4.2.0"
@ -27333,9 +27333,9 @@
"dev": true
},
"caniuse-lite": {
"version": "1.0.30001574",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001574.tgz",
"integrity": "sha512-BtYEK4r/iHt/txm81KBudCUcTy7t+s9emrIaHqjYurQ10x71zJ5VQ9x1dYPcz/b+pKSp4y/v1xSI67A+LzpNyg==",
"version": "1.0.30001579",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001579.tgz",
"integrity": "sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==",
"dev": true
},
"canvas": {
@ -27792,9 +27792,9 @@
}
},
"core-js": {
"version": "3.35.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.35.0.tgz",
"integrity": "sha512-ntakECeqg81KqMueeGJ79Q5ZgQNR+6eaE8sxGCx62zMbAIj65q+uYvatToew3m6eAGdU4gNZwpZ34NMe4GYswg=="
"version": "3.35.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.35.1.tgz",
"integrity": "sha512-IgdsbxNyMskrTFxa9lWHyMwAJU5gXOPP+1yO+K59d50VLVAIDAbs7gIv705KzALModfK3ZrSZTPNpC0PQgIZuw=="
},
"core-js-compat": {
"version": "3.33.2",
@ -34832,9 +34832,9 @@
"dev": true
},
"sass": {
"version": "1.69.7",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.69.7.tgz",
"integrity": "sha512-rzj2soDeZ8wtE2egyLXgOOHQvaC2iosZrkF6v3EUG+tBwEvhqUCzm0VP3k9gHF9LXbSrRhT5SksoI56Iw8NPnQ==",
"version": "1.70.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.70.0.tgz",
"integrity": "sha512-uUxNQ3zAHeAx5nRFskBnrWzDUJrrvpCPD5FNAoRvTi0WwremlheES3tg+56PaVtCs5QDRX5CBLxxKMDJMEa1WQ==",
"dev": true,
"requires": {
"chokidar": ">=3.0.0 <4.0.0",

View file

@ -21,7 +21,7 @@
"@typescript-eslint/eslint-plugin": "5.62.0",
"@typescript-eslint/parser": "5.62.0",
"@uupaa/dynamic-import-polyfill": "1.0.2",
"autoprefixer": "10.4.16",
"autoprefixer": "10.4.17",
"babel-loader": "9.1.3",
"babel-plugin-dynamic-import-polyfill": "1.0.0",
"clean-webpack-plugin": "4.0.0",
@ -49,7 +49,7 @@
"postcss-loader": "7.3.4",
"postcss-preset-env": "9.3.0",
"postcss-scss": "4.0.9",
"sass": "1.69.7",
"sass": "1.70.0",
"sass-loader": "13.3.3",
"source-map-loader": "4.0.2",
"speed-measure-webpack-plugin": "1.5.0",
@ -90,7 +90,7 @@
"blurhash": "2.0.5",
"classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz",
"classnames": "2.5.1",
"core-js": "3.35.0",
"core-js": "3.35.1",
"date-fns": "2.30.0",
"dompurify": "3.0.1",
"epubjs": "0.3.93",
@ -149,9 +149,7 @@
"lint": "eslint \"./\"",
"test": "vitest --watch=false --config vite.config.ts",
"test:watch": "vitest --config vite.config.ts",
"stylelint": "npm run stylelint:css && npm run stylelint:scss",
"stylelint:css": "stylelint \"src/**/*.css\"",
"stylelint:scss": "stylelint --config=\".stylelintrc.scss.json\" \"src/**/*.scss\""
"stylelint": "stylelint \"src/**/*.{css,scss}\""
},
"engines": {
"node": ">=20.0.0",

View file

@ -29,6 +29,10 @@ export default function RootAppRouter({ history }: Readonly<{ history: History}>
return <RouterProvider router={router} />;
}
/**
* Layout component that renders legacy components required on all pages.
* NOTE: The app will crash if these get removed from the DOM.
*/
function RootAppLayout() {
return (
<>

View file

@ -414,7 +414,6 @@ const UserParentalControl: FunctionComponent = () => {
return <AccessScheduleList
key={accessSchedule.Id}
index={index}
Id={accessSchedule.Id}
DayOfWeek={accessSchedule.DayOfWeek}
StartHour={accessSchedule.StartHour}
EndHour={accessSchedule.EndHour}

View file

@ -2,7 +2,6 @@ import React from 'react';
import { RouteObject, redirect } from 'react-router-dom';
import { REDIRECTS } from 'apps/dashboard/routes/_redirects';
import { DASHBOARD_APP_PATHS } from 'apps/dashboard/routes/routes';
import ConnectionRequired from 'components/ConnectionRequired';
import { toAsyncPageRoute } from 'components/router/AsyncRoute';
import { toViewManagerPageRoute } from 'components/router/LegacyRoute';
@ -32,11 +31,5 @@ export const EXPERIMENTAL_APP_ROUTES: RouteObject[] = [
},
/* Redirects for old paths */
...REDIRECTS.map(toRedirectRoute),
/* Ignore dashboard routes */
...Object.entries(DASHBOARD_APP_PATHS).map(([, path]) => ({
path: `/${path}/*`,
element: null
}))
...REDIRECTS.map(toRedirectRoute)
];

View file

@ -1,24 +1,12 @@
import React from 'react';
import { Outlet, useLocation } from 'react-router-dom';
import { Outlet } from 'react-router-dom';
import AppBody from 'components/AppBody';
import { DASHBOARD_APP_PATHS } from 'apps/dashboard/routes/routes';
import Backdrop from 'components/Backdrop';
import AppHeader from 'components/AppHeader';
export default function AppLayout() {
const location = useLocation();
const isNewLayoutPath = Object.values(DASHBOARD_APP_PATHS)
.some(path => location.pathname.startsWith(`/${path}`));
return (
<>
<Backdrop />
<AppHeader isHidden={isNewLayoutPath} />
<AppBody>
<Outlet />
</AppBody>
</>
);
}

View file

@ -1,18 +1,42 @@
import { History } from '@remix-run/router';
import React from 'react';
import { RouterProvider, createHashRouter } from 'react-router-dom';
import { Outlet, RouterProvider, createHashRouter, useLocation } from 'react-router-dom';
import { DASHBOARD_APP_ROUTES } from 'apps/dashboard/routes/routes';
import { useLegacyRouterSync } from 'hooks/useLegacyRouterSync';
import { STABLE_APP_ROUTES } from './routes/routes';
import Backdrop from 'components/Backdrop';
import AppHeader from 'components/AppHeader';
import { DASHBOARD_APP_PATHS, DASHBOARD_APP_ROUTES } from 'apps/dashboard/routes/routes';
const router = createHashRouter([
const router = createHashRouter([{
element: <StableAppLayout />,
children: [
...STABLE_APP_ROUTES,
...DASHBOARD_APP_ROUTES
]);
]
}]);
export default function StableAppRouter({ history }: Readonly<{ history: History }>) {
useLegacyRouterSync({ router, history });
return <RouterProvider router={router} />;
}
/**
* Layout component that renders legacy components required on all pages.
* NOTE: The app will crash if these get removed from the DOM.
*/
function StableAppLayout() {
const location = useLocation();
const isNewLayoutPath = Object.values(DASHBOARD_APP_PATHS)
.some(path => location.pathname.startsWith(`/${path}`));
return (
<>
<Backdrop />
<AppHeader isHidden={isNewLayoutPath} />
<Outlet />
</>
);
}

View file

@ -1,12 +1,13 @@
import { RouteObject, redirect } from 'react-router-dom';
import React from 'react';
import { DASHBOARD_APP_PATHS } from 'apps/dashboard/routes/routes';
import ConnectionRequired from 'components/ConnectionRequired';
import { toAsyncPageRoute } from 'components/router/AsyncRoute';
import { toViewManagerPageRoute } from 'components/router/LegacyRoute';
import { toRedirectRoute } from 'components/router/Redirect';
import AppLayout from '../AppLayout';
import { REDIRECTS } from './_redirects';
import { ASYNC_USER_ROUTES } from './asyncRoutes';
import { LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './legacyRoutes';
@ -27,20 +28,10 @@ export const STABLE_APP_ROUTES: RouteObject[] = [
/* Public routes */
{ index: true, loader: () => redirect('/home.html') },
...LEGACY_PUBLIC_ROUTES.map(toViewManagerPageRoute),
/* Suppress warnings for unhandled routes */
{ path: '*', element: null }
...LEGACY_PUBLIC_ROUTES.map(toViewManagerPageRoute)
]
},
/* Redirects for old paths */
...REDIRECTS.map(toRedirectRoute),
/* Ignore dashboard routes */
...Object.entries(DASHBOARD_APP_PATHS).map(([, path]) => ({
path: `/${path}/*`,
element: null
}))
...REDIRECTS.map(toRedirectRoute)
];

View file

@ -47,8 +47,9 @@ const ConnectionRequired: FunctionComponent<ConnectionRequiredProps> = ({
if (location.pathname === BounceRoutes.Login) {
setIsLoading(false);
} else {
console.debug('[ConnectionRequired] not logged in, redirecting to login page');
navigate(`${BounceRoutes.Login}?serverid=${connectionResponse.ApiClient.serverId()}`);
console.debug('[ConnectionRequired] not logged in, redirecting to login page', location);
const url = encodeURIComponent(location.pathname + location.search);
navigate(`${BounceRoutes.Login}?serverid=${connectionResponse.ApiClient.serverId()}&url=${url}`);
}
return;
case ConnectionState.ServerSelection:

View file

@ -5,7 +5,6 @@ import IconButtonElement from '../../../elements/IconButtonElement';
type AccessScheduleListProps = {
index: number;
Id?: number;
DayOfWeek?: string;
StartHour?: number ;
EndHour?: number;

View file

@ -90,8 +90,6 @@
<div class="detailPageContent">
<div class="detailPagePrimaryContent padded-right">
<div class="detailSection">
<div class="itemMiscInfo nativeName hide"></div>
<form class="trackSelections hide focuscontainer-x">
<div class="selectContainer selectSourceContainer hide trackSelectionFieldContainer flex-shrink-zero">
<select is="emby-select" class="selectSource detailTrackSelect" label=""></select>
@ -110,8 +108,6 @@
<div class="recordingFields hide" style="margin: 0.5em 0 1.5em;"></div>
<div class="detailSectionContent">
<div class="itemLastPlayed hide"></div>
<p class="itemGenres"></p>
<h3 class="tagline"></h3>
<p class="overview"></p>

View file

@ -20,13 +20,13 @@ import { getDefaultBackgroundClass } from '../../../components/cardbuilder/cardB
const enableFocusTransform = !browser.slow && !browser.edge;
function authenticateUserByName(page, apiClient, username, password) {
function authenticateUserByName(page, apiClient, url, username, password) {
loading.show();
apiClient.authenticateUserByName(username, password).then(function (result) {
const user = result.User;
loading.hide();
onLoginSuccessful(user.Id, result.AccessToken, apiClient);
onLoginSuccessful(user.Id, result.AccessToken, apiClient, url);
}, function (response) {
page.querySelector('#txtManualPassword').value = '';
loading.hide();
@ -44,7 +44,7 @@ function authenticateUserByName(page, apiClient, username, password) {
});
}
function authenticateQuickConnect(apiClient) {
function authenticateQuickConnect(apiClient, targetUrl) {
const url = apiClient.getUrl('/QuickConnect/Initiate');
apiClient.ajax({ type: 'POST', url }, true).then(res => res.json()).then(function (json) {
if (!json.Secret || !json.Code) {
@ -77,7 +77,7 @@ function authenticateQuickConnect(apiClient) {
}
const result = await apiClient.quickConnect(data.Secret);
onLoginSuccessful(result.User.Id, result.AccessToken, apiClient);
onLoginSuccessful(result.User.Id, result.AccessToken, apiClient, targetUrl);
}, function (e) {
clearInterval(interval);
@ -108,9 +108,9 @@ function authenticateQuickConnect(apiClient) {
});
}
function onLoginSuccessful(id, accessToken, apiClient) {
function onLoginSuccessful(id, accessToken, apiClient, url) {
Dashboard.onServerChanged(id, accessToken, apiClient);
Dashboard.navigate('home.html');
Dashboard.navigate(url || 'home.html');
}
function showManualForm(context, showCancel, focusPassword) {
@ -192,6 +192,18 @@ export default function (view, params) {
return ApiClient;
}
function getTargetUrl() {
if (params.url) {
try {
return decodeURIComponent(params.url);
} catch (err) {
console.warn('[LoginPage] unable to decode url param', params.url, err);
}
}
return '/home.html';
}
function showVisualForm() {
view.querySelector('.visualLoginForm').classList.remove('hide');
view.querySelector('.manualLoginForm').classList.add('hide');
@ -216,7 +228,7 @@ export default function (view, params) {
context.querySelector('#txtManualName').value = '';
showManualForm(context, true);
} else if (haspw == 'false') {
authenticateUserByName(context, getApiClient(), name, '');
authenticateUserByName(context, getApiClient(), getTargetUrl(), name, '');
} else {
context.querySelector('#txtManualName').value = name;
context.querySelector('#txtManualPassword').value = '';
@ -226,8 +238,7 @@ export default function (view, params) {
});
view.querySelector('.manualLoginForm').addEventListener('submit', function (e) {
appSettings.enableAutoLogin(view.querySelector('.chkRememberLogin').checked);
const apiClient = getApiClient();
authenticateUserByName(view, apiClient, view.querySelector('#txtManualName').value, view.querySelector('#txtManualPassword').value);
authenticateUserByName(view, getApiClient(), getTargetUrl(), view.querySelector('#txtManualName').value, view.querySelector('#txtManualPassword').value);
e.preventDefault();
return false;
});
@ -236,8 +247,7 @@ export default function (view, params) {
});
view.querySelector('.btnCancel').addEventListener('click', showVisualForm);
view.querySelector('.btnQuick').addEventListener('click', function () {
const apiClient = getApiClient();
authenticateQuickConnect(apiClient);
authenticateQuickConnect(getApiClient(), getTargetUrl());
return false;
});
view.querySelector('.btnManual').addEventListener('click', function () {

View file

@ -210,6 +210,14 @@ function supportsDolbyVision(options) {
);
}
function canPlayDolbyVisionHevc(videoTestElement) {
// Profiles 5/7/8 4k@60fps
return !!videoTestElement.canPlayType
&& (videoTestElement.canPlayType('video/mp4; codecs="dvh1.05.09"').replace(/no/, '')
&& videoTestElement.canPlayType('video/mp4; codecs="dvh1.07.09"').replace(/no/, '')
&& videoTestElement.canPlayType('video/mp4; codecs="dvh1.08.09"').replace(/no/, ''));
}
function getDirectPlayProfileForVideoContainer(container, videoAudioCodecs, videoTestElement, options) {
let supported = false;
let profileContainer = container;
@ -927,7 +935,7 @@ export default function (options) {
av1VideoRangeTypes += '|HLG';
}
if (supportsDolbyVision(options)) {
if (supportsDolbyVision(options) && canPlayDolbyVisionHevc(videoTestElement)) {
hevcVideoRangeTypes += '|DOVI';
}

View file

@ -38,5 +38,7 @@
"AddToPlayQueue": "დაკვრის რიგში დამატება",
"AgeValue": "({0} წლის)",
"AirDate": "ეთერში გაშვების თარიღი",
"AllLibraries": "ყველა ბიბლიოთეკა"
"AllLibraries": "ყველა ბიბლიოთეკა",
"AllowedRemoteAddressesHelp": "IP მისამართების ან IP/ქსელური მასკის ჩანაწერების ძიმეთი დაყოფილი სია ქსელებისთვის, რომლებიც შეძლებენ დაშორებულად დაკავშირებას. თუ დატოვებთ ცარიელს, ყველა დაშორებული მისამართი იქნება დაშვებული.",
"AllowCollectionManagement": "ამ მომხმარებლისთვის კოლექციების მართვის საშუალების მიცემა"
}

View file

@ -1194,7 +1194,7 @@
"MusicArtist": "Wykonawca muzyczny",
"MusicVideo": "Teledysk",
"Option3D": "3D",
"OptionCaptionInfoExSamsung": "RozszerzoneInfoNagłówka (Samsung)",
"OptionCaptionInfoExSamsung": "CaptionInfoEx (Samsung)",
"OptionIsHD": "HD",
"OptionIsSD": "SD",
"OptionLoginAttemptsBeforeLockout": "Określ ile nieprawidłowych prób logowania można wykonać przed wystąpieniem blokady.",

View file

@ -699,7 +699,7 @@
"HeaderCancelSeries": "Cancelar gravação de série",
"HeaderCancelRecording": "Cancelar gravação",
"HeaderAudioBooks": "Áudiolivro",
"HeaderAllowMediaDeletionFrom": "Permitir remoção de multimédia a partir de",
"HeaderAllowMediaDeletionFrom": "Permitir remoção de multimídia a partir de",
"HeaderAlert": "Alerta",
"HeaderAddToPlaylist": "Adicionar à Lista de Reprodução",
"HDPrograms": "Programas em Alta-Definição",
@ -783,8 +783,8 @@
"LabelBurnSubtitles": "Integrar legendas",
"LabelBirthYear": "Ano de nascimento",
"LabelBirthDate": "Data de nascimento",
"LabelBindToLocalNetworkAddressHelp": "Indique um endereço IP de um interface de rede local para colocar o servidor à escuta. Caso deixe em branco, o servidor ficará à escuta em todas os interfaces de rede disponíveis. Alterar este parâmetro requer reiniciar o servidor.",
"LabelBindToLocalNetworkAddress": "Endereço local para colocar o servidor à escuta",
"LabelBindToLocalNetworkAddressHelp": "Substituir o endereço IP local do servidor HTTP. Se deixado em branco, o servidor irá vincular-se a todos os endereços disponíveis. A alteração deste valor requer uma reinicialização.",
"LabelBindToLocalNetworkAddress": "Vincular ao endereço de rede local",
"LabelAutomaticallyRefreshInternetMetadataEvery": "Actualizar metadados automaticamente a partir da Internet",
"LabelAuthProvider": "Fornecedor de autenticação",
"LabelAllowedRemoteAddressesMode": "Tipo de filtro de IP remoto",
@ -830,7 +830,7 @@
"RepeatMode": "Modo de Repetição",
"ServerRestartNeededAfterPluginInstall": "O Jellyfin terá que reiniciar após instalar uma extensão.",
"MessageNoPluginConfiguration": "Esta extensão não tem definições que possa alterar.",
"MessagePluginInstallDisclaimer": "As extensões desenvolvidas por membros da comunidade são uma ótima maneira de melhorar a experiência com funcionalidades adicionais. Antes de proceder à instalação, tenha em atenção que estas podem alterar determinados comportamentos no servidor, como o aumento da duração de análise de bibliotecas, processamento adicional em segundo plano e redução da estabilidade do sistema.",
"MessagePluginInstallDisclaimer": "AVISO: Instalar um plugin de terceiros traz riscos. Estes podem conter código instável ou malicioso e podem mudar a qualquer momento. Instale apenas plugins de autores em quem você confia e esteja ciente dos possíveis efeitos que isso pode ter, incluindo consultas de serviços externos, varreduras de biblioteca mais longas ou processamento adicional em segundo plano.",
"MessagePluginConfigurationRequiresLocalAccess": "Para configurar esta extensão, inicie sessão localmente no servidor.",
"HeaderPluginInstallation": "Instalação de extensão",
"MessagePluginInstalled": "A extensão foi instalada com sucesso. O servidor terá que reiniciar para aplicar as alterações.",
@ -1233,7 +1233,7 @@
"AllowFfmpegThrottling": "Desacelerar transcodificações",
"PreferEmbeddedTitlesOverFileNamesHelp": "Determina o título a apresentar por defeito quando não é possível carregar metadados locais nem da Internet.",
"OptionSaveMetadataAsHiddenHelp": "Alterar esta definição apenas afetará metadados guardados futuramente. Ficheiros existentes serão atualizados assim que forem alterados pelo servidor.",
"ButtonSyncPlay": "SyncPlay",
"ButtonSyncPlay": "'SyncPlay'",
"LabelRepositoryUrl": "URL do Repositório",
"HeaderNewRepository": "Novo repositório",
"MessageNoRepositories": "Sem repositórios.",
@ -1413,7 +1413,7 @@
"SmallCaps": "Maiúsculas reduzidas",
"LabelTonemappingRange": "Alcance do Tone Mapping",
"TonemappingAlgorithmHelp": "O Tone Mapping pode ser afinado. Se não estiver familiarizado com estas opções, mantenha-as nas opções padrão. O valor recomendado é 'BT.2390'.",
"AllowTonemappingHelp": "Tone-mapping can transform the dynamic range of a video from HDR to SDR while maintaining image details and colors, which are very important information for representing the original scene. Currently works only with 10bit HDR10, HLG and DoVi videos. This requires the corresponding OpenCL or CUDA runtime.",
"AllowTonemappingHelp": "O mapeamento de tons pode transformar a faixa dinâmica de um vídeo de HDR para SDR, mantendo os detalhes e cores da imagem, que são informações muito importantes para representar a cena original. Atualmente funciona apenas com vídeos HDR10 de 10 bits, HLG e DoVi. Isto requer OpenCL ou CUDA correspondente.",
"LabelMaxMuxingQueueSizeHelp": "Número máximo de pacotes armazenados em <i>buffer</i> enquanto aguardam que todas as transmissões iniciem. Tente aumentá-lo caso se depare com o seguinte erro nos <i>registos</i> do FFmpeg \"Too many packets buffered for output stream\". O valor recomendado é 2048.",
"DeleteAll": "Apagar tudo",
"DeleteDevicesConfirmation": "Tem a certeza que deseja remover todos os dispositivos? Todas as outras sessões serão terminadas. Os dispositivos reaparecerão da próxima vez que um utilizador iniciar sessão.",
@ -1425,7 +1425,7 @@
"AspectRatioCover": "Capa",
"EnableFallbackFontHelp": "Ativar fontes de contingência personalizadas. Estas podem evitar o problema da renderização incorreta das legendas.",
"EnableFallbackFont": "Ativar fontes de contingência",
"LabelFallbackFontPathHelp": "Indicar uma pasta que contém fontes de contingência para a renderização de legendas ASS/SSA. O tamanho máximo de todas as fontes é 20MB. Recomendam-se formatos ligeiros, por exemplo woff2.",
"LabelFallbackFontPathHelp": "Essas fontes são usadas por alguns clientes para renderizar legendas. Consulte a documentação para obter mais informações.",
"LabelFallbackFontPath": "Localização da pasta de fontes de contingência",
"HeaderSelectFallbackFontPathHelp": "Procurar ou digitar a localização da pasta de fontes de contingência, utilizados para renderizar as legendas ASS/SSA.",
"HeaderSelectFallbackFontPath": "Selecionar Localização da Pasta de Fontes de Contingência",
@ -1494,7 +1494,7 @@
"MessagePlaybackError": "Ocorreu um erro na reprodução deste ficheiro no se recetor Google Cast.",
"MessageChromecastConnectionError": "O seu recetor Google Cast não pode contatar o servidor Jellyfin. Por favor, verifique a ligação e tente de novo.",
"YoutubeDenied": "Não é permitida a reprodução do vídeo solicitado em reprodutores embutidos.",
"PreferFmp4HlsContainerHelp": "Preferir utilizar fMP4 como o contentor padrão para HLS, que torna possível a transmissão direta do conteùdo HEVC em dispositivos que o suportam.",
"PreferFmp4HlsContainerHelp": "Preferir utilizar fMP4 como o contentor padrão para HLS, que torna possível a transmissão direta do conteúdo HEVC e AV1 em dispositivos que os suportam.",
"PreferFmp4HlsContainer": "Preferir o Contentor da Multimédia fMP4-HLS",
"LabelSyncPlayInfo": "Info do SyncPlay",
"LabelRemuxingInfo": "Info da Remuxing",
@ -1687,7 +1687,7 @@
"SubtitleMagenta": "Magenta",
"SubtitleRed": "Vermelho",
"SubtitleYellow": "Amarelo",
"Featurette": "Featurette",
"Featurette": "Destaque",
"Studio": "Estúdio",
"StereoDownmixAlgorithmHelp": "Algoritmo usado para fazer downmix de áudio multicanal para estéreo.",
"Unreleased": "Ainda não foi lançado",
@ -1718,7 +1718,7 @@
"EnableAudioNormalization": "Normalização de áudio",
"HeaderRecordingMetadataSaving": "Gravar metadados",
"OptionDateEpisodeAdded": "Data de adição do episódio",
"LabelEnableLUFSScanHelp": "Ative a verificação LUFS para música (isso levará mais tempo e mais recursos).",
"LabelEnableLUFSScanHelp": "Os clientes podem normalizar a reprodução de áudio para obter um volume semelhante nas faixas. Isso tornará as varreduras da biblioteca mais demoradas e consumirá mais recursos.",
"LabelEnableLUFSScan": "Ative a verificação LUFS",
"HeaderDummyChapter": "Imagens dos Capítulos",
"LabelEnableAudioVbrHelp": "A taxa de bits variável oferece melhor qualidade relativamente à taxa de bits média, mas, em alguns casos raros, pode causar problemas de buffer e compatibilidade.",
@ -1760,5 +1760,11 @@
"AiTranslated": "Traduzido por inteligencia artificial",
"HearingImpairedShort": "HI/SDH",
"LabelSelectAudioNormalization": "Normalização de som",
"LabelAlbumGain": "Ganho do Album"
"LabelAlbumGain": "Ganho do Album",
"BackdropScreensaver": "Fundo do protetor de ecrã",
"LabelIsHearingImpaired": "Para deficientes auditivos (SDH)",
"LabelBackdropScreensaverIntervalHelp": "O tempo em segundos entre diferentes cenários ao usar o protetor de ecrã de cenário.",
"LabelBackdropScreensaverInterval": "Intervalo do fundo do protetor de ecrã",
"HeaderAllRecordings": "Todas as Gravações",
"SelectAudioNormalizationHelp": "Ganho de faixa - ajusta o volume de cada faixa para que sejam reproduzidas com o mesmo volume. Ganho do álbum - ajusta o volume de todas as faixas apenas de um álbum, mantendo a faixa dinâmica do álbum."
}

View file

@ -83,7 +83,7 @@
"Screenshot": "Captura de Ecrã",
"Schedule": "Agendamentos",
"ScanForNewAndUpdatedFiles": "Procurar ficheiros novos ou actualizados",
"SaveSubtitlesIntoMediaFoldersHelp": "Guardar ficheiros de legendas junto aos ficheiros vídeo facilita a sua gestão.",
"SaveSubtitlesIntoMediaFoldersHelp": "Guardar ficheiros de legendas junto aos ficheiros vídeo irá facilitar a sua gestão.",
"SaveSubtitlesIntoMediaFolders": "Guardar legendas nas pastas multimédia",
"Save": "Guardar",
"Saturday": "Sábado",
@ -92,7 +92,7 @@
"ResumeAt": "Retomar a partir de {0}",
"ReplaceExistingImages": "Substituir imagens existentes",
"ReplaceAllMetadata": "Substituir todos os metadados",
"RepeatOne": "Repetir este",
"RepeatOne": "Repetir um",
"RepeatMode": "Modo de repetição",
"Repeat": "Repetir",
"RemoveFromPlaylist": "Remover da lista de reprodução",
@ -105,11 +105,11 @@
"RecommendationDirectedBy": "Realizado por {0}",
"RecommendationBecauseYouWatched": "Porque viu {0}",
"RecommendationBecauseYouLike": "Porque gosta de {0}",
"Raised": "Alto relevo",
"Raised": "Elevado",
"Programs": "Programas",
"Producer": "Produtor",
"MessagePluginInstalled": "A extensão foi instalada com sucesso. O servidor necessitará de ser reiniciado para aplicar as alterações.",
"PleaseSelectTwoItems": "Por favor seleccione pelo menos dois itens.",
"PleaseSelectTwoItems": "Por favor selecione pelo menos dois itens.",
"PleaseRestartServerName": "Por favor, reinicie o Servidor Jellyfin - {0}.",
"PleaseEnterNameOrId": "Por favor, digite um nome ou Id externo.",
"PleaseConfirmPluginInstallation": "Por favor clique em OK para confirmar que leu o conteúdo acima e que deseja prosseguir com a instalação da extensão.",
@ -123,21 +123,21 @@
"PlaybackData": "Dados de Reprodução",
"PlayAllFromHere": "Reproduzir todos a partir daqui",
"Play": "Reproduzir",
"PlaceFavoriteChannelsAtBeginning": "Mover canais favoritos para o início",
"PlaceFavoriteChannelsAtBeginning": "Colocar canais favoritos no início",
"PinCodeResetConfirmation": "Tem a certeza de que devia repôr o código PIN?",
"PinCodeResetComplete": "O código PIN foi redefinido.",
"Photos": "Fotografias",
"PerfectMatch": "Correspondência perfeita",
"People": "Pessoas",
"PasswordSaved": "Palavra-passe guardada.",
"PasswordResetProviderHelp": "Seleccione um provedor de reposição de palavra-passe a ser usado quando um utilizador requisitar uma reposição de palavra-passe.",
"PasswordResetConfirmation": "Tem a certeza que deseja redefinir a palavra-passe?",
"PasswordResetComplete": "A palavra-passe foi redefinida.",
"PasswordMatchError": "A palavra-passe e a confirmação devem coincidir.",
"PasswordSaved": "Palavra passe guardada.",
"PasswordResetProviderHelp": "Selecione um fornecedor de reposição de palavra passe a ser usado quando um utilizador requisitar uma redefinição de palavra passe.",
"PasswordResetConfirmation": "Tem a certeza que deseja redefinir a palavra passe?",
"PasswordResetComplete": "A palavra passe foi redefinida.",
"PasswordMatchError": "A palavra passe e a palavra passe de confirmação devem ser iguais.",
"ParentalRating": "Classificação parental",
"PackageInstallFailed": "A instalação de {0} falhou.",
"PackageInstallCompleted": "A instalação de {0} terminou.",
"PackageInstallCancelled": "A instalação de {0} foi cancelada.",
"PackageInstallFailed": "A instalação de {0} (versão{1}) falhou.",
"PackageInstallCompleted": "A instalação de {0} (versão {1}) foi concluída.",
"PackageInstallCancelled": "A instalação de {0} (versão {1}) foi cancelada.",
"Overview": "Resumo",
"OriginalAirDateValue": "Data de estreia original: {0}",
"OptionWeekly": "Semanalmente",
@ -590,10 +590,10 @@
"MessageUnableToConnectToServer": "Não foi possível estabelecer ligação ao servidor. Por favor, certifique-se que o servidor está a correr e tente de novo.",
"MessageTheFollowingLocationWillBeRemovedFromLibrary": "As seguintes pastas multimédia serão removidas da Biblioteca",
"MessageReenableUser": "Veja abaixo como reactivar",
"MessagePluginInstallDisclaimer": "As extensões desenvolvidas pela comunidade Jellyfin adicionam novas funcionalidades e benefícios, sendo uma ótima forma de estender a experiência de utilização do Jellyfin. Antes de instalar uma extensão, considere os impactos que pode ter no Servidor Jellyfin, como tempos de atualização da Biblioteca mais longos, adicional processamento em segundo plano e reduzida estabilidade do sistema.",
"MessagePluginInstallDisclaimer": "AVISO: Instalar um plugin de terceiros traz riscos. Ele pode conter código instável ou malicioso e pode mudar a qualquer momento. Instale apenas plugins de autores em quem você confia e esteja ciente dos possíveis efeitos que isso poderá ter, incluindo consultas de serviços externos, varreduras de biblioteca mais longas ou processamento adicional em segundo plano.",
"MessagePluginConfigurationRequiresLocalAccess": "Para configurar esta extensão, inicie sessão localmente no servidor.",
"MessagePleaseEnsureInternetMetadata": "Certifique-se que a transferência de metadados da Internet está activada.",
"MessagePasswordResetForUsers": "As palavras-passe dos utilizadores abaixo foram repostas. Deverão utilizar o PIN de reposição de palavra-passe para fazer login.",
"MessagePasswordResetForUsers": "Os seguintes usuários tiveram suas senhas redefinidas. Agora eles podem fazer login com os códigos PIN usados para fazer a redefinição.",
"MessageNothingHere": "Nada aqui.",
"MessageNoTrailersFound": "Instale o canal de trailers para aprimorar sua experiência de cinema, adicionando uma biblioteca de trailers da Internet.",
"MessageNoPluginsInstalled": "Não existe nenhuma extensão instalada.",
@ -734,7 +734,7 @@
"ErrorPleaseSelectLineup": "Por favor selecione a programação e tente novamente. Se não houver programações disponíveis, verifique se o seu nome de utilizador, senha e código postal estão correctos.",
"ErrorStartHourGreaterThanEnd": "A hora de fim deve ser superior à hora de início.",
"ErrorGettingTvLineups": "Ocorreu um erro ao transferir a programação de TV. Por favor, certifique-se que a sua informação está correcta e tente novamente.",
"ErrorDeletingItem": "Ocorreu um erro ao apagar o item do servidor. Por favor, verifique se o Jellyfin tem accessp de escrita na pasta e tente de novo.",
"ErrorDeletingItem": "Ocorreu um erro ao apagar o item do servidor. Por favor, verifique se o Jellyfin tem permissão de escrita na pasta e tente de novo.",
"ErrorAddingXmlTvFile": "Ocorreu um erro ao aceder ao ficheiro XmlTV. Por favor, garanta que o ficheiro está acessível e tente de novo.",
"ErrorAddingTunerDevice": "Ocorreu um erro ao adicionar o dispositivo de sintonização. Por favor, garanta que está acessível e tente de novo.",
"ErrorAddingMediaPathToVirtualFolder": "Ocorreu um erro ao adicionar a localização dos seus ficheiros. Por favor, verifique se o caminho é valido e se o Jellyfin tem acesso à localização.",
@ -951,7 +951,7 @@
"AccessRestrictedTryAgainLater": "O acesso está atualmente restrito. Por favor, tente novamente mais tarde.",
"Absolute": "Absoluto",
"AlwaysPlaySubtitlesHelp": "As legendas correspondentes à preferência de idioma serão carregadas, independentemente do idioma do áudio.",
"SearchForMissingMetadata": "Procurar metadados ausentes",
"SearchForMissingMetadata": "Procurar metadados em falta",
"ScanLibrary": "Analisar biblioteca",
"HeaderDeleteItem": "Remover item",
"HeaderDeleteDevice": "Apagar Dispositivo",
@ -1154,14 +1154,14 @@
"AlbumArtist": "Álbum do Artista",
"Quality": "Qualidade",
"Previous": "Anterior",
"PictureInPicture": "Vídeo em janela",
"PictureInPicture": "Imagem em janela flutuante",
"OptionRequirePerfectSubtitleMatchHelp": "Solicitar a \"correspondência perfeita\" filtrará as legendas incluindo apenas aquelas que foram testadas com o arquivo de vídeo. Desmarcar isto aumentará a probabilidade de baixar legendas, mas poderá obter legendas incorretas ou não sincronizadas.",
"StopRecording": "Parar gravação",
"ShowYear": "Exibir ano",
"ShowTitle": "Exibir título",
"SettingsWarning": "Mudar estes valores pode causar instabilidade ou falhas de conexão. Se tiver problemas, recomendamos restaurar os valores originais.",
"ServerNameIsShuttingDown": "Servidor Jellyfin - {0} está desligando.",
"ServerNameIsRestarting": "Servidor Jellyfin - {0} está reiniciando.",
"ServerNameIsShuttingDown": "O servidor Jellyfin - {0} está a desligar.",
"ServerNameIsRestarting": "O servidor Jellyfin - {0} está a reiniciar.",
"SeriesYearToPresent": "{0} - Atualmente",
"SeriesCancelled": "Série cancelada.",
"SelectAdminUsername": "Por favor, selecione um usuário para a conta de administrador.",
@ -1179,15 +1179,15 @@
"OptionAutomaticallyGroupSeries": "Mesclar automaticamente séries que estão espalhadas por várias pastas",
"OptionAllowSyncTranscoding": "Permitir download e sincronização de mídia que requeiram transcodificação",
"OptionForceRemoteSourceTranscoding": "Força a transcodificação de fontes de mídia remotas, como TV ao vivo",
"PreferEmbeddedTitlesOverFileNames": "Preferir títulos incorporados sobre nomes de arquivos",
"PreferEmbeddedTitlesOverFileNames": "Preferir títulos incorporados ao invés dos nomes dos arquivos",
"OptionSaveMetadataAsHiddenHelp": "Alterar isso será aplicado aos novos metadados salvos daqui para frente. Os arquivos de metadados existentes serão atualizados na próxima vez em que forem salvos pelo Jellyfin Server.",
"OptionRegex": "Regex",
"OptionLoginAttemptsBeforeLockoutHelp": "Um valor zero significa herdar o padrão de três tentativas para usuários normais e cinco para administradores. Definir como -1 desativará o recurso.",
"OptionExtractChapterImage": "Ativar extração de imagem de capítulo",
"PreferEmbeddedEpisodeInfosOverFileNames": "Preferir informações de episódios incorporados sobre nomes de arquivos",
"PreferEmbeddedEpisodeInfosOverFileNamesHelp": "Isso usa as informações do episódio dos metadados incorporados, se disponíveis.",
"PreferEmbeddedTitlesOverFileNamesHelp": "Determina o título quando nenhum metadado da Internet ou local está disponível.",
"PlaybackErrorNoCompatibleStream": "Este cliente não é compatível com a mídia e o servidor não está enviando um formato de mídia compatível.",
"PreferEmbeddedEpisodeInfosOverFileNames": "Preferir informações de episódios incorporados ao invés de nomes de arquivos",
"PreferEmbeddedEpisodeInfosOverFileNamesHelp": "Usar os metadados incorporados para informações do episódio, se disponíveis.",
"PreferEmbeddedTitlesOverFileNamesHelp": "Determina o título de exibição a ser usado quando nenhum metadado da Internet ou local estiver disponível.",
"PlaybackErrorNoCompatibleStream": "Este cliente não é compatível com a mídia e o servidor não está a enviar um formato de mídia compatível.",
"Person": "Pessoa",
"LabelRequireHttpsHelp": "Se marcado, o servidor redirecionará automaticamente todas as solicitações por HTTP para HTTPS. Isso não terá efeito se o servidor não estiver escutando HTTPS.",
"LabelRequireHttps": "Requer HTTPS",
@ -1372,11 +1372,11 @@
"Small": "Pequeno",
"QuickConnectActivationSuccessful": "Activado com sucesso",
"SaveChanges": "Gravar alterações",
"PreferEmbeddedExtrasTitlesOverFileNames": "Preferir informações de legendas incorporados sobre nomes de arquivos para os extras",
"PreferEmbeddedExtrasTitlesOverFileNames": "Preferir títulos incorporados ao invés dos nomes dos arquivos para os extras",
"AllowEmbeddedSubtitlesAllowAllOption": "Permitir tudo",
"AllowEmbeddedSubtitlesAllowImageOption": "Permitir imagens",
"Preview": "Prever",
"Premieres": "Estréias",
"Preview": "Amostra",
"Premieres": "Estreias",
"Production": "Produção",
"Profile": "Perfil",
"PreviousTrack": "Faixa anterior",
@ -1385,7 +1385,7 @@
"MediaInfoBlPresentFlag": "Flag de pré-definição BL DV",
"ReleaseGroup": "Grupo do lançamento",
"Primary": "Primário",
"RefreshDialogHelp": "Os metadados são refrescados com base nas configurações que estão activos no painel principal.",
"RefreshDialogHelp": "Os metadados são atualizados com base nas configurações e nos serviços de Internet habilitados no painel principal.",
"Cursive": "Cursivo",
"ItemDetails": "Detalhe do item",
"HomeVideosPhotos": "Videos e Fotos",
@ -1406,7 +1406,7 @@
"LabelDummyChapterCount": "Limite",
"HeaderRecordingMetadataSaving": "Gravando Metadados",
"AllowEmbeddedSubtitlesAllowTextOption": "Permitir texto",
"Premiere": "Estréia",
"Premiere": "Estreia",
"PreviousChapter": "Capitulo anterior",
"LabelDummyChapterDurationHelp": "O intervalo entre capítulos forçados. Ajuste para 0 para desabilitar geração de capítulos forçados. As mudanças não terão efeito nos capítulos forçados já criados.",
"AllowCollectionManagement": "Permite que este usuário gerencie as coleções",
@ -1420,7 +1420,7 @@
"EnableAudioNormalizationHelp": "A normalização de áudio vai adicionar um ganho constante para manter a média em um nível desejável (-18db).",
"LabelParallelImageEncodingLimit": "Limite de codificação de imagens em paralelo",
"LabelEnableLUFSScan": "Habilitar busca LUFS",
"LabelEnableLUFSScanHelp": "Habilitar busca LUFS para música (Isto necessitará de mais tempo e recursos).",
"LabelEnableLUFSScanHelp": "Os clientes podem normalizar a reprodução de áudio para obter um volume igual entre as faixas. Isso tornará as varreduras da biblioteca mais demoradas e consumirá mais recursos.",
"LabelParallelImageEncodingLimitHelp": "Quantidade máxima de imagens codificadas que são permitidas rodar em paralelo. Ajustar este valor para 0 ira selecionar um limite baseado nas especificaçõrs do seu sistema.",
"GoHome": "Ir ao início",
"GridView": "Visão em grade",
@ -1430,5 +1430,46 @@
"LabelSegmentKeepSeconds": "Tempo em segundos para manter os segmentos",
"LabelSegmentKeepSecondsHelp": "Tempo em segundos no qual o segmento deve ser mantido antes de ser reescrito. Deve ser maior que \"Acelerar depois\". So funciona se Deletar Segmentos estiver ativo.",
"LabelThrottleDelaySeconds": "acelerar depois",
"HeaderAllRecordings": "Todas as gravações"
"HeaderAllRecordings": "Todas as gravações",
"PreferEmbeddedExtrasTitlesOverFileNamesHelp": "Os extras geralmente têm o mesmo nome incorporado do parente, marque isto para usar títulos incorporados para eles de qualquer maneira.",
"QuickConnectAuthorizeSuccess": "Você autenticou o seu dispositivo com sucesso!",
"QuickConnectNotActive": "O 'Quick Connect' não está ativo neste servidor",
"ResolutionMatchSource": "Mesma que a fonte",
"SeriesRecordingScheduled": "Gravação da Serie agendada.",
"RememberSubtitleSelections": "Definir faixa de legendas com base no item anterior",
"RememberAudioSelections": "Defina a faixa de áudio com base no item anterior",
"RememberAudioSelectionsHelp": "Tente definir a faixa de áudio para a correspondência mais próxima do último vídeo.",
"RememberSubtitleSelectionsHelp": "Tente definir a faixa de legendas para a correspondência mais próxima do último vídeo.",
"ResetPassword": "Redefinir Palavra Passe",
"LabelSyncPlaySettingsMaxDelaySpeedToSyncHelp": "Atraso máximo de reprodução (em ms) após o qual SkipToSync é usado em vez de SpeedToSync.",
"LabelSyncPlaySettingsMinDelaySpeedToSyncHelp": "Atraso mínimo da reprodução (em ms) após o qual o SpeedToSync tenta corrigir a posição de reprodução.",
"QuickConnectNotAvailable": "Peça ao administrador do servidor para ativar o 'Quick Connect'",
"Remixer": "'Remixer'",
"QuickConnectAuthorizeCode": "Introduzir o código {0} para entrar",
"QuickConnect": "'Quick Connect'",
"SelectServer": "Selecionar Servidor",
"PosterCard": "Poster",
"SortByValue": "Ordenar por {0}",
"PathNotFound": "O caminho não foi encontrado. Certifique-se de que o caminho é válido e tente novamente.",
"PlaybackErrorPlaceHolder": "Este é um espaço reservado para mídia física que o Jellyfin não consegue reproduzir. Por favor insira o disco para reproduzir.",
"ProductionLocations": "Locais da produção",
"Photo": "Foto",
"SearchResultsEmpty": "Desculpe! Não foram encontrados resultados para \"{0}\"",
"ShowParentImages": "Mostrar imagens das series",
"SaveRecordingNFO": "Guardar metadados EPG da gravação no NFO",
"PersonRole": "como {0}",
"AllowEmbeddedSubtitles": "Desativar diferentes tipos de legendas incorporadas",
"QuickConnectDeactivated": "O 'Quick Connect' foi desativado antes que o pedido de login pudesse ser aprovado",
"QuickConnectInvalidCode": "Código 'Quick Connect' inválido",
"QuickConnectDescription": "Para fazer login com o 'Quick Connect', selecione o botão 'Quick Connect' no dispositivo a partir do qual você quer fazer login e insira o código exibido abaixo.",
"RefreshQueued": "Actualização em fila.",
"PlaybackRate": "Velocidade de Reprodução",
"AllowEmbeddedSubtitlesHelp": "Desativar as legendas incorporadas nos contentores de mídia. Requer uma atualização completa da biblioteca.",
"LabelEnableGamepad": "Ativar Gamepad",
"LabelTonemappingThreshold": "Limite de mapeamento de tom",
"LabelTonemappingRange": "Intervalo de mapeamento de tons",
"PasswordRequiredForAdmin": "É necessária uma palavra passe para contas de administrador.",
"PleaseConfirmRepositoryInstallation": "Clique em OK para confirmar que leu o texto acima e deseja prosseguir com a instalação do repositório de plug-ins.",
"LabelThrottleDelaySecondsHelp": "Tempo em segundos após o qual o transcodificador será limitado. Deve ser grande o suficiente para que o cliente mantenha um buffer saudável. Só funciona se a limitação estiver ligada.",
"QuickConnectAuthorizeFail": "Código 'Quick Connect' desconhecido"
}