Compare commits

..

38 Commits

Author SHA1 Message Date
Joshua M. Boniface
fc461a830d Fix Release ref for Fedora 2020-08-30 16:45:54 -04:00
Joshua M. Boniface
e6e5f38a0d Bump version to 10.6.4 2020-08-30 16:45:40 -04:00
dkanada
756e322e1c Merge pull request #1820 from thornbill/fix-guide-margin
Remove horizontal margins on guide

(cherry picked from commit 9e3a27266c)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-08-30 16:15:07 -04:00
Anthony Lavado
c9ed8c750e Merge pull request #1823 from thornbill/extra-blury
Set background color on blurhash image load

(cherry picked from commit 5a2c0beec5)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-08-30 16:14:54 -04:00
Joshua M. Boniface
5f1af65c2e Merge pull request #1849 from brianjmurrell/patch-1
Add BuildRequires: git to Fedora specfile
2020-08-30 16:05:29 -04:00
Brian J. Murrell
ff88922f19 Add BuildRequires: git to Fedora specfile
Sadly the yarn RPM at https://dl.yarnpkg.com/rpm/ uses git but doesn't
add it as a BuildRequires:.

This really should be reported upstream at yarnpkg.com.

Signed-off-by: Brian J. Murrell <brian@interlinx.bc.ca>
2020-08-27 12:29:07 -04:00
dkanada
47700dc29c Merge pull request #1818 from dmitrylyzo/fix-non-es6
Fix non-ES6 import [10.6.z]
2020-08-18 23:15:12 +09:00
Dmitry Lyzo
c2ebc35080 Fix non-ES6 import 2020-08-18 15:01:41 +03:00
Joshua M. Boniface
d040177525 Bump version to 10.6.3 2020-08-16 19:48:04 -04:00
dkanada
cac6b42dab Merge pull request #1799 from matjaz321/checkbox-space-ff-issue
Hitting space to check/uncheck checkboxes doesn't work on firefox

(cherry picked from commit fea28f7277)
2020-08-16 19:47:09 -04:00
dkanada
15e9b645f2 Merge pull request #1794 from bugfixin/master
Remove extraneous pageContainer element from videoOSD

(cherry picked from commit 926f1cbbcc)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-08-16 19:29:20 -04:00
dkanada
1833b348e9 Merge pull request #1748 from dmitrylyzo/fix-old-edge
Fix old Edge loading

(cherry picked from commit 73e3a94755)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-08-16 19:29:17 -04:00
dkanada
ccb74610aa Merge pull request #1542 from dmitrylyzo/fix-osd-lock
Fix OSD lock

(cherry picked from commit 04b2763447)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-08-16 19:21:38 -04:00
Joshua M. Boniface
5c37ee6276 Bump version to 10.6.2 2020-08-02 20:26:00 -04:00
dkanada
e25721cb34 Merge pull request #1734 from dmitrylyzo/fix-plugin-configuration
Fix injecting of view with embedded script

(cherry picked from commit 6607718edb)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-08-02 20:24:11 -04:00
dkanada
f11b27fc14 Merge pull request #1701 from MrTimscampi/mobile-logo
Use emblem when loading on mobile

(cherry picked from commit 60d9af0d75)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-08-02 20:15:48 -04:00
dkanada
26d29dc2cb Merge pull request #1686 from Larvitar/master
Fix issue with nowplaying page when item.Album or item.Artists are null.

(cherry picked from commit b1aa18e7e7)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-08-02 20:15:48 -04:00
Anthony Lavado
537b3a3351 Merge pull request #1684 from thornbill/fix-ios-fullscreeen
Fix fullscreen video in iOS Safari

(cherry picked from commit 9b6a90ffdd)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-08-02 20:15:47 -04:00
dkanada
ab58d3c3a1 Merge pull request #1681 from jellyfin/book-paging
Add paging in book player with touch events

(cherry picked from commit cefdde1848)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-08-02 20:15:47 -04:00
dkanada
e7be594b8f Merge pull request #1678 from jellyfin/banner
Fix banner height and use primary image as fallback

(cherry picked from commit 34d0b67f0e)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-08-02 20:15:47 -04:00
dkanada
229294aecc Merge pull request #1672 from MrTimscampi/browsers
Adjust target browsers

(cherry picked from commit feab1aca89)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-08-02 20:15:47 -04:00
dkanada
e41c1854d0 Merge pull request #1669 from joshuaboniface/fix-ci-docker
Flip quoting in variable set command

(cherry picked from commit 40b98bb3d4)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-08-02 20:15:47 -04:00
Anthony Lavado
e355fcdac0 Merge pull request #1667 from joshuaboniface/fix-ci-docker
Get and tag with actual release version in CI

(cherry picked from commit 2c53a329e7)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-08-02 20:15:47 -04:00
dkanada
453d225c84 Merge pull request #1665 from joshuaboniface/fix-bump-version
Fix bump_version so it works properly

(cherry picked from commit c8966a7f7d)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-08-02 20:15:47 -04:00
dkanada
ec9ab39d26 Merge pull request #1656 from dmitrylyzo/fix-plugin-install
Fix CircleOfDeath on plugin install

(cherry picked from commit 89e584686e)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-08-02 20:15:47 -04:00
Joshua M. Boniface
c2d9ca2af9 Fix bad Debian package name in changelog 2020-07-27 18:57:44 -04:00
Joshua M. Boniface
eba30bda75 Bump version to 10.6.1 2020-07-27 18:30:12 -04:00
Anthony Lavado
5c9847468f Merge pull request #1662 from dmitrylyzo/fix-ios-transcode
Add h264 codec profile for TS container

(cherry picked from commit 58198df5ce)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-07-27 18:19:52 -04:00
Joshua M. Boniface
027cb4f744 Merge pull request #1660 from nyanmisaka/edge-chromium
Fix mkv directplay on Edge chromium

(cherry picked from commit 0408ff0867)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-07-27 18:11:21 -04:00
dkanada
37cde45d12 Merge pull request #1641 from dmitrylyzo/fix-event-source-2
Fix event source for inputManager in case of multiple open dialogs

(cherry picked from commit f5e93a18de)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-07-27 18:11:21 -04:00
dkanada
875c4e0882 Merge pull request #1632 from dmitrylyzo/remove-leftovers-1
Remove debug leftovers

(cherry picked from commit 71646b6131)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-07-27 18:11:21 -04:00
dkanada
ee9d651246 Merge pull request #1628 from dmitrylyzo/fix-webos3
Use NodeList instead of HTMLCollection

(cherry picked from commit 5bc2d567ab)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-07-27 18:11:20 -04:00
dkanada
7f133ff8cd Merge pull request #1627 from rom4nik/master
Fix required track count for subtitle selector to appear

(cherry picked from commit 120ce4f0ff)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-07-27 18:11:20 -04:00
dkanada
76f9b2c741 Merge pull request #1625 from MrTimscampi/syncplay-version-check
Add version check for SyncPlay

(cherry picked from commit 03a9e73b3b)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-07-27 18:11:20 -04:00
Bond-009
51768eb119 Merge pull request #1624 from MrTimscampi/apiclient-update
Update apiclient to 1.4.1

(cherry picked from commit 930197ac9e)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-07-27 18:11:20 -04:00
dkanada
cdaf03a769 Merge pull request #1620 from MrTimscampi/metadata-more-fix
Restore More button in metadata editor

(cherry picked from commit 995cbdde16)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-07-27 18:11:20 -04:00
dkanada
f1acfda7d2 Merge pull request #1612 from Maxr1998/master
Add support for seeking with milliseconds

(cherry picked from commit 6b45755480)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-07-27 18:11:20 -04:00
dkanada
fef30a0be3 Merge pull request #1595 from jellyfin/error
Fix issue with sync menu and excessive logging

(cherry picked from commit 7c2472785b)
Signed-off-by: Joshua M. Boniface <joshua@boniface.me>
2020-07-27 18:11:20 -04:00
741 changed files with 70954 additions and 113012 deletions

View File

@@ -8,6 +8,8 @@ jobs:
BuildConfiguration: development
Production:
BuildConfiguration: production
Standalone:
BuildConfiguration: standalone
pool:
vmImage: 'ubuntu-latest'
@@ -19,24 +21,28 @@ jobs:
versionSpec: '12.x'
- task: Cache@2
displayName: 'Cache node_modules'
displayName: 'Check Cache'
inputs:
key: 'npm | package-lock.json'
key: 'yarn | yarn.lock'
path: 'node_modules'
cacheHitVar: CACHE_RESTORED
- script: 'npm ci --no-audit'
- script: 'yarn install --frozen-lockfile'
displayName: 'Install Dependencies'
env:
SKIP_PREPARE: 'true'
condition: ne(variables.CACHE_RESTORED, 'true')
- script: 'npm run build:development'
- script: 'yarn build:development'
displayName: 'Build Development'
condition: eq(variables['BuildConfiguration'], 'development')
- script: 'npm run build:production'
- script: 'yarn build:production'
displayName: 'Build Production'
condition: eq(variables['BuildConfiguration'], 'production')
- script: 'yarn build:standalone'
displayName: 'Build Standalone'
condition: eq(variables['BuildConfiguration'], 'standalone')
- script: 'test -d dist'
displayName: 'Check Build'

View File

@@ -0,0 +1,29 @@
jobs:
- job: Lint
displayName: 'Lint'
pool:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool@0
displayName: 'Install Node'
inputs:
versionSpec: '12.x'
- task: Cache@2
displayName: 'Check Cache'
inputs:
key: 'yarn | yarn.lock'
path: 'node_modules'
cacheHitVar: CACHE_RESTORED
- script: 'yarn install --frozen-lockfile'
displayName: 'Install Dependencies'
condition: ne(variables.CACHE_RESTORED, 'true')
- script: 'yarn run lint --quiet'
displayName: 'Run ESLint'
- script: 'yarn run stylelint'
displayName: 'Run Stylelint'

View File

@@ -17,10 +17,6 @@ jobs:
vmImage: 'ubuntu-latest'
steps:
- script: echo "##vso[task.setvariable variable=JellyfinVersion]$( awk -F '/' '{ print $NF }' <<<'$(Build.SourceBranch)' | sed 's/^v//' )"
displayName: Set release version (stable)
condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/v')
- script: 'docker build -f deployment/Dockerfile.$(BuildConfiguration) -t jellyfin-web-$(BuildConfiguration) deployment'
displayName: 'Build Dockerfile'
condition: or(startsWith(variables['Build.SourceBranch'], 'refs/tags'), startsWith(variables['Build.SourceBranch'], 'refs/heads/master'))
@@ -123,4 +119,4 @@ jobs:
inputs:
sshEndpoint: repository
runOptions: 'inline'
inline: 'sudo /srv/repository/collect-server.azure.sh /srv/repository/incoming/azure $(Build.BuildNumber) $(Build.SourceBranch)'
inline: 'sudo /srv/repository/collect-server.azure.sh /srv/repository/incoming/azure $(Build.BuildNumber)'

View File

@@ -13,4 +13,5 @@ pr:
jobs:
- template: azure-pipelines-build.yml
- template: azure-pipelines-lint.yml
- template: azure-pipelines-package.yml

1
.copr
View File

@@ -1 +0,0 @@
fedora/

1
.copr/Makefile Symbolic link
View File

@@ -0,0 +1 @@
../fedora/Makefile

5
.dependabot/config.yml Normal file
View File

@@ -0,0 +1,5 @@
version: 1
update_configs:
- package_manager: "javascript"
directory: "/"
update_schedule: "weekly"

View File

@@ -8,5 +8,5 @@ trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf
[*.json]
[json]
indent_size = 2

View File

@@ -2,3 +2,4 @@ node_modules
dist
.idea
.vscode
src/libraries

View File

@@ -1,10 +1,6 @@
const restrictedGlobals = require('confusing-browser-globals');
module.exports = {
root: true,
plugins: [
'@babel',
'react',
'promise',
'import',
'eslint-comments'
@@ -19,153 +15,42 @@ module.exports = {
ecmaVersion: 2020,
sourceType: 'module',
ecmaFeatures: {
impliedStrict: true,
jsx: true
impliedStrict: true
}
},
extends: [
'eslint:recommended',
'plugin:react/recommended',
// 'plugin:promise/recommended',
'plugin:import/errors',
'plugin:import/warnings',
'plugin:eslint-comments/recommended',
'plugin:compat/recommended'
],
rules: {
'array-callback-return': ['error'],
'block-spacing': ['error'],
'brace-style': ['error', '1tbs', { 'allowSingleLine': true }],
'brace-style': ['error'],
'comma-dangle': ['error', 'never'],
'comma-spacing': ['error'],
'default-case-last': ['error'],
'eol-last': ['error'],
'indent': ['error', 4, { 'SwitchCase': 1 }],
'jsx-quotes': ['error', 'prefer-single'],
'keyword-spacing': ['error'],
'max-statements-per-line': ['error'],
'no-empty-function': ['error'],
'no-floating-decimal': ['error'],
'no-multi-spaces': ['error'],
'no-multiple-empty-lines': ['error', { 'max': 1 }],
'no-restricted-globals': ['error'].concat(restrictedGlobals),
'no-trailing-spaces': ['error'],
'@babel/no-unused-expressions': ['error', { 'allowShortCircuit': true, 'allowTernary': true, 'allowTaggedTemplates': true }],
'one-var': ['error', 'never'],
'padded-blocks': ['error', 'never'],
'prefer-const': ['error', {'destructuring': 'all'}],
'quotes': ['error', 'single', { 'avoidEscape': true, 'allowTemplateLiterals': false }],
'@babel/semi': ['error'],
'no-var': ['error'],
'semi': ['error'],
'space-before-blocks': ['error'],
'space-infix-ops': 'error',
'yoda': 'error'
},
settings: {
react: {
version: 'detect'
},
'import/extensions': [
'.js',
'.ts',
'.jsx',
'.tsx'
],
'import/parsers': {
'@typescript-eslint/parser': [ '.ts', '.tsx' ]
},
polyfills: [
// Native Promises Only
'Promise',
// whatwg-fetch
'fetch',
// document-register-element
'document.registerElement',
// resize-observer-polyfill
'ResizeObserver',
// fast-text-encoding
'TextEncoder',
// intersection-observer
'IntersectionObserver',
// Core-js
'Object.assign',
'Object.is',
'Object.setPrototypeOf',
'Object.toString',
'Object.freeze',
'Object.seal',
'Object.preventExtensions',
'Object.isFrozen',
'Object.isSealed',
'Object.isExtensible',
'Object.getOwnPropertyDescriptor',
'Object.getPrototypeOf',
'Object.keys',
'Object.entries',
'Object.getOwnPropertyNames',
'Function.name',
'Function.hasInstance',
'Array.from',
'Array.arrayOf',
'Array.copyWithin',
'Array.fill',
'Array.find',
'Array.findIndex',
'Array.iterator',
'String.fromCodePoint',
'String.raw',
'String.iterator',
'String.codePointAt',
'String.endsWith',
'String.includes',
'String.repeat',
'String.startsWith',
'String.trim',
'String.anchor',
'String.big',
'String.blink',
'String.bold',
'String.fixed',
'String.fontcolor',
'String.fontsize',
'String.italics',
'String.link',
'String.small',
'String.strike',
'String.sub',
'String.sup',
'RegExp',
'Number',
'Math',
'Date',
'async',
'Symbol',
'Map',
'Set',
'WeakMap',
'WeakSet',
'ArrayBuffer',
'DataView',
'Int8Array',
'Uint8Array',
'Uint8ClampedArray',
'Int16Array',
'Uint16Array',
'Int32Array',
'Uint32Array',
'Float32Array',
'Float64Array',
'Reflect',
// Temporary while eslint-compat-plugin is buggy
'document.querySelector'
]
'space-infix-ops': 'error'
},
overrides: [
{
files: [
'./src/**/*.js',
'./src/**/*.ts'
'./src/**/*.js'
],
parser: '@babel/eslint-parser',
parser: 'babel-eslint',
env: {
node: false,
amd: true,
@@ -185,13 +70,17 @@ module.exports = {
// Dependency globals
'$': 'readonly',
'jQuery': 'readonly',
'requirejs': 'readonly',
// Jellyfin globals
'ApiClient': 'writable',
'Events': 'writable',
'AppInfo': 'writable',
'chrome': 'writable',
'ConnectionManager': 'writable',
'DlnaProfilePage': 'writable',
'Dashboard': 'writable',
'DashboardPage': 'writable',
'Emby': 'readonly',
'Events': 'writable',
'getParameterByName': 'writable',
'getWindowLocationSearch': 'writable',
'Globalize': 'writable',
@@ -200,33 +89,108 @@ module.exports = {
'LibraryMenu': 'writable',
'LinkParser': 'writable',
'LiveTvHelpers': 'writable',
'Loading': 'writable',
'MetadataEditor': 'writable',
'pageClassOn': 'writable',
'pageIdOn': 'writable',
'PlaylistViewer': 'writable',
'ServerNotifications': 'writable',
'TaskButton': 'writable',
'UserParentalControlPage': 'writable',
'Windows': 'readonly'
},
rules: {
// TODO: Fix warnings and remove these rules
'no-redeclare': ['warn'],
'no-unused-vars': ['warn'],
'no-useless-escape': ['warn'],
// TODO: Remove after ES6 migration is complete
'import/no-unresolved': ['off']
},
settings: {
polyfills: [
// Native Promises Only
'Promise',
// whatwg-fetch
'fetch',
// document-register-element
'document.registerElement',
// resize-observer-polyfill
'ResizeObserver',
// fast-text-encoding
'TextEncoder',
// intersection-observer
'IntersectionObserver',
// Core-js
'Object.assign',
'Object.is',
'Object.setPrototypeOf',
'Object.toString',
'Object.freeze',
'Object.seal',
'Object.preventExtensions',
'Object.isFrozen',
'Object.isSealed',
'Object.isExtensible',
'Object.getOwnPropertyDescriptor',
'Object.getPrototypeOf',
'Object.keys',
'Object.entries',
'Object.getOwnPropertyNames',
'Function.name',
'Function.hasInstance',
'Array.from',
'Array.arrayOf',
'Array.copyWithin',
'Array.fill',
'Array.find',
'Array.findIndex',
'Array.iterator',
'String.fromCodePoint',
'String.raw',
'String.iterator',
'String.codePointAt',
'String.endsWith',
'String.includes',
'String.repeat',
'String.startsWith',
'String.trim',
'String.anchor',
'String.big',
'String.blink',
'String.bold',
'String.fixed',
'String.fontcolor',
'String.fontsize',
'String.italics',
'String.link',
'String.small',
'String.strike',
'String.sub',
'String.sup',
'RegExp',
'Number',
'Math',
'Date',
'async',
'Symbol',
'Map',
'Set',
'WeakMap',
'WeakSet',
'ArrayBuffer',
'DataView',
'Int8Array',
'Uint8Array',
'Uint8ClampedArray',
'Int16Array',
'Uint16Array',
'Int32Array',
'Uint32Array',
'Float32Array',
'Float64Array',
'Reflect',
// Temporary while eslint-compat-plugin is buggy
'document.querySelector'
]
}
},
{
files: [
'./src/**/*.ts',
'./src/**/*.tsx'
],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
extends: [
'eslint:recommended',
'plugin:import/typescript',
'plugin:@typescript-eslint/recommended',
'plugin:eslint-comments/recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:jsx-a11y/recommended'
]
}
]
};
}

4
.github/CODEOWNERS vendored
View File

@@ -1,6 +1,4 @@
.ci @dkanada @EraYaN
.github @jellyfin/core
fedora @joshuaboniface
debian @joshuaboniface
.copr @joshuaboniface
build.sh @joshuaboniface
deployment @joshuaboniface

View File

@@ -1,22 +0,0 @@
---
name: Playback Issue
about: You have playback issues with some files
labels: playback
---
**Describe The Bug**
<!-- A clear and concise description of what the bug is. -->
**Media Information**
<!-- Please paste any ffprobe or MediaInfo logs. -->
**Screenshots**
<!-- Add screenshots from the Playback Data and Media Info. -->
**System (please complete the following information):**
- Platform: [e.g. Linux, Windows, iPhone, Tizen]
- Browser: [e.g. Firefox, Chrome, Safari]
- Jellyfin Version: [e.g. 10.6.0]
**Additional Context**
<!-- Add any other context about the problem here. -->

View File

@@ -1,13 +0,0 @@
---
name: Technical Discussion
about: You want to discuss technical aspects of changes you intend to make
labels: enhancement
---
<!-- Explain the change and the motivations behind it.
For example, if you plan to rely on a new dependency, explain why and what
it brings to the project.
If you plan to make significant changes, go roughly over the steps you intend
to take and how you would divide the change in PRs of a manageable size. -->

View File

@@ -1,9 +0,0 @@
---
name: Meta Issue
about: You want to track a number of other issues as part of a larger project
labels: meta
---
* [ ] Issue 1 [#123]
* [ ] Issue 2 [#456]
* [ ] ...

View File

@@ -1,20 +1,23 @@
---
name: Bug Report
about: You have noticed a general issue or regression, and would like to report it
name: Bug report
about: Create a bug report
title: ''
labels: bug
assignees: ''
---
**Describe The Bug**
**Describe the bug**
<!-- A clear and concise description of what the bug is. -->
**Steps To Reproduce**
**To Reproduce**
<!-- Steps to reproduce the behavior: -->
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected Behavior**
**Expected behavior**
<!-- A clear and concise description of what you expected to happen. -->
**Logs**
@@ -24,9 +27,9 @@ labels: bug
<!-- If applicable, add screenshots to help explain your problem. -->
**System (please complete the following information):**
- Platform: [e.g. Linux, Windows, iPhone, Tizen]
- OS: [e.g. Docker, Debian, Windows]
- Browser: [e.g. Firefox, Chrome, Safari]
- Jellyfin Version: [e.g. 10.6.0]
- Jellyfin Version: [e.g. 10.0.1]
**Additional Context**
**Additional context**
<!-- Add any other context about the problem here. -->

View File

@@ -1,8 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: Feature Request
url: https://features.jellyfin.org/
about: Please head over to our feature request hub to vote on or submit a feature.
- name: Help Or Question
url: https://matrix.to/#/#jellyfin-troubleshooting:matrix.org
about: Please join the troubleshooting Matrix channel to get some help.

24
.github/SUPPORT.md vendored
View File

@@ -1,24 +0,0 @@
# Support
Jellyfin contributors have limited availability to address general support
questions. Please make sure you are using the latest version of Jellyfin.
When looking for support or information, please first search for your
question in these venues:
* [Jellyfin Forum](https://forum.jellyfin.org)
* [Jellyfin Documentation](https://docs.jellyfin.org)
* [Open or **closed** issues in the organization](https://github.com/issues?q=sort%3Aupdated-desc+org%3Ajellyfin+is%3Aissue+)
If you didn't find an answer in the resources above, contributors and other
users are reachable through the following channels:
* #jellyfin on [Matrix](https://matrix.to/#/#jellyfin:matrix.org%22) or [IRC](ircs://irc.libera.chat:6697/#jellyfin)
* #jellyfin-troubleshooting on [Matrix](https://matrix.to/#/#jellyfin-troubleshooting:matrix.org) or [IRC](ircs://irc.libera.chat:6697/#jellyfin-troubleshooting)
* [/r/jellyfin on Reddit](https://www.reddit.com/r/jellyfin)
GitHub issues are for tracking enhancements and bugs, not general support.
The open source license grants you the freedom to use Jellyfin.
It does not guarantee commitments of other people's time.
Please be respectful and manage your expectations.

51
.github/renovate.json vendored
View File

@@ -1,51 +0,0 @@
{
"packageRules": [
{
"matchManagers": ["npm"],
"addLabels": ["javascript"]
},
{
"description": "Adds label to dev dependency updates",
"matchDepTypes": ["devDependencies"],
"addLabels": ["dev-deps"]
},
{
"description": "Collects and groups dev dependency updates",
"matchDepTypes": ["devDependencies"],
"groupName": "development dependencies",
"groupSlug": "dev-deps"
},
{
"description": "Collects and groups npm dependency updates",
"matchDepTypes": ["dependencies"],
"groupName": "dependencies",
"groupSlug": "deps"
},
{
"description": "Collects and groups GitHub Action dependency updates",
"matchDepTypes": ["action"],
"addLabels": ["github_actions"],
"groupName": "CI dependencies",
"groupSlug": "ci-deps"
},
{
"description": "Disables HLS.js major updates",
"matchPackageNames": ["hls.js"],
"matchUpdateTypes": "major",
"enabled": false
}
],
"vulnerabilityAlerts": {
"addLabels": ["security"]
},
"dependencyDashboard": false,
"ignoreDeps": ["npm", "node"],
"lockFileMaintenance": {
"enabled": false
},
"enabledManagers": ["npm", "github-actions"],
"labels": ["dependencies"],
"prHourlyLimit": 2,
"rebaseWhen": "conflicted",
"rangeStrategy": "pin"
}

20
.github/stale.yml vendored Normal file
View File

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

View File

@@ -1,20 +0,0 @@
name: 'Automation'
on:
push:
branches:
- master
pull_request_target:
types:
- synchronize
jobs:
triage:
name: 'Merge conflict labeling'
runs-on: ubuntu-latest
if: ${{ github.repository == 'jellyfin/jellyfin-web' }}
steps:
- uses: eps1lon/actions-label-merge-conflict@v2.0.1
with:
dirtyLabel: 'merge conflict'
repoToken: ${{ secrets.JF_BOT_TOKEN }}

View File

@@ -1,31 +0,0 @@
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
schedule:
- cron: '30 7 * * 6'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
queries: +security-extended
- name: Autobuild
uses: github/codeql-action/autobuild@v1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@@ -1,28 +0,0 @@
name: Commands
on:
issue_comment:
types:
- created
- edited
jobs:
rebase:
name: Rebase
if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '@jellyfin-bot rebase') && github.event.comment.author_association == 'MEMBER'
runs-on: ubuntu-latest
steps:
- name: Notify as seen
uses: peter-evans/create-or-update-comment@v1.4.5
with:
token: ${{ secrets.JF_BOT_TOKEN }}
comment-id: ${{ github.event.comment.id }}
reactions: '+1'
- name: Checkout the latest code
uses: actions/checkout@v3.0.0
with:
token: ${{ secrets.JF_BOT_TOKEN }}
fetch-depth: 0
- name: Automatic Rebase
uses: cirrus-actions/rebase@1.5
env:
GITHUB_TOKEN: ${{ secrets.JF_BOT_TOKEN }}

View File

@@ -1,119 +0,0 @@
name: Lint
on:
push:
branches: [ master, release* ]
pull_request:
branches: [ master, release* ]
jobs:
run-eslint:
name: Run eslint
runs-on: ubuntu-latest
steps:
- name: Check out Git repository
uses: actions/checkout@v3
- name: Setup node environment
uses: actions/setup-node@v3.0.0
with:
node-version: 12
check-latest: true
- name: Get npm cache directory path
id: npm-cache-dir-path
run: echo "::set-output name=dir::$(npm config get cache)"
- name: Cache node_modules
uses: actions/cache@v3.0.0
id: npm-cache
with:
path: ${{ steps.npm-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-npm-
- name: Install Node.js dependencies
run: npm ci --no-audit
env:
SKIP_PREPARE: true
- name: Run eslint
run: npm run lint
run-stylelint-css:
name: Run stylelint (css)
runs-on: ubuntu-latest
steps:
- name: Check out Git repository
uses: actions/checkout@v3
- name: Setup node environment
uses: actions/setup-node@v3.0.0
with:
node-version: 12
check-latest: true
- name: Get npm cache directory path
id: npm-cache-dir-path
run: echo "::set-output name=dir::$(npm config get cache)"
- name: Cache node_modules
uses: actions/cache@v3.0.0
id: npm-cache
with:
path: ${{ steps.npm-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-npm-
- name: Set up stylelint matcher
uses: xt0rted/stylelint-problem-matcher@v1
- name: Install Node.js dependencies
run: npm ci --no-audit
env:
SKIP_PREPARE: true
- 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@v3
- name: Setup node environment
uses: actions/setup-node@v3.0.0
with:
node-version: 12
check-latest: true
- name: Get npm cache directory path
id: npm-cache-dir-path
run: echo "::set-output name=dir::$(npm config get cache)"
- name: Cache node_modules
uses: actions/cache@v3.0.0
id: npm-cache
with:
path: ${{ steps.npm-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-npm-
- name: Set up stylelint matcher
uses: xt0rted/stylelint-problem-matcher@v1
- name: Install Node.js dependencies
run: npm ci --no-audit
env:
SKIP_PREPARE: true
- name: Run stylelint
run: npm run stylelint:scss

View File

@@ -1,27 +0,0 @@
name: Issue Stale Check
on:
schedule:
- cron: '30 1 * * *'
workflow_dispatch:
jobs:
stale:
runs-on: ubuntu-latest
if: ${{ contains(github.repository, 'jellyfin/') }}
steps:
- uses: actions/stale@v5.0.0
with:
repo-token: ${{ secrets.JF_BOT_TOKEN }}
days-before-stale: 120
days-before-pr-stale: -1
days-before-close: 21
days-before-pr-close: -1
exempt-issue-labels: regression,security,roadmap,future,feature,enhancement,confirmed
stale-issue-label: stale
stale-issue-message: |-
This issue has gone 120 days without comment. To avoid abandoned issues, it will be closed in 21 days if there are no new comments.
If you're the original submitter of this issue, please comment confirming if this issue still affects you in the latest release or master branch, or close the issue if it has been fixed. If you're another user also affected by this bug, please comment confirming so. Either action will remove the stale label.
This bot exists to prevent issues from becoming stale and forgotten. Jellyfin is always moving forward, and bugs are often fixed as side effects of other changes. We therefore ask that bug report authors remain vigilant about their issues to ensure they are closed if fixed, or re-confirmed - perhaps with fresh logs or reproduction examples - regularly. If you have any questions you can reach us on [Matrix or Social Media](https://docs.jellyfin.org/general/getting-help.html).

10
.gitignore vendored
View File

@@ -3,19 +3,9 @@ dist
web
node_modules
# config
config.json
# ide
.idea
.vscode
# log
yarn-error.log
# vim
*.sw?
# build artifacts
fedora/jellyfin-web-*.src.rpm
fedora/jellyfin-web-*.tar.gz

2
.npmrc
View File

@@ -1,2 +0,0 @@
fund=false
save-exact=true

View File

@@ -1,14 +1,14 @@
{
"plugins": [
"stylelint-no-browser-hacks/lib"
"stylelint-no-browser-hacks/lib",
],
"rules": {
"at-rule-empty-line-before": [ "always", {
"except": [
except: [
"blockless-after-same-name-blockless",
"first-nested"
"first-nested",
],
"ignore": ["after-comment"]
ignore: ["after-comment"],
} ],
"at-rule-name-case": "lower",
"at-rule-name-space-after": "always-single-line",
@@ -26,27 +26,27 @@
"color-hex-length": "short",
"color-no-invalid-hex": true,
"comment-empty-line-before": [ "always", {
"except": ["first-nested"],
"ignore": ["stylelint-commands"]
except: ["first-nested"],
ignore: ["stylelint-commands"],
} ],
"comment-no-empty": true,
"comment-whitespace-inside": "always",
"custom-property-empty-line-before": [ "always", {
"except": [
except: [
"after-custom-property",
"first-nested"
"first-nested",
],
"ignore": [
ignore: [
"after-comment",
"inside-single-line-block"
]
"inside-single-line-block",
],
} ],
"declaration-bang-space-after": "never",
"declaration-bang-space-before": "always",
"declaration-block-no-duplicate-properties": [
true,
{
"ignore": ["consecutive-duplicates-with-different-values"]
ignore: ["consecutive-duplicates-with-different-values"]
}
],
"declaration-block-no-shorthand-property-overrides": true,
@@ -59,6 +59,7 @@
"declaration-colon-space-after": "always-single-line",
"declaration-colon-space-before": "never",
"font-family-no-duplicate-names": true,
"function-calc-no-invalid": true,
"function-calc-no-unspaced-operator": true,
"function-comma-newline-after": "always-multi-line",
"function-comma-space-after": "always-single-line",
@@ -104,8 +105,8 @@
}
],
"rule-empty-line-before": [ "always-multi-line", {
"except": ["first-nested"],
"ignore": ["after-comment"]
except: ["first-nested"],
ignore: ["after-comment"],
} ],
"selector-attribute-brackets-space-inside": "never",
"selector-attribute-operator-space-after": "never",
@@ -137,6 +138,6 @@
"value-list-comma-newline-after": "always-multi-line",
"value-list-comma-space-after": "always-single-line",
"value-list-comma-space-before": "never",
"value-list-max-empty-lines": 0
"value-list-max-empty-lines": 0,
}
}

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

@@ -34,25 +34,8 @@
- [Ryan Hartzell](https://github.com/ryan-hartzell)
- [Thibault Nocchi](https://github.com/ThibaultNocchi)
- [MrTimscampi](https://github.com/MrTimscampi)
- [artiume](https://github.com/Artiume)
- [ConfusedPolarBear](https://github.com/ConfusedPolarBear)
- [Sarab Singh](https://github.com/sarab97)
- [DesertCookie](https://github.com/desertcookie)
- [GuilhermeHideki](https://github.com/GuilhermeHideki)
- [Andrei Oanca](https://github.com/OancaAndrei)
- [Cromefire_](https://github.com/cromefire)
- [Orry Verducci](https://github.com/orryverducci)
- [Camc314](https://github.com/camc314)
- [danieladov](https://github.com/danieladov)
- [Stephane Senart](https://github.com/ssenart)
- [imchasingshadows](https://github.com/imchasingshadows)
- [Ömer Erdinç Yağmurlu](https://github.com/omeryagmurlu)
- [Keegan Dahm](https://github.com/keegandahm)
- [GodTamIt](https://github.com/GodTamIt)
- [MinecraftPlaye](https://github.com/MinecraftPlaye)
- [Matthew Jones](https://github.com/matthew-jones-uk)
- [taku0](https://github.com/taku0)
- [Peter Spenler](https://github.com/peterspenler)
# Emby Contributors
@@ -116,6 +99,3 @@
- [tikuf](https://github.com/tikuf/)
- [Tim Hobbs](https://github.com/timhobbs)
- [SvenVandenbrande](https://github.com/SvenVandenbrande)
- [jomp16](https://github.com/jomp16)
- [Leon de Klerk](https://github.com/leondeklerk)
- [CrispyBaguette](https://github.com/CrispyBaguette)

View File

@@ -23,6 +23,9 @@
<a href="https://features.jellyfin.org">
<img alt="Feature Requests" src="https://img.shields.io/badge/fider-vote%20on%20features-success.svg"/>
</a>
<a href="https://forum.jellyfin.org">
<img alt="Discuss on our Forum" src="https://img.shields.io/discourse/https/forum.jellyfin.org/users.svg"/>
</a>
<a href="https://matrix.to/#/+jellyfin:matrix.org">
<img alt="Chat on Matrix" src="https://img.shields.io/matrix/jellyfin:matrix.org.svg?logo=matrix"/>
</a>
@@ -41,8 +44,8 @@ Jellyfin Web is the frontend used for most of the clients available for end user
### Dependencies
- [Node.js](https://nodejs.org/en/download)
- npm (included in Node.js)
- [Yarn 1.22.4](https://classic.yarnpkg.com/en/docs/install)
- Gulp-cli
### Getting Started
@@ -56,17 +59,23 @@ Jellyfin Web is the frontend used for most of the clients available for end user
2. Install build dependencies in the project directory.
```sh
npm install
yarn install
```
3. Run the web client with webpack for local development.
```sh
npm start
yarn serve
```
4. Build the client with sourcemaps available.
4. Build the client with sourcemaps.
```sh
npm run build:development
yarn build:development
```
You can build a nginx compatible version as well.
```sh
yarn build:standalone
```

View File

@@ -1,29 +0,0 @@
module.exports = {
babelrcRoots: [
// Keep the root as a root
'.'
],
sourceType: 'unambiguous',
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: 3
}
],
'@babel/preset-react',
[
'@babel/preset-typescript',
{
isTSX: true,
allExtensions: true
}
]
],
plugins: [
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-private-methods',
'babel-plugin-dynamic-import-polyfill'
]
};

View File

@@ -39,7 +39,7 @@ do_build_native() {
}
do_build_docker() {
if ! [ $(uname -m) = "x86_64" ]; then
if ! dpkg --print-architecture | grep -q 'amd64'; then
echo "Docker-based builds only support amd64-based cross-building; use a 'native' build instead."
exit 1
fi

View File

@@ -1,7 +1,7 @@
---
# We just wrap `build` so this is really it
name: "jellyfin-web"
version: "10.8.13"
version: "10.6.4"
packages:
- debian.all
- fedora.all

View File

@@ -18,39 +18,38 @@ if [[ -z $1 ]]; then
exit 1
fi
shared_version_file="src/components/apphost.js"
build_file="./build.yaml"
package_file="./package*.json"
new_version="$1"
old_version="$(
grep "version:" ${build_file} \
| sed -E 's/version: "([0-9\.]+[-a-z0-9]*)"/\1/'
)"
echo "Old version: ${old_version}"
# Parse the version from shared version file
old_version="$( grep "appVersion" ${shared_version_file} | head -1 | sed -E "s/var appVersion = '([0-9\.]+)';/\1/" | tr -d '[:space:]' )"
echo "Old version in appHost is: $old_version"
# Bump the NPM version
# Set the shared version to the specified new_version
old_version_sed="$( sed 's/\./\\./g' <<<"${old_version}" )" # Escape the '.' chars
new_version_sed="$( cut -f1 -d'-' <<<"${new_version}" )"
npm --no-git-tag-version --allow-same-version version v${new_version_sed}
sed -i "s/${old_version_sed}/${new_version_sed}/g" ${shared_version_file}
old_version="$( grep "version:" ${build_file} | sed -E 's/version: "([0-9\.]+[-a-z0-9]*)"/\1/' )"
echo "Old version in ${build_file}: ${old_version}"
# Set the build.yaml version to the specified new_version
old_version_sed="$( sed 's/\./\\./g' <<<"${old_version}" )" # Escape the '.' chars
sed -i "s/${old_version_sed}/${new_version_sed}/g" ${build_file}
sed -i "s/${old_version_sed}/${new_version}/g" ${build_file}
if [[ ${new_version} == *"-"* ]]; then
new_version_pkg="$( sed 's/-/~/g' <<<"${new_version}" )"
new_version_deb_sup=""
new_version_deb="$( sed 's/-/~/g' <<<"${new_version}" )"
else
new_version_pkg="${new_version}"
new_version_deb_sup="-1"
new_version_deb="${new_version}-1"
fi
# Write out a temporary Debian changelog with our new stuff appended and some templated formatting
debian_changelog_file="debian/changelog"
debian_changelog_temp="$( mktemp )"
# Create new temp file with our changelog
echo -e "jellyfin-web (${new_version_pkg}${new_version_deb_sup}) unstable; urgency=medium
echo -e "jellyfin-web (${new_version_deb}) unstable; urgency=medium
* New upstream version ${new_version}; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v${new_version}
@@ -71,7 +70,7 @@ pushd ${fedora_spec_temp_dir}
# Split out the stuff before and after changelog
csplit jellyfin-web.spec "/^%changelog/" # produces xx00 xx01
# Update the version in xx00
sed -i "s/${old_version_sed}/${new_version_pkg}/g" xx00
sed -i "s/${old_version_sed}/${new_version_sed}/g" xx00
# Remove the header from xx01
sed -i '/^%changelog/d' xx01
# Create new temp file with our changelog
@@ -85,8 +84,8 @@ popd
# Move into place
mv ${fedora_spec_temp} ${fedora_spec_file}
# Clean up
rm -rf ${fedora_spec_temp_dir}
rm -rf ${fedora_changelog_temp} ${fedora_spec_temp_dir}
# Stage the changed files for commit
git add .
git status -v
git add ${shared_version_file} ${build_file} ${debian_changelog_file} ${fedora_spec_file}
git status

90
debian/changelog vendored
View File

@@ -1,92 +1,26 @@
jellyfin-web (10.8.13-1) unstable; urgency=medium
jellyfin-web (10.6.4-1) unstable; urgency=medium
* New upstream version 10.8.13; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.13
* New upstream version 10.6.4; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.6.4
-- Jellyfin Packaging Team <packaging@jellyfin.org> Tue, 28 Nov 2023 22:21:29 -0500
-- Jellyfin Packaging Team <packaging@jellyfin.org> Sun, 30 Aug 2020 16:45:08 -0400
jellyfin-web (10.8.12-1) unstable; urgency=medium
jellyfin-web (10.6.3-1) unstable; urgency=medium
* New upstream version 10.8.12; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.12
* New upstream version 10.6.3; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.6.3
-- Jellyfin Packaging Team <packaging@jellyfin.org> Sat, 04 Nov 2023 14:42:41 -0400
-- Jellyfin Packaging Team <packaging@jellyfin.org> Sun, 16 Aug 2020 19:48:03 -0400
jellyfin-web (10.8.11-1) unstable; urgency=medium
jellyfin-web (10.6.2-1) unstable; urgency=medium
* New upstream version 10.8.11; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.11
* New upstream version 10.6.2; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.6.2
-- Jellyfin Packaging Team <packaging@jellyfin.org> Sat, 23 Sep 2023 21:41:40 -0400
-- Jellyfin Packaging Team <packaging@jellyfin.org> Sun, 02 Aug 2020 20:25:58 -0400
jellyfin-web (10.8.10-1) unstable; urgency=medium
jellyfin-web (10.6.1-1) unstable; urgency=medium
* New upstream version 10.8.10; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.10
* New upstream version 10.6.1; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.6.1
-- Jellyfin Packaging Team <packaging@jellyfin.org> Sun, 23 Apr 2023 11:01:33 -0400
jellyfin-web (10.8.9-1) unstable; urgency=medium
* New upstream version 10.8.9; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.9
-- Jellyfin Packaging Team <packaging@jellyfin.org> Sun, 22 Jan 2023 14:09:13 -0500
jellyfin-web (10.8.8-1) unstable; urgency=medium
* New upstream version 10.8.8; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.8
-- Jellyfin Packaging Team <packaging@jellyfin.org> Tue, 29 Nov 2022 13:42:54 -0500
jellyfin-web (10.8.7-1) unstable; urgency=medium
* New upstream version 10.8.7; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.7
-- Jellyfin Packaging Team <packaging@jellyfin.org> Mon, 31 Oct 2022 23:06:34 -0400
jellyfin-web (10.8.6-1) unstable; urgency=medium
* New upstream version 10.8.6; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.6
-- Jellyfin Packaging Team <packaging@jellyfin.org> Fri, 28 Oct 2022 22:44:15 -0400
jellyfin-web (10.8.5-1) unstable; urgency=medium
* New upstream version 10.8.5; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.5
-- Jellyfin Packaging Team <packaging@jellyfin.org> Sat, 24 Sep 2022 22:02:26 -0400
jellyfin-web (10.8.4-1) unstable; urgency=medium
* New upstream version 10.8.4; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.4
-- Jellyfin Packaging Team <packaging@jellyfin.org> Sat, 13 Aug 2022 21:52:04 -0400
jellyfin-web (10.8.3-1) unstable; urgency=medium
* New upstream version 10.8.3; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.3
-- Jellyfin Packaging Team <packaging@jellyfin.org> Mon, 01 Aug 2022 20:22:00 -0400
jellyfin-web (10.8.2-1) unstable; urgency=medium
* New upstream version 10.8.2; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.2
-- Jellyfin Packaging Team <packaging@jellyfin.org> Mon, 01 Aug 2022 14:27:56 -0400
jellyfin-web (10.8.1-1) unstable; urgency=medium
* New upstream version 10.8.1; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.1
-- Jellyfin Packaging Team <packaging@jellyfin.org> Sun, 26 Jun 2022 20:59:39 -0400
jellyfin-web (10.8.0-1) unstable; urgency=medium
* New upstream version 10.8.0; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.0
-- Jellyfin Packaging Team <packaging@jellyfin.org> Fri, 10 Jun 2022 22:16:40 -0400
jellyfin-web (10.7.0-1) unstable; urgency=medium
* New upstream version 10.7.0; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.7.0
-- Jellyfin Packaging Team <packaging@jellyfin.org> Mon, 27 Jul 2020 19:13:31 -0400
-- Jellyfin Packaging Team <packaging@jellyfin.org> Mon, 27 Jul 2020 18:29:54 -0400
jellyfin-web (10.6.0-1) unstable; urgency=medium

1
debian/conffiles vendored
View File

@@ -1 +0,0 @@
/usr/share/jellyfin/web/config.json

2
debian/rules vendored
View File

@@ -11,7 +11,7 @@ override_dh_auto_test:
override_dh_clistrip:
override_dh_auto_build:
npm ci --no-audit --unsafe-perm
npx yarn install
mv $(CURDIR)/dist $(CURDIR)/web
override_dh_auto_clean:

View File

@@ -12,9 +12,12 @@ ENV IS_DOCKER=YES
# Prepare CentOS environment
RUN yum update -y \
&& yum install -y epel-release \
&& yum install -y @buildsys-build rpmdevtools git yum-plugins-core autoconf automake glibc-devel gcc-c++ make \
&& curl -fsSL https://rpm.nodesource.com/setup_12.x | bash - \
&& yum install -y nodejs
&& yum install -y @buildsys-build rpmdevtools git yum-plugins-core nodejs-yarn autoconf automake glibc-devel
# Install recent NodeJS and Yarn
RUN curl -fSsLo /etc/yum.repos.d/yarn.repo https://dl.yarnpkg.com/rpm/yarn.repo \
&& rpm -i https://rpm.nodesource.com/pub_10.x/el/7/x86_64/nodesource-release-el7-1.noarch.rpm \
&& yum install -y yarn
# Link to build script
RUN ln -sf ${SOURCE_DIR}/deployment/build.centos /build.sh

View File

@@ -12,10 +12,10 @@ ENV IS_DOCKER=YES
# Prepare Debian build environment
RUN apt-get update \
&& apt-get install -y debhelper mmv git curl \
&& curl -fsSL https://deb.nodesource.com/setup_12.x | bash - \
&& apt-get install -y nodejs
&& apt-get install -y debhelper mmv npm git
# Prepare Yarn
RUN npm install -g yarn
# Link to build script
RUN ln -sf ${SOURCE_DIR}/deployment/build.debian /build.sh

View File

@@ -1,11 +1,11 @@
FROM node:lts-alpine
FROM node:alpine
ARG SOURCE_DIR=/src
ARG ARTIFACT_DIR=/jellyfin-web
RUN apk add autoconf g++ make libpng-dev gifsicle alpine-sdk automake libtool make gcc musl-dev nasm python3
RUN apk add autoconf g++ make libpng-dev gifsicle alpine-sdk automake libtool make gcc musl-dev nasm python
WORKDIR ${SOURCE_DIR}
COPY . .
RUN npm ci --no-audit --unsafe-perm && mv dist ${ARTIFACT_DIR}
RUN yarn install && mv dist ${ARTIFACT_DIR}

View File

@@ -1,4 +1,4 @@
FROM fedora:36
FROM fedora:31
# Docker build arguments
ARG SOURCE_DIR=/jellyfin
@@ -11,7 +11,7 @@ ENV IS_DOCKER=YES
# Prepare Fedora environment
RUN dnf update -y \
&& dnf install -y @buildsys-build rpmdevtools git dnf-plugins-core nodejs autoconf automake glibc-devel make
&& dnf install -y @buildsys-build rpmdevtools git dnf-plugins-core nodejs-yarn autoconf automake glibc-devel
# Link to build script
RUN ln -sf ${SOURCE_DIR}/deployment/build.fedora /build.sh

View File

@@ -11,9 +11,10 @@ ENV IS_DOCKER=YES
# Prepare Debian build environment
RUN apt-get update \
&& apt-get install -y mmv curl git \
&& curl -fsSL https://deb.nodesource.com/setup_12.x | bash - \
&& apt-get install -y nodejs
&& apt-get install -y mmv npm git
# Prepare Yarn
RUN npm install -g yarn
# Link to build script
RUN ln -sf ${SOURCE_DIR}/deployment/build.portable /build.sh

View File

@@ -6,7 +6,7 @@ set -o xtrace
# move to source directory
pushd ${SOURCE_DIR}
cp -a package-lock.json /tmp/package-lock.json
cp -a yarn.lock /tmp/yarn.lock
# modify changelog to unstable configuration if IS_UNSTABLE
if [[ ${IS_UNSTABLE} == 'yes' ]]; then
@@ -36,6 +36,6 @@ if [[ ${IS_DOCKER} == YES ]]; then
fi
rm -f fedora/jellyfin*.tar.gz
cp -a /tmp/package-lock.json package-lock.json
cp -a /tmp/yarn.lock yarn.lock
popd

View File

@@ -6,7 +6,7 @@ set -o xtrace
# move to source directory
pushd ${SOURCE_DIR}
cp -a package-lock.json /tmp/package-lock.json
cp -a yarn.lock /tmp/yarn.lock
# modify changelog to unstable configuration if IS_UNSTABLE
if [[ ${IS_UNSTABLE} == 'yes' ]]; then
@@ -30,7 +30,7 @@ dpkg-buildpackage -us -uc --pre-clean --post-clean
mkdir -p ${ARTIFACT_DIR}
mv ../jellyfin*.{deb,dsc,tar.gz,buildinfo,changes} ${ARTIFACT_DIR}
cp -a /tmp/package-lock.json package-lock.json
cp -a /tmp/yarn.lock yarn.lock
if [[ ${IS_DOCKER} == YES ]]; then
chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}

View File

@@ -6,7 +6,7 @@ set -o xtrace
# move to source directory
pushd ${SOURCE_DIR}
cp -a package-lock.json /tmp/package-lock.json
cp -a yarn.lock /tmp/yarn.lock
# modify changelog to unstable configuration if IS_UNSTABLE
if [[ ${IS_UNSTABLE} == 'yes' ]]; then
@@ -36,6 +36,6 @@ if [[ ${IS_DOCKER} == YES ]]; then
fi
rm -f fedora/jellyfin*.tar.gz
cp -a /tmp/package-lock.json package-lock.json
cp -a /tmp/yarn.lock yarn.lock
popd

View File

@@ -14,7 +14,7 @@ else
fi
# build archives
npm ci --no-audit --unsafe-perm
npx yarn install
mv dist jellyfin-web_${version}
tar -czf jellyfin-web_${version}_portable.tar.gz jellyfin-web_${version}
rm -rf dist

View File

@@ -1,48 +1,21 @@
DIR := $(dir $(lastword $(MAKEFILE_LIST)))
# install git and npm
$(info $(shell set -x; if [ "$$(id -u)" = "0" ]; then echo "Installing git"; dnf -y install git npm; fi))
NAME := jellyfin-web
VERSION := $(shell set -x; sed -ne '/^Version:/s/.* *//p' $(DIR)/$(NAME).spec)
RELEASE := $(shell set -x; sed -ne '/^Release:/s/.* *\(.*\)%{.*}.*/\1/p' $(DIR)/$(NAME).spec)
SRPM := jellyfin-web-$(subst -,~,$(VERSION))-$(RELEASE)$(shell rpm --eval %dist).src.rpm
TARBALL :=$(NAME)-$(subst -,~,$(VERSION)).tar.gz
VERSION := $(shell sed -ne '/^Version:/s/.* *//p' fedora/jellyfin-web.spec)
epel-7-x86_64_repos := https://rpm.nodesource.com/pub_16.x/el/\$$releasever/\$$basearch/
fed_ver := $(shell rpm -E %fedora)
# fallback when not running on Fedora
fed_ver ?= 36
TARGET ?= fedora-$(fed_ver)-x86_64
outdir ?= $(PWD)/$(DIR)/
srpm: $(DIR)/$(SRPM)
tarball: $(DIR)/$(TARBALL)
$(DIR)/$(TARBALL):
cd $(DIR)/; \
SOURCE_DIR=.. \
WORKDIR="$${PWD}"; \
version=$(VERSION); \
tar \
--transform "s,^\.,$(NAME)-$(subst -,~,$(VERSION))," \
--exclude='.git*' \
--exclude='**/.git' \
--exclude='**/.hg' \
--exclude=deployment \
--exclude='*.deb' \
--exclude='*.rpm' \
--exclude=$(notdir $@) \
-czf $(notdir $@) \
srpm:
cd fedora/; \
SOURCE_DIR=.. \
WORKDIR="$${PWD}"; \
tar \
--transform "s,^\.,jellyfin-web-$(VERSION)," \
--exclude='.git*' \
--exclude='**/.git' \
--exclude='**/.hg' \
--exclude='deployment' \
--exclude='*.deb' \
--exclude='*.rpm' \
--exclude='jellyfin-web-$(VERSION).tar.gz' \
-czf "jellyfin-web-$(VERSION).tar.gz" \
-C $${SOURCE_DIR} ./
$(DIR)/$(SRPM): $(DIR)/$(TARBALL) $(DIR)/jellyfin-web.spec
cd $(DIR)/; \
rpmbuild -bs $(NAME).spec \
--define "_sourcedir $$PWD/" \
cd fedora/; \
rpmbuild -bs jellyfin-web.spec \
--define "_sourcedir $$PWD/" \
--define "_srcrpmdir $(outdir)"
rpms: $(DIR)/$(SRPM)
mock $(addprefix --addrepo=, $($(TARGET)_repos)) \
--enable-network \
-r $(TARGET) $<

View File

@@ -1,21 +1,25 @@
%global debug_package %{nil}
Name: jellyfin-web
Version: 10.8.13
Version: 10.6.4
Release: 1%{?dist}
Summary: The Free Software Media System web client
License: GPLv2
License: GPLv3
URL: https://jellyfin.org
# Jellyfin Server tarball created by `make -f .copr/Makefile srpm`, real URL ends with `v%%{version}.tar.gz`
# Jellyfin Server tarball created by `make -f .copr/Makefile srpm`, real URL ends with `v%{version}.tar.gz`
Source0: jellyfin-web-%{version}.tar.gz
BuildArch: noarch
%if 0%{?rhel} > 0 && 0%{?rhel} < 8
BuildRequires: nodejs
%if 0%{?centos}
BuildRequires: yarn
# sadly the yarn RPM at https://dl.yarnpkg.com/rpm/ uses git but doesn't Requires: it
BuildRequires: git
%else
BuildRequires: git
BuildRequires: npm
BuildRequires: nodejs-yarn
%endif
BuildArch: noarch
# Disable Automatic Dependency Processing
AutoReqProv: no
%description
Jellyfin is a free software media system that puts you in control of managing and streaming your media.
@@ -24,53 +28,26 @@ Jellyfin is a free software media system that puts you in control of managing an
%prep
%autosetup -n jellyfin-web-%{version} -b 0
%if 0%{?rhel} > 0 && 0%{?rhel} < 8
# Required for CentOS build
chown root:root -R .
%endif
%build
npm ci --no-audit --unsafe-perm
%install
%{__mkdir} -p %{buildroot}%{_libdir}/jellyfin/jellyfin-web
%{__cp} -r dist/* %{buildroot}%{_libdir}/jellyfin/jellyfin-web
yarn install
%{__mkdir} -p %{buildroot}%{_datadir}
mv dist %{buildroot}%{_datadir}/jellyfin-web
%{__install} -D -m 0644 LICENSE %{buildroot}%{_datadir}/licenses/jellyfin/LICENSE
%files
%defattr(644,root,root,755)
%{_libdir}/jellyfin/jellyfin-web
%license LICENSE
%attr(755,root,root) %{_datadir}/jellyfin-web
%{_datadir}/licenses/jellyfin/LICENSE
%changelog
* Tue Nov 28 2023 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.8.13; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.13
* Sat Nov 04 2023 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.8.12; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.12
* Sat Sep 23 2023 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.8.11; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.11
* Sun Apr 23 2023 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.8.10; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.10
* Sun Jan 22 2023 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.8.9; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.9
* Tue Nov 29 2022 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.8.8; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.8
* Mon Oct 31 2022 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.8.7; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.7
* Fri Oct 28 2022 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.8.6; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.6
* Sat Sep 24 2022 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.8.5; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.5
* Sat Aug 13 2022 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.8.4; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.4
* Mon Aug 01 2022 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.8.3; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.3
* Mon Aug 01 2022 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.8.2; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.2
* Sun Jun 26 2022 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.8.1; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.1
* Fri Jun 10 2022 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.8.0; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.8.0
* Sun Aug 30 2020 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.6.4; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.6.4
* Sun Aug 16 2020 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.6.3; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.6.3
* Sun Aug 02 2020 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.6.2; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.6.2
* Mon Jul 27 2020 Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version 10.6.1; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.6.1
* Mon Mar 23 2020 Jellyfin Packaging Team <packaging@jellyfin.org>
- Forthcoming stable release

204
gulpfile.js Normal file
View File

@@ -0,0 +1,204 @@
const { src, dest, series, parallel, watch } = require('gulp');
const browserSync = require('browser-sync').create();
const del = require('del');
const babel = require('gulp-babel');
const concat = require('gulp-concat');
const terser = require('gulp-terser');
const htmlmin = require('gulp-htmlmin');
const imagemin = require('gulp-imagemin');
const sourcemaps = require('gulp-sourcemaps');
const mode = require('gulp-mode')({
modes: ['development', 'production'],
default: 'development',
verbose: false
});
const stream = require('webpack-stream');
const inject = require('gulp-inject');
const postcss = require('gulp-postcss');
const sass = require('gulp-sass');
const gulpif = require('gulp-if');
const lazypipe = require('lazypipe');
sass.compiler = require('node-sass');
let config;
if (mode.production()) {
config = require('./webpack.prod.js');
} else {
config = require('./webpack.dev.js');
}
const options = {
javascript: {
query: ['src/**/*.js', '!src/bundle.js', '!src/standalone.js', '!src/scripts/apploader.js']
},
apploader: {
query: ['src/standalone.js', 'src/scripts/apploader.js']
},
css: {
query: ['src/**/*.css', 'src/**/*.scss']
},
html: {
query: ['src/**/*.html', '!src/index.html']
},
images: {
query: ['src/**/*.png', 'src/**/*.jpg', 'src/**/*.gif', 'src/**/*.svg']
},
copy: {
query: ['src/**/*.json', 'src/**/*.ico', 'src/**/*.mp3']
},
injectBundle: {
query: 'src/index.html'
}
};
function serve() {
browserSync.init({
server: {
baseDir: './dist'
},
port: 8080
});
const events = ['add', 'change'];
watch(options.javascript.query).on('all', function (event, path) {
if (events.includes(event)) {
javascript(path);
}
});
watch(options.apploader.query, apploader(true));
watch('src/bundle.js', webpack);
watch(options.css.query).on('all', function (event, path) {
if (events.includes(event)) {
css(path);
}
});
watch(options.html.query).on('all', function (event, path) {
if (events.includes(event)) {
html(path);
}
});
watch(options.images.query).on('all', function (event, path) {
if (events.includes(event)) {
images(path);
}
});
watch(options.copy.query).on('all', function (event, path) {
if (events.includes(event)) {
copy(path);
}
});
watch(options.injectBundle.query, injectBundle);
}
function clean() {
return del(['dist/']);
}
const pipelineJavascript = lazypipe()
.pipe(function () {
return mode.development(sourcemaps.init({ loadMaps: true }));
})
.pipe(function () {
return babel({
presets: [
['@babel/preset-env']
]
});
})
.pipe(function () {
return terser({
keep_fnames: true,
mangle: false
});
})
.pipe(function () {
return mode.development(sourcemaps.write('.'));
});
function javascript(query) {
return src(typeof query !== 'function' ? query : options.javascript.query, { base: './src/' })
.pipe(pipelineJavascript())
.pipe(dest('dist/'))
.pipe(browserSync.stream());
}
function apploader(standalone) {
function task() {
return src(options.apploader.query, { base: './src/' })
.pipe(gulpif(standalone, concat('scripts/apploader.js')))
.pipe(pipelineJavascript())
.pipe(dest('dist/'))
.pipe(browserSync.stream());
}
task.displayName = 'apploader';
return task;
}
function webpack() {
return stream(config)
.pipe(dest('dist/'))
.pipe(browserSync.stream());
}
function css(query) {
return src(typeof query !== 'function' ? query : options.css.query, { base: './src/' })
.pipe(mode.development(sourcemaps.init({ loadMaps: true })))
.pipe(sass().on('error', sass.logError))
.pipe(postcss())
.pipe(mode.development(sourcemaps.write('.')))
.pipe(dest('dist/'))
.pipe(browserSync.stream());
}
function html(query) {
return src(typeof query !== 'function' ? query : options.html.query, { base: './src/' })
.pipe(mode.production(htmlmin({ collapseWhitespace: true })))
.pipe(dest('dist/'))
.pipe(browserSync.stream());
}
function images(query) {
return src(typeof query !== 'function' ? query : options.images.query, { base: './src/' })
.pipe(mode.production(imagemin()))
.pipe(dest('dist/'))
.pipe(browserSync.stream());
}
function copy(query) {
return src(typeof query !== 'function' ? query : options.copy.query, { base: './src/' })
.pipe(dest('dist/'))
.pipe(browserSync.stream());
}
function injectBundle() {
return src(options.injectBundle.query, { base: './src/' })
.pipe(inject(
src(['src/scripts/apploader.js'], { read: false }, { base: './src/' }), {
relative: true,
transform: function (filepath) {
return `<script src="${filepath}" defer></script>`;
}
}
))
.pipe(dest('dist/'))
.pipe(browserSync.stream());
}
function build(standalone) {
return series(clean, parallel(javascript, apploader(standalone), webpack, css, html, images, copy));
}
exports.default = series(build(false), injectBundle);
exports.standalone = series(build(true), injectBundle);
exports.serve = series(exports.standalone, serve);

15705
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,109 +1,150 @@
{
"name": "jellyfin-web",
"version": "10.8.13",
"version": "0.0.0",
"description": "Web interface for Jellyfin",
"repository": "https://github.com/jellyfin/jellyfin-web",
"license": "GPL-2.0-or-later",
"devDependencies": {
"@babel/core": "7.17.7",
"@babel/eslint-parser": "7.17.0",
"@babel/eslint-plugin": "7.17.7",
"@babel/plugin-proposal-class-properties": "7.16.7",
"@babel/plugin-proposal-private-methods": "7.16.11",
"@babel/plugin-transform-modules-umd": "7.16.7",
"@babel/preset-env": "7.16.11",
"@babel/preset-react": "7.16.7",
"@babel/preset-typescript": "7.16.7",
"@thornbill/jellyfin-sdk": "0.4.1",
"@types/escape-html": "1.0.1",
"@types/lodash-es": "4.17.6",
"@types/react": "17.0.40",
"@types/react-dom": "17.0.13",
"@typescript-eslint/eslint-plugin": "5.15.0",
"@typescript-eslint/parser": "5.15.0",
"@uupaa/dynamic-import-polyfill": "1.0.2",
"autoprefixer": "10.4.4",
"babel-loader": "8.2.3",
"babel-plugin-dynamic-import-polyfill": "1.0.0",
"clean-webpack-plugin": "4.0.0",
"confusing-browser-globals": "1.0.11",
"copy-webpack-plugin": "10.2.4",
"css-loader": "6.7.1",
"cssnano": "5.1.4",
"eslint": "8.11.0",
"eslint-plugin-compat": "4.0.2",
"eslint-plugin-eslint-comments": "3.2.0",
"eslint-plugin-import": "2.25.4",
"eslint-plugin-jsx-a11y": "6.5.1",
"eslint-plugin-promise": "6.0.0",
"eslint-plugin-react": "7.29.4",
"eslint-plugin-react-hooks": "4.3.0",
"expose-loader": "3.1.0",
"html-loader": "3.1.0",
"html-webpack-plugin": "5.5.0",
"postcss": "8.4.12",
"postcss-loader": "6.2.1",
"postcss-preset-env": "7.4.2",
"postcss-scss": "4.0.3",
"sass": "1.49.9",
"sass-loader": "12.6.0",
"source-map-loader": "3.0.1",
"style-loader": "3.3.1",
"stylelint": "14.6.0",
"stylelint-config-rational-order": "0.1.2",
"stylelint-no-browser-hacks": "1.2.1",
"stylelint-order": "5.0.0",
"stylelint-scss": "4.2.0",
"ts-loader": "9.2.8",
"typescript": "4.6.2",
"webpack": "5.70.0",
"webpack-cli": "4.9.2",
"webpack-dev-server": "4.7.4",
"webpack-merge": "5.8.0",
"workbox-webpack-plugin": "6.5.1",
"worker-loader": "3.0.8"
"@babel/core": "^7.10.3",
"@babel/plugin-proposal-class-properties": "^7.10.1",
"@babel/plugin-proposal-private-methods": "^7.10.1",
"@babel/plugin-transform-modules-amd": "^7.9.6",
"@babel/polyfill": "^7.8.7",
"@babel/preset-env": "^7.10.3",
"autoprefixer": "^9.8.5",
"babel-eslint": "^11.0.0-beta.2",
"babel-loader": "^8.0.6",
"browser-sync": "^2.26.7",
"copy-webpack-plugin": "^5.1.1",
"css-loader": "^3.6.0",
"cssnano": "^4.1.10",
"del": "^5.1.0",
"eslint": "^6.8.0",
"eslint-plugin-compat": "^3.5.1",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-import": "^2.21.2",
"eslint-plugin-promise": "^4.2.1",
"file-loader": "^6.0.0",
"gulp": "^4.0.2",
"gulp-babel": "^8.0.0",
"gulp-cli": "^2.3.0",
"gulp-concat": "^2.6.1",
"gulp-htmlmin": "^5.0.1",
"gulp-if": "^3.0.0",
"gulp-imagemin": "^7.1.0",
"gulp-inject": "^5.0.5",
"gulp-mode": "^1.0.2",
"gulp-postcss": "^8.0.0",
"gulp-sass": "^4.0.2",
"gulp-sourcemaps": "^2.6.5",
"gulp-terser": "^1.2.0",
"html-webpack-plugin": "^4.3.0",
"lazypipe": "^1.0.2",
"node-sass": "^4.13.1",
"postcss-loader": "^3.0.0",
"postcss-preset-env": "^6.7.0",
"style-loader": "^1.1.3",
"stylelint": "^13.6.1",
"stylelint-config-rational-order": "^0.1.2",
"stylelint-no-browser-hacks": "^1.2.1",
"stylelint-order": "^4.1.0",
"webpack": "^4.41.5",
"webpack-merge": "^4.2.2",
"webpack-stream": "^5.2.1"
},
"dependencies": {
"@fontsource/noto-sans": "4.5.1",
"@fontsource/noto-sans-hk": "4.5.2",
"@fontsource/noto-sans-jp": "4.5.2",
"@fontsource/noto-sans-kr": "4.5.2",
"@fontsource/noto-sans-sc": "4.5.2",
"@fontsource/noto-sans-tc": "4.5.2",
"@jellyfin/libass-wasm": "4.1.1",
"blurhash": "1.1.4",
"alameda": "^1.4.0",
"blurhash": "^1.1.3",
"classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz",
"classnames": "2.3.1",
"core-js": "3.20.2",
"date-fns": "2.28.0",
"dompurify": "2.3.4",
"epubjs": "0.3.93",
"escape-html": "1.0.3",
"fast-text-encoding": "1.0.3",
"flv.js": "1.6.2",
"headroom.js": "0.12.0",
"hls.js": "0.14.17",
"intersection-observer": "0.12.0",
"jellyfin-apiclient": "1.10.0",
"jquery": "3.6.0",
"jstree": "3.3.12",
"libarchive.js": "1.3.0",
"lodash-es": "4.17.21",
"marked": "4.0.10",
"material-design-icons-iconfont": "6.1.1",
"native-promise-only": "0.8.1",
"page": "1.11.6",
"pdfjs-dist": "2.12.313",
"react": "17.0.2",
"react-dom": "17.0.2",
"resize-observer-polyfill": "1.5.1",
"screenfull": "6.0.0",
"sortablejs": "1.14.0",
"swiper": "6.8.4",
"webcomponents.js": "0.7.24",
"whatwg-fetch": "3.6.2",
"workbox-core": "6.2.4",
"workbox-precaching": "6.2.4"
"core-js": "^3.6.5",
"date-fns": "^2.14.0",
"epubjs": "^0.3.85",
"fast-text-encoding": "^1.0.3",
"flv.js": "^1.5.0",
"headroom.js": "^0.11.0",
"hls.js": "^0.14.0",
"howler": "^2.2.0",
"intersection-observer": "^0.11.0",
"jellyfin-apiclient": "^1.4.1",
"jellyfin-noto": "https://github.com/jellyfin/jellyfin-noto",
"jquery": "^3.5.1",
"jstree": "^3.3.10",
"libass-wasm": "https://github.com/jellyfin/JavascriptSubtitlesOctopus#4.0.0-jf-smarttv",
"material-design-icons-iconfont": "^5.0.1",
"native-promise-only": "^0.8.0-a",
"page": "^1.11.6",
"query-string": "^6.13.1",
"resize-observer-polyfill": "^1.5.1",
"screenfull": "^5.0.2",
"shaka-player": "^2.5.13",
"sortablejs": "^1.10.2",
"swiper": "^5.4.5",
"webcomponents.js": "^0.7.24",
"whatwg-fetch": "^3.2.0"
},
"babel": {
"presets": [
"@babel/preset-env"
],
"overrides": [
{
"test": [
"src/components/accessSchedule/accessSchedule.js",
"src/components/actionSheet/actionSheet.js",
"src/components/autoFocuser.js",
"src/components/cardbuilder/cardBuilder.js",
"src/components/cardbuilder/chaptercardbuilder.js",
"src/components/cardbuilder/peoplecardbuilder.js",
"src/components/images/imageLoader.js",
"src/components/indicators/indicators.js",
"src/components/lazyLoader/lazyLoaderIntersectionObserver.js",
"src/components/playback/brightnessosd.js",
"src/components/playback/mediasession.js",
"src/components/playback/nowplayinghelper.js",
"src/components/playback/playbackorientation.js",
"src/components/playback/playerSelectionMenu.js",
"src/components/playback/playersettingsmenu.js",
"src/components/playback/playmethodhelper.js",
"src/components/playback/remotecontrolautoplay.js",
"src/components/playback/volumeosd.js",
"src/components/playmenu.js",
"src/components/sanatizefilename.js",
"src/components/scrollManager.js",
"src/components/syncPlay/groupSelectionMenu.js",
"src/components/syncPlay/playbackPermissionManager.js",
"src/components/syncPlay/syncPlayManager.js",
"src/components/syncPlay/timeSyncManager.js",
"src/controllers/dashboard/logs.js",
"src/controllers/dashboard/plugins/repositories.js",
"src/controllers/user/display.js",
"src/controllers/user/home.js",
"src/controllers/user/playback.js",
"src/controllers/user/subtitles.js",
"src/plugins/bookPlayer/plugin.js",
"src/plugins/bookPlayer/tableOfContents.js",
"src/plugins/photoPlayer/plugin.js",
"src/scripts/deleteHelper.js",
"src/scripts/dfnshelper.js",
"src/scripts/dom.js",
"src/scripts/fileDownloader.js",
"src/scripts/filesystem.js",
"src/scripts/imagehelper.js",
"src/scripts/inputManager.js",
"src/plugins/backdropScreensaver/plugin.js",
"src/components/filterdialog/filterdialog.js",
"src/components/fetchhelper.js",
"src/scripts/keyboardNavigation.js",
"src/scripts/settings/appSettings.js",
"src/scripts/settings/userSettings.js",
"src/scripts/settings/webSettings.js"
],
"plugins": [
"@babel/plugin-transform-modules-amd",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-private-methods"
]
}
]
},
"browserslist": [
"last 2 Firefox versions",
@@ -122,17 +163,12 @@
"Firefox ESR"
],
"scripts": {
"start": "npm run serve",
"serve": "webpack serve --config webpack.dev.js",
"prepare": "node ./scripts/prepare.js",
"build:development": "webpack --config webpack.dev.js",
"build:production": "webpack --config webpack.prod.js",
"lint": "eslint \"src/\"",
"stylelint": "npm run stylelint:css && npm run stylelint:scss",
"stylelint:css": "stylelint \"src/**/*.css\"",
"stylelint:scss": "stylelint --config=\".stylelintrc.scss.json\" \"src/**/*.scss\""
},
"engines": {
"yarn": "YARN NO LONGER USED - use npm instead."
"serve": "gulp serve --development",
"prepare": "gulp --production",
"build:development": "gulp --development",
"build:production": "gulp --production",
"build:standalone": "gulp standalone --development",
"lint": "eslint \".\"",
"stylelint": "stylelint \"src/**/*.css\""
}
}

View File

@@ -1,33 +0,0 @@
import sys
import os
import json
# load every string in the source language
# print all duplicate values to a file
cwd = os.getcwd()
source = cwd + '/../src/strings/en-us.json'
reverse = {}
duplicates = {}
with open(source) as en:
strings = json.load(en)
for key, value in strings.items():
if value not in reverse:
reverse[value] = [key]
else:
reverse[value].append(key)
for key, value in reverse.items():
if len(value) > 1:
duplicates[key] = value
print('LENGTH: ' + str(len(duplicates)))
with open('duplicates.txt', 'w') as out:
for item in duplicates:
out.write(json.dumps(item) + ': ')
out.write(json.dumps(duplicates[item]) + '\n')
out.close()
print('DONE')

View File

@@ -1,12 +0,0 @@
const { execSync } = require('child_process');
/**
* The npm `prepare` script needs to run a build to support installing
* a package from git repositories (this is dumb but a limitation of how
* npm behaves). We don't want to run these in CI though because
* building is slow so this script will skip the build when the
* `SKIP_PREPARE` environment variable has been set.
*/
if (!process.env.SKIP_PREPARE) {
execSync('webpack --config webpack.prod.js', { stdio: 'inherit' });
}

View File

@@ -16,7 +16,7 @@ langlst.append('en-us.json')
dep = []
def grep(key):
command = 'grep -r -E "(\\\"|\'|\{)%s(\\\"|\'|\})" --include=\*.{js,html} --exclude-dir=../src/strings ../src' % key
command = 'grep -r -E "(\(\\\"|\(\'|\{)%s(\\\"|\'|\})" --include=\*.{js,html} --exclude-dir=../src/strings ../src' % key
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output = p.stdout.readlines()
if output:

View File

@@ -11,7 +11,7 @@ langlst = os.listdir(langdir)
keys = []
with open('unused.txt', 'r') as f:
with open('scout.txt', 'r') as f:
for line in f:
keys.append(line.strip('\n'))

View File

@@ -34,9 +34,7 @@
<div class="readOnlyContent">
<div is="emby-collapse" title="${HeaderDeveloperInfo}">
<div class="collapseContent">
<p>${LabelDeveloper}: <span id="developer"></span></p>
<p>${LabelRepositoryName}: <span id="repositoryName"></span></p>
<p>${LabelRepositoryUrl}: <span id="repositoryUrl"></span></p>
<p id="developer"></p>
</div>
</div>

View File

@@ -8,7 +8,7 @@
</div>
<br />
<button is="emby-button" type="submit" class="raised button-submit block">
<span>${Connect}</span>
<span>${ButtonConnect}</span>
</button>
<button is="emby-button" type="button" class="raised button-cancel block btnCancel">
<span>${ButtonCancel}</span>

352
src/apiclient.d.ts vendored
View File

@@ -1,352 +0,0 @@
// TODO: Move to jellyfin-apiclient
/* eslint-disable @typescript-eslint/no-explicit-any */
declare module 'jellyfin-apiclient' {
import type {
AllThemeMediaResult,
AuthenticationResult,
BaseItemDto,
BaseItemDtoQueryResult,
BufferRequestDto,
ClientCapabilities,
CountryInfo,
CultureDto,
DeviceOptions,
DisplayPreferencesDto,
EndPointInfo,
FileSystemEntryInfo,
GeneralCommand,
GroupInfoDto,
GuideInfo,
IgnoreWaitRequestDto,
ImageInfo,
ImageProviderInfo,
ImageType,
ItemCounts,
LiveTvInfo,
MovePlaylistItemRequestDto,
NewGroupRequestDto,
NextItemRequestDto,
NotificationResultDto,
NotificationsSummaryDto,
ParentalRating,
PingRequestDto,
PlaybackInfoResponse,
PlaybackProgressInfo,
PlaybackStartInfo,
PlaybackStopInfo,
PlayCommand,
PlaystateCommand,
PluginInfo,
PluginSecurityInfo,
PreviousItemRequestDto,
QueryFiltersLegacy,
QueueRequestDto,
QuickConnectResult,
QuickConnectState,
ReadyRequestDto,
RecommendationDto,
RemoteImageResult,
RemoveFromPlaylistRequestDto,
SearchHintResult,
SeekRequestDto,
SeriesTimerInfoDto,
SeriesTimerInfoDtoQueryResult,
ServerConfiguration,
SessionInfo,
SetPlaylistItemRequestDto,
SetRepeatModeRequestDto,
SetShuffleModeRequestDto,
SystemInfo,
TaskInfo,
TaskTriggerInfo,
TimerInfoDto,
TimerInfoDtoQueryResult,
UserConfiguration,
UserDto,
UserItemDataDto,
UserPolicy,
UtcTimeResponse,
VirtualFolderInfo
} from '@thornbill/jellyfin-sdk/dist/generated-client';
class ApiClient {
constructor(serverAddress: string, appName: string, appVersion: string, deviceName: string, deviceId: string);
accessToken(): string;
addMediaPath(virtualFolderName: string, mediaPath: string, networkSharePath: string, refreshLibrary?: boolean): Promise<void>;
addVirtualFolder(name: string, type?: string, refreshLibrary?: boolean, libraryOptions?: any): Promise<void>;
appName(): string;
appVersion(): string;
authenticateUserByName(name: string, password: string): Promise<AuthenticationResult>;
cancelLiveTvSeriesTimer(id: string): Promise<void>;
cancelLiveTvTimer(id: string): Promise<void>;
cancelSyncItems(itemIds: string[], targetId?: string): Promise<void>;
clearAuthenticationInfo(): void;
clearUserItemRating(userId: string, itemId: string): Promise<UserItemDataDto>;
closeWebSocket(): void;
createLiveTvSeriesTimer(item: string): Promise<void>;
createLiveTvTimer(item: string): Promise<void>;
createPackageReview(review: any): Promise<any>;
createSyncPlayGroup(options?: NewGroupRequestDto): Promise<void>;
createUser(user: UserDto): Promise<UserDto>;
deleteDevice(deviceId: string): Promise<void>;
deleteItemImage(itemId: string, imageType: ImageType, imageIndex?: number): Promise<void>;
deleteItem(itemId: string): Promise<void>;
deleteLiveTvRecording(id: string): Promise<void>;
deleteUserImage(userId: string, imageType: ImageType, imageIndex?: number): Promise<void>;
deleteUser(userId: string): Promise<void>;
detectBitrate(force: boolean): Promise<number>;
deviceId(): string;
deviceName(): string;
disablePlugin(id: string, version: string): Promise<void>;
downloadRemoteImage(options: any): Promise<void>;
enablePlugin(id: string, version: string): Promise<void>;
encodeName(name: string): string;
ensureWebSocket(): void;
fetch(request: any, includeAuthorization?: boolean): Promise<any>;
fetchWithFailover(request: any, enableReconnection?: boolean): Promise<any>;
getAdditionalVideoParts(userId?: string, itemId: string): Promise<BaseItemDtoQueryResult>;
getAlbumArtists(userId: string, options?: any): Promise<BaseItemDtoQueryResult>;
getAncestorItems(itemId: string, userId?: string): Promise<BaseItemDto[]>;
getArtist(name: string, userId?: string): Promise<BaseItemDto>;
getArtists(userId: string, options?: any): Promise<BaseItemDtoQueryResult>;
getAvailablePlugins(options?: any): Promise<PluginInfo[]>;
getAvailableRemoteImages(options: any): Promise<RemoteImageResult>;
getContentUploadHistory(): Promise<any>;
getCountries(): Promise<CountryInfo[]>;
getCriticReviews(itemId: string, options?: any): Promise<BaseItemDtoQueryResult>;
getCultures(): Promise<CultureDto[]>;
getCurrentUserId(): string;
getDateParamValue(date: Date): string;
getDefaultImageQuality(imageType: ImageType): number;
getDevicesOptions(): Promise<DeviceOptions>;
getDirectoryContents(path: string, options?: any): Promise<FileSystemEntryInfo[]>;
getDisplayPreferences(id: string, userId: string, app: string): Promise<DisplayPreferencesDto>;
getDownloadSpeed(byteSize: number): Promise<number>;
getDrives(): Promise<FileSystemEntryInfo[]>;
getEndpointInfo(): Promise<EndPointInfo>;
getEpisodes(itemId: string, options?: any): Promise<BaseItemDtoQueryResult>;
getFilters(options?: any): Promise<QueryFiltersLegacy>;
getGenre(name: string, userId?: string): Promise<BaseItemDto>;
getGenres(userId: string, options?: any): Promise<BaseItemDtoQueryResult>;
getImageUrl(itemId: string, options?: any): string;
getInstalledPlugins(): Promise<PluginInfo[]>;
getInstantMixFromItem(itemId: string, options?: any): Promise<BaseItemDtoQueryResult>;
getIntros(itemId: string): Promise<BaseItemDtoQueryResult>;
getItemCounts(userId?: string): Promise<ItemCounts>;
getItemDownloadUrl(itemId: string): string;
getItemImageInfos(itemId: string): Promise<ImageInfo[]>;
getItems(userId: string, options?: any): Promise<BaseItemDtoQueryResult>;
getItem(userId: string, itemId: string): Promise<BaseItemDto>;
getJSON(url: string, includeAuthorization?: boolean): Promise<any>;
getLatestItems(options?: any): Promise<BaseItemDto[]>;
getLiveStreamMediaInfo(liveStreamId: string): Promise<any>;
getLiveTvChannel(id: string, userId?: string): Promise<BaseItemDto>;
getLiveTvChannels(options?: any): Promise<BaseItemDtoQueryResult>;
getLiveTvGuideInfo(userId: string): Promise<GuideInfo>;
getLiveTvInfo(userId: string): Promise<LiveTvInfo>;
getLiveTvProgram(id: string, userId?: string): Promise<BaseItemDto>;
getLiveTvPrograms(options?: any): Promise<BaseItemDtoQueryResult>;
getLiveTvRecommendedPrograms(options?: any): Promise<BaseItemDtoQueryResult>;
getLiveTvRecordingGroup(id: string): Promise<BaseItemDto>;
getLiveTvRecordingGroups(options?: any): Promise<BaseItemDtoQueryResult>;
getLiveTvRecording(id: string, userId?: string): Promise<BaseItemDto>;
getLiveTvRecordingSeries(options?: any): Promise<BaseItemDtoQueryResult>;
getLiveTvRecordings(options?: any): Promise<BaseItemDtoQueryResult>;
getLiveTvSeriesTimer(id: string): Promise<SeriesTimerInfoDto>;
getLiveTvSeriesTimers(options?: any): Promise<SeriesTimerInfoDtoQueryResult>;
getLiveTvTimer(id: string): Promise<TimerInfoDto>;
getLiveTvTimers(options?: any): Promise<TimerInfoDtoQueryResult>;
getLocalTrailers(userId: string, itemId: string): Promise<BaseItemDto[]>;
getMovieRecommendations(options?: any): Promise<RecommendationDto[]>;
getMusicGenre(name: string, userId?: string): Promise<BaseItemDto>;
getMusicGenres(userId: string, options?: any): Promise<BaseItemDtoQueryResult>;
getNamedConfiguration(name: string): Promise<any>;
getNetworkDevices(): Promise<any>;
getNetworkShares(path: string): Promise<FileSystemEntryInfo[]>;
getNewLiveTvTimerDefaults(options?: any): Promise<SeriesTimerInfoDto>;
getNextUpEpisodes(options?: any): Promise<BaseItemDtoQueryResult>;
getNotificationSummary(userId: string): Promise<NotificationsSummaryDto>;
getNotifications(userId: string, options?: any): Promise<NotificationResultDto>;
getPackageInfo(name: string, guid: string): Promise<PackageInfo>;
getPackageReviews(packageId: string, minRating?: string, maxRating?: string, limit?: string): Promise<any>;
getParentalRatings(): Promise<ParentalRating[]>;
getParentPath(path: string): Promise<string>;
getPeople(userId: string, options?: any): Promise<BaseItemDtoQueryResult>;
getPerson(name: string, userId?: string): Promise<BaseItemDto>;
getPhysicalPaths(): Promise<string[]>;
getPlaybackInfo(itemId: string, options: any, deviceProfile: any): Promise<PlaybackInfoResponse>;
getPluginConfiguration(id: string): Promise<any>;
getPublicSystemInfo(): Promise<PublicSystemInfo>;
getPublicUsers(): Promise<UserDto[]>;
getQuickConnect(verb: string): Promise<void|boolean|number|QuickConnectResult|QuickConnectState>;
getReadySyncItems(deviceId: string): Promise<any>;
getRecordingFolders(userId: string): Promise<BaseItemDtoQueryResult>;
getRegistrationInfo(feature: string): Promise<any>;
getRemoteImageProviders(options: any): Promise<ImageProviderInfo[]>;
getResumableItems(userId: string, options?: any): Promise<BaseItemDtoQueryResult>;
getRootFolder(userId: string): Promise<BaseItemDto>;
getSavedEndpointInfo(): EndPointInfo;
getScaledImageUrl(itemId: string, options?: any): string;
getScheduledTask(id: string): Promise<TaskInfo>;
getScheduledTasks(options?: any): Promise<TaskInfo[]>;
getSearchHints(options?: any): Promise<SearchHintResult>;
getSeasons(itemId: string, options?: any): Promise<BaseItemDtoQueryResult>;
getServerConfiguration(): Promise<ServerConfiguration>;
getServerTime(): Promise<UtcTimeResponse>;
getSessions(options?: any): Promise<SessionInfo[]>;
getSimilarItems(itemId: string, options?: any): Promise<BaseItemDtoQueryResult>;
getSpecialFeatures(userId: string, itemId: string): Promise<BaseItemDto[]>;
getStudio(name: string, userId?: string): Promise<BaseItemDto>;
getStudios(userId: string, options?: any): Promise<BaseItemDtoQueryResult>;
getSyncPlayGroups(): Promise<GroupInfoDto[]>;
getSyncStatus(itemId: string): Promise<any>;
getSystemInfo(): Promise<SystemInfo>;
getThemeMedia(userId?: string, itemId: string, inherit?: boolean): Promise<AllThemeMediaResult>;
getThumbImageUrl(item: BaseItemDto, options?: any): string;
getUpcomingEpisodes(options?: any): Promise<BaseItemDtoQueryResult>;
getUrl(name: string, params?: any, serverAddress?: string): string;
get(url: string): Promise<any>;
getUserImageUrl(userId: string, options?: any): string;
getUsers(options?: any): Promise<UserDto[]>;
getUser(userId: string): Promise<UserDto>;
getUserViews(options?: any, userId: string): Promise<BaseItemDtoQueryResult>;
getVirtualFolders(): Promise<VirtualFolderInfo[]>;
handleMessageReceived(msg: any): void;
installPlugin(name: string, guid: string, version?: string): Promise<void>;
isLoggedIn(): boolean;
isMessageChannelOpen(): boolean;
isMinServerVersion(version: string): boolean;
isWebSocketOpen(): boolean;
isWebSocketOpenOrConnecting(): boolean;
isWebSocketSupported(): boolean;
joinSyncPlayGroup(options?: any): Promise<void>;
leaveSyncPlayGroup(): Promise<void>;
logout(): Promise<void>;
markNotificationsRead(userId: string, idList: string[], isRead: boolean): Promise<void>;
markPlayed(userId: string, itemId: string, date: Date): Promise<UserItemDataDto>;
markUnplayed(userId: string, itemId: string, date: Date): Promise<UserItemDataDto>;
openWebSocket(): void;
quickConnect(secret: string): Promise<AuthenticationResult>;
refreshItem(itemId: string, options?: any): Promise<void>;
removeMediaPath(virtualFolderName: string, mediaPath: string, refreshLibrary?: boolean): Promise<void>;
removeVirtualFolder(name: string, refreshLibrary?: boolean): Promise<void>;
renameVirtualFolder(name: string, newName: string, refreshLibrary?: boolean): Promise<void>;
reportCapabilities(capabilities: ClientCapabilities): Promise<void>;
reportOfflineActions(actions: any): Promise<any>;
reportPlaybackProgress(options: PlaybackProgressInfo): Promise<void>;
reportPlaybackStart(options: PlaybackStartInfo): Promise<void>;
reportPlaybackStopped(options: PlaybackStopInfo): Promise<void>;
reportSyncJobItemTransferred(syncJobItemId: string): Promise<any>;
requestSyncPlayBuffering(options?: BufferRequestDto): Promise<void>;
requestSyncPlayMovePlaylistItem(options?: MovePlaylistItemRequestDto): Promise<void>;
requestSyncPlayNextItem(options?: NextItemRequestDto): Promise<void>;
requestSyncPlayPause(): Promise<void>;
requestSyncPlayPreviousItem(options?: PreviousItemRequestDto): Promise<void>;
requestSyncPlayQueue(options?: QueueRequestDto): Promise<void>;
requestSyncPlayReady(options?: ReadyRequestDto): Promise<void>;
requestSyncPlayRemoveFromPlaylist(options?: RemoveFromPlaylistRequestDto): Promise<void>;
requestSyncPlaySeek(options?: SeekRequestDto): Promise<void>;
requestSyncPlaySetIgnoreWait(options?: IgnoreWaitRequestDto): Promise<void>;
requestSyncPlaySetNewQueue(options?: NewGroupRequestDto): Promise<void>;
requestSyncPlaySetPlaylistItem(options?: SetPlaylistItemRequestDto): Promise<void>;
requestSyncPlaySetRepeatMode(options?: SetRepeatModeRequestDto): Promise<void>;
requestSyncPlaySetShuffleMode(options?: SetShuffleModeRequestDto): Promise<void>;
requestSyncPlayUnpause(): Promise<void>;
resetEasyPassword(userId: string): Promise<void>;
resetLiveTvTuner(id: string): Promise<void>;
resetUserPassword(userId: string): Promise<void>;
restartServer(): Promise<void>;
sendCommand(sessionId: string, command: any): Promise<void>;
sendMessageCommand(sessionId: string, options: GeneralCommand): Promise<void>;
sendMessage(name: string, data: any): void;
sendPlayCommand(sessionId: string, options: PlayCommand): Promise<void>;
sendPlayStateCommand(sessionId: string, command: PlaystateCommand, options?: any): Promise<void>;
sendSyncPlayPing(options?: PingRequestDto): Promise<void>;
sendWebSocketMessage(name: string, data: any): void;
serverAddress(val?: string): string;
serverId(): string;
serverVersion(): string
setAuthenticationInfo(accessKey?: string, userId?: string): void;
setRequestHeaders(headers: any): void;
setSystemInfo(info: SystemInfo): void;
shutdownServer(): Promise<void>;
startScheduledTask(id: string): Promise<void>;
stopActiveEncodings(playSessionId: string): Promise<void>;
stopScheduledTask(id: string): Promise<void>;
syncData(data: any): Promise<any>;
uninstallPluginByVersion(id: string, version: string): Promise<void>;
uninstallPlugin(id: string): Promise<void>;
updateDisplayPreferences(id: string, obj: DisplayPreferencesDto, userId: string, app: string): Promise<void>;
updateEasyPassword(userId: string, newPassword: string): Promise<void>;
updateFavoriteStatus(userId: string, itemId: string, isFavorite: boolean): Promise<UserItemDataDto>;
updateItemImageIndex(itemId: string, imageType: ImageType, imageIndex: number, newIndex: number): Promise<any>;
updateItem(item: BaseItemDto): Promise<void>;
updateLiveTvSeriesTimer(item: SeriesTimerInfoDto): Promise<void>;
updateLiveTvTimer(item: TimerInfoDto): Promise<void>;
updateMediaPath(virtualFolderName: string, pathInfo: any): Promise<void>;
updateNamedConfiguration(name: string, configuration: any): Promise<void>;
updatePluginConfiguration(id: string, configuration: any): Promise<void>;
updatePluginSecurityInfo(info: PluginSecurityInfo): Promise<void>;
updateScheduledTaskTriggers(id: string, triggers: TaskTriggerInfo[]): Promise<void>;
updateServerConfiguration(configuration: ServerConfiguration): Promise<void>;
updateServerInfo(server: any, serverUrl: string): void;
updateUserConfiguration(userId: string, configuration: UserConfiguration): Promise<void>;
updateUserItemRating(userId: string, itemId: string, likes: boolean): Promise<UserItemDataDto>;
updateUserPassword(userId: string, currentPassword: string, newPassword: string): Promise<void>;
updateUserPolicy(userId: string, policy: UserPolicy): Promise<void>;
updateUser(user: UserDto): Promise<void>;
updateVirtualFolderOptions(id: string, libraryOptions?: any): Promise<void>;
uploadItemImage(itemId: string, imageType: ImageType, file: File): Promise<void>;
uploadItemSubtitle(itemId: string, language: string, isForced: boolean, file: File): Promise<void>;
uploadUserImage(userId: string, imageType: ImageType, file: File): Promise<void>;
}
class AppStore {
constructor();
getItem(name: string): string|null;
removeItem(name: string): void;
setItem(name: string, value: string): void;
}
class ConnectionManager {
constructor(credentialProvider: Credentials, appName: string, appVersion: string, deviceName: string, deviceId: string, capabilities: ClientCapabilities);
addApiClient(apiClient: ApiClient): void;
clearData(): void;
connect(options?: any): Promise<any>;
connectToAddress(address: string, options?: any): Promise<any>;
connectToServer(server: any, options?: any): Promise<any>;
connectToServers(servers: any[], options?: any): Promise<any>;
deleteServer(serverId: string): Promise<void>;
getApiClient(item: BaseItemDto|string): ApiClient;
getApiClients(): ApiClient[];
getAvailableServers(): any[];
getOrCreateApiClient(serverId: string): ApiClient;
getSavedServers(): any[];
handleMessageReceived(msg: any): void;
logout(): Promise<void>;
minServerVersion(val?: string): string;
user(apiClient: ApiClient): Promise<any>;
}
class Credentials {
constructor(key?: string);
addOrUpdateServer(list: any[], server: any): any;
clear(): void;
credentials(data?: any): any;
}
interface Event {
type: string;
}
const Events: {
off(obj: any, eventName: string, fn: (e: Event, ...args: any[]) => void): void;
on(obj: any, eventName: string, fn: (e: Event, ...args: any[]) => void): void;
trigger(obj: any, eventName: string, ...args: any[]): void;
};
}
/* eslint-enable @typescript-eslint/no-explicit-any */

View File

@@ -3,7 +3,7 @@
<div class="content-primary">
<div class="detailSectionHeader">
<h2 style="margin:.6em 0;vertical-align:middle;display:inline-block;">${HeaderApiKeys}</h2>
<button is="emby-button" type="button" class="fab btnNewKey submit" style="margin-left:1em;" title="${Add}">
<button is="emby-button" type="button" class="fab btnNewKey submit" style="margin-left:1em;" title="${ButtonAdd}">
<span class="material-icons add" aria-hidden="true"></span>
</button>
</div>

View File

@@ -127,8 +127,8 @@ div[data-role=controlgroup] a.ui-btn-active {
}
.sessionAppInfo img {
max-width: 2.5em;
max-height: 2.5em;
max-width: 40px;
max-height: 40px;
margin-right: 8px;
}
@@ -204,17 +204,12 @@ div[data-role=controlgroup] a.ui-btn-active {
flex-grow: 1;
}
.dashboardActionsContainer {
margin: 1em -0.3em 0;
}
.sessionNowPlayingContent {
-webkit-background-size: cover;
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
position: absolute;
border-radius: 0.2em;
top: 0;
left: 0;
right: 0;
@@ -236,13 +231,6 @@ div[data-role=controlgroup] a.ui-btn-active {
margin-bottom: 0.5em;
}
.dashboardSection .sectionTitleTextButton > .material-icons.material-icons {
font-size: 1.17em;
margin-top: 0.5em;
margin-bottom: 0.5em;
padding-top: 0;
}
.activeRecordingItems > .card {
width: 50%;
}
@@ -258,12 +246,20 @@ div[data-role=controlgroup] a.ui-btn-active {
@media all and (min-width: 70em) {
.dashboardSections {
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
flex-direction: row;
}
.dashboardColumn-2-60 {
flex-grow: 2;
width: 46%;
}
.dashboardColumn-2-40 {
width: 27%;
}
.dashboardSection {
@@ -295,7 +291,6 @@ div[data-role=controlgroup] a.ui-btn-active {
}
.activeSession {
min-width: 20rem;
width: 100% !important;
}
@@ -309,24 +304,27 @@ div[data-role=controlgroup] a.ui-btn-active {
background-position: center;
}
@media all and (min-width: 40em) {
.activeSession {
width: 100% !important;
}
}
@media all and (min-width: 50em) {
.activeSession {
max-width: 25rem;
flex-grow: 0;
flex-shrink: 0;
flex-basis: 50%;
width: 50% !important;
}
}
.sessionCardFooter {
padding-top: 0.5em !important;
padding-bottom: 1em !important;
border-top: 1px solid #eee;
text-align: center;
position: relative;
}
.sessionAppInfo {
flex-grow: 1;
padding: 0.5em;
overflow: hidden;
}
@@ -346,13 +344,11 @@ div[data-role=controlgroup] a.ui-btn-active {
right: 0;
bottom: 0;
font-weight: 400;
display: flex;
flex-direction: column;
}
.darkenContent {
.sessionNowPlayingContent-withbackground + .sessionNowPlayingInnerContent {
color: #fff !important;
background: rgba(0, 0, 0, 0.7);
color: #ddd;
}
.sessionAppName {
@@ -362,6 +358,9 @@ div[data-role=controlgroup] a.ui-btn-active {
.sessionNowPlayingDetails {
display: flex;
position: absolute;
bottom: 0;
width: 100%;
}
.sessionNowPlayingInfo {
@@ -377,6 +376,10 @@ div[data-role=controlgroup] a.ui-btn-active {
padding: 0.8em 0.5em;
}
.sessionNowPlayingStreamInfo {
white-space: nowrap;
}
.playbackProgress,
.transcodingProgress {
margin: 0;
@@ -384,12 +387,6 @@ div[data-role=controlgroup] a.ui-btn-active {
background: transparent !important;
}
.activeDevices.itemsContainer {
/* offset for cardBox margin */
margin: -0.6em;
}
.activeSession .backgroundProgress,
.activeSession .playbackProgress,
.activeSession .transcodingProgress {
position: absolute;
@@ -406,14 +403,9 @@ div[data-role=controlgroup] a.ui-btn-active {
}
.transcodingProgress > div {
z-index: 10;
background-color: #dd4919;
}
.backgroundProgress > div {
background-color: #303030;
}
@media all and (max-width: 34.375em) {
.sessionAppName {
max-width: 160px;

37
src/assets/css/fonts.css Normal file
View File

@@ -0,0 +1,37 @@
html {
font-family: "Noto Sans", sans-serif;
font-size: 93%;
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
h1,
h2,
h3 {
font-family: "Noto Sans", sans-serif;
}
h1 {
font-weight: 400;
font-size: 1.8em;
}
h2 {
font-weight: 400;
font-size: 1.5em;
}
h3 {
font-weight: 400;
font-size: 1.17em;
}
.layout-tv {
font-size: 130%;
}
.layout-mobile {
font-size: 90%;
}

View File

@@ -1,56 +0,0 @@
@import "../../styles/noto-sans/index.scss";
@mixin font($weight: null, $size: null) {
font-weight: $weight;
font-size: $size;
}
html {
@include font($size: 93%);
font-family: "Noto Sans", "Noto Sans HK", "Noto Sans JP", "Noto Sans KR", "Noto Sans SC", "Noto Sans TC", sans-serif;
text-size-adjust: 100%;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
html[lang|="ja"] {
font-family: "Noto Sans", "Noto Sans JP", "Noto Sans HK", "Noto Sans KR", "Noto Sans SC", "Noto Sans TC", sans-serif;
}
html[lang|="ko"] {
font-family: "Noto Sans", "Noto Sans KR", "Noto Sans HK", "Noto Sans JP", "Noto Sans SC", "Noto Sans TC", sans-serif;
}
html[lang|="zh-CN"] {
font-family: "Noto Sans", "Noto Sans SC", "Noto Sans HK", "Noto Sans JP", "Noto Sans KR", "Noto Sans TC", sans-serif;
}
html[lang|="zh-TW"] {
font-family: "Noto Sans", "Noto Sans TC", "Noto Sans HK", "Noto Sans JP", "Noto Sans KR", "Noto Sans SC", sans-serif;
}
html[lang|="zh-HK"] {
font-family: "Noto Sans", "Noto Sans HK", "Noto Sans JP", "Noto Sans KR", "Noto Sans SC", "Noto Sans TC", sans-serif;
}
h1 {
@include font(400, 1.8em);
}
h2 {
@include font(400, 1.5em);
}
h3 {
@include font(400, 1.17em);
}
.layout-tv {
/* Per WebOS and Tizen guidelines, fonts must be 20px minimum.
This takes the 16px baseline and multiplies it by 1.25 to get 20px. */
font-size: 125%;
}
.layout-mobile {
font-size: 90%;
}

View File

@@ -0,0 +1,31 @@
h1 {
font-weight: 400;
font-size: 1.8em;
}
.layout-desktop h1 {
font-size: 2em;
}
h2 {
font-weight: 400;
font-size: 1.5em;
}
h3 {
font-weight: 400;
font-size: 1.17em;
}
@media all and (min-height: 720px) {
html {
font-size: 20px;
}
}
/* This is supposed to be 1080p, but had to reduce the min height to account for possible browser chrome */
@media all and (min-height: 1000px) {
html {
font-size: 27px;
}
}

View File

@@ -1,31 +0,0 @@
@mixin header-font($size: null) {
font-weight: 400;
font-size: $size;
}
html {
@media all and (min-height: 720px) {
font-size: 20px;
}
/* This is supposed to be 1080p, but had to reduce the min height to account for possible browser chrome */
@media all and (min-height: 1000px) {
font-size: 27px;
}
}
h1 {
@include header-font(1.8em);
.layout-desktop & {
font-size: 2em;
}
}
h2 {
@include header-font(1.8em);
}
h3 {
@include header-font(1.17em);
}

View File

@@ -1,37 +1,3 @@
// The padding of the header content on mobile needs to be adjusted
// based on the size of the poster card (values from card.scss)
@mixin header-poster-padding() {
padding-left: 37.5%;
@media all and (min-width: 43.75em) {
padding-left: 25%;
}
@media all and (min-width: 50em) {
padding-left: 20%;
}
@media all and (min-width: 75em) {
padding-left: 16.666666666666666666666666666667%;
}
@media all and (min-width: 87.5em) {
padding-left: 14.285714285714285714285714285714%;
}
@media all and (min-width: 100em) {
padding-left: 12.5%;
}
@media all and (min-width: 120em) {
padding-left: 11.111111111111111111111111111111%;
}
@media all and (min-width: 131.25em) {
padding-left: 10%;
}
}
.headerUserImage,
.navMenuOption,
.pageTitle {
@@ -62,10 +28,6 @@
padding-top: 0 !important;
}
.layout-tv .itemDetailPage {
padding-top: 4.2em !important;
}
.standalonePage {
padding-top: 4.5em !important;
}
@@ -86,6 +48,8 @@
z-index: 1;
margin: 0 !important;
top: 6.9em !important;
-webkit-transition: -webkit-transform 0.2s ease-out;
-o-transition: transform 0.2s ease-out;
transition: transform 0.2s ease-out;
}
@@ -94,14 +58,17 @@
}
.headerUserImage {
-webkit-background-size: contain;
background-size: contain;
background-repeat: no-repeat;
background-position: center center;
-webkit-border-radius: 100em;
border-radius: 100em;
display: inline-block;
}
.headerUserButtonRound div {
-webkit-border-radius: 100em;
border-radius: 100em;
background-size: cover;
background-repeat: no-repeat;
@@ -109,6 +76,7 @@
}
.headerButton {
-webkit-flex-shrink: 0;
flex-shrink: 0;
}
@@ -118,15 +86,23 @@
.headerLeft {
display: flex;
-webkit-align-items: center;
align-items: center;
-webkit-box-flex: 1;
-webkit-flex-grow: 1;
flex-grow: 1;
overflow: hidden;
justify-content: flex-start;
}
.headerRight {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-align-items: center;
align-items: center;
-webkit-box-pack: end;
-webkit-justify-content: flex-end;
justify-content: flex-end;
}
@@ -136,10 +112,15 @@
}
.pageTitle {
display: -webkit-inline-box;
display: -webkit-inline-flex;
display: inline-flex;
margin: 0 0 0 0.5em;
height: 1.7em;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
-webkit-flex-shrink: 1;
flex-shrink: 1;
}
@@ -149,16 +130,21 @@
.headerLeft,
.skinHeader {
display: flex;
display: -webkit-box;
display: -webkit-flex;
}
.detailButton,
.skinHeader {
flex-direction: column;
-webkit-flex-direction: column;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
}
.pageTitleWithLogo {
background-position: left center;
-webkit-background-size: contain;
background-size: contain;
background-repeat: no-repeat;
width: 13.2em;
@@ -177,12 +163,6 @@
transition: background ease-in-out 0.5s;
}
.layout-tv .skinHeader {
/* In TV layout, it makes more sense to keep the top bar at the top of the page
Having it follow the view only makes us lose vertical space, while not being focusable */
position: relative;
}
.hiddenViewMenuBar .skinHeader {
display: none;
}
@@ -204,19 +184,27 @@
}
.navMenuOption {
display: -webkit-box !important;
display: -webkit-flex !important;
display: flex !important;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
text-decoration: none;
color: inherit;
padding: 0.9em 0 0.9em 2.4em !important;
-webkit-box-flex: 1;
-webkit-flex-grow: 1;
flex-grow: 1;
font-weight: 400 !important;
margin: 0 !important;
-webkit-border-radius: 0 !important;
border-radius: 0 !important;
}
.navMenuOptionIcon {
margin-right: 1.2em;
-webkit-flex-shrink: 0;
flex-shrink: 0;
}
@@ -231,6 +219,8 @@
}
.dashboardDocument .skinBody {
-webkit-transition: left ease-in-out 0.3s, padding ease-in-out 0.3s;
-o-transition: left ease-in-out 0.3s, padding ease-in-out 0.3s;
transition: left ease-in-out 0.3s, padding ease-in-out 0.3s;
position: absolute;
top: 0;
@@ -246,6 +236,12 @@
text-align: center;
}
.layout-desktop .searchTabButton,
.layout-mobile .searchTabButton,
.layout-tv .headerSearchButton {
display: none !important;
}
.mainDrawer-scrollContainer {
padding-bottom: 10vh;
}
@@ -260,7 +256,9 @@
z-index: inherit !important;
left: 0 !important;
top: 0 !important;
-webkit-transform: none !important;
transform: none !important;
-webkit-box-shadow: none !important;
box-shadow: none !important;
width: 20.205em !important;
font-size: 94%;
@@ -295,9 +293,14 @@
}
.headerTabs {
-webkit-align-self: center;
align-self: center;
width: auto;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
-webkit-box-pack: center;
-webkit-justify-content: center;
justify-content: center;
position: relative;
margin-top: -4.3em;
@@ -354,6 +357,8 @@
}
.flexPageTabContent.is-active {
display: -webkit-box !important;
display: -webkit-flex !important;
display: flex !important;
}
@@ -374,17 +379,13 @@
margin: 1.5em 0;
background: #222;
padding: 0.8em 0.8em 0.8em 3em;
-webkit-border-radius: 0.3em;
border-radius: 0.3em;
position: relative;
}
.detailLogo {
width: 25vw;
height: 16vh;
position: absolute;
top: 10vh;
right: 25vw;
background-size: contain;
.detailLogo,
.itemBackdrop {
background-repeat: no-repeat;
background-position: center center;
}
@@ -437,34 +438,32 @@
}
.itemBackdrop {
-webkit-background-size: cover;
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
background-position: center;
background-attachment: fixed;
height: 40vh;
position: relative;
animation: backdrop-fadein 800ms ease-in normal both;
.layout-mobile & {
background-attachment: initial;
background-position: top center;
margin-top: 3rem;
@media all and (orientation: portrait) and (max-width: 40em) {
height: 30vh;
}
}
.layout-desktop &::after {
content: "";
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.65);
display: block;
}
}
.layout-tv .itemBackdrop {
.layout-mobile .itemBackdrop {
background-attachment: scroll;
height: 26.5vh;
}
.layout-desktop .itemBackdrop::after,
.layout-tv .itemBackdrop::after {
content: "";
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.65);
display: block;
}
.layout-desktop .noBackdrop .itemBackdrop,
.layout-tv .noBackdrop .itemBackdrop {
display: none;
}
@@ -473,18 +472,26 @@
flex-direction: column;
padding-left: 32.45vw;
padding-right: 2%;
}
.layout-mobile & {
padding-left: 5%;
padding-right: 5%;
}
.layout-mobile .detailPageContent {
padding-left: 5%;
padding-right: 5%;
}
.layout-desktop &,
.layout-tv & {
.emby-scroller {
margin-left: 0;
}
}
.layout-desktop .detailPageContent .emby-scroller,
.layout-tv .detailPageContent .emby-scroller {
margin-left: 0;
}
.layout-desktop .noBackdrop .detailPageContent,
.layout-tv .noBackdrop .detailPageContent {
margin-top: 2.5em;
}
.layout-desktop .noBackdrop .detailImageContainer img,
.layout-tv .noBackdrop .detailImageContainer img {
margin-top: 0;
}
.detailSectionContent a {
@@ -524,8 +531,14 @@
margin: -0.25em 0 0.25em;
}
.layout-mobile .itemExternalLinks {
display: none;
}
.mainDetailButtons {
display: flex;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
margin: 1em 0;
}
@@ -533,19 +546,13 @@
.detailButton,
.mainDetailButtons {
display: flex;
display: -webkit-box;
display: -webkit-flex;
}
.itemName {
margin: 0.5em 0;
font-weight: 600;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
.layout-mobile & {
white-space: normal;
overflow: visible;
}
}
.itemName.originalTitle {
@@ -584,19 +591,14 @@
}
.itemMiscInfo {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
.layout-mobile & {
@media all and (orientation: portrait) and (max-width: 40em) {
margin-bottom: 0 !important;
.mediaInfoItem {
margin-top: 0.5em;
}
}
}
}
.layout-mobile .parentName,
@@ -611,28 +613,14 @@
.layout-mobile .mainDetailButtons {
margin-top: 1em;
margin-bottom: 0.5em;
margin-left: 0;
@include header-poster-padding;
// The buttons row is full width on small screens
@media all and (max-width: 32em) {
margin-bottom: 0;
padding-left: 0;
}
}
.subtitle {
margin: 0.15em 0 0.2em;
// Leave room for a focused button
margin-left: -1em;
padding-left: 1em;
}
.layout-mobile .subtitle {
margin: 0.2em 0 0.2em;
padding-left: 0; // Reset padding for focused button since 'margin-left' is 0
}
.detailPagePrimaryContainer {
@@ -640,52 +628,47 @@
align-items: center;
align-content: center;
z-index: 2;
.layout-mobile & {
display: block;
position: relative;
padding: 0.5rem 5%;
}
.layout-desktop & {
position: relative;
padding-left: 32.45vw;
}
.layout-tv & {
display: block;
padding-left: 32.45vw;
}
}
.layout-desktop .detailRibbon {
.layout-mobile .detailPagePrimaryContainer {
display: block;
position: relative;
padding: 0.5em 3.3% 0.5em;
}
.layout-tv #itemDetailPage:not(.noBackdrop) .detailPagePrimaryContainer,
.layout-desktop #itemDetailPage:not(.noBackdrop) .detailPagePrimaryContainer {
position: relative;
top: 0;
padding-left: 32.45vw;
}
.layout-desktop .detailRibbon,
.layout-tv .detailRibbon {
margin-top: -7.2em;
height: 7.2em;
}
.layout-tv .detailRibbon {
.layout-desktop .noBackdrop .detailRibbon,
.layout-tv .noBackdrop .detailRibbon {
margin-top: 0;
height: inherit;
}
.infoWrapper {
min-width: 0;
max-width: 100%;
flex: 1 0 0;
.layout-mobile & {
@include header-poster-padding;
@media all and (max-width: 32em) {
position: relative;
}
}
}
.infoText {
white-space: nowrap;
text-overflow: ellipsis;
text-align: left;
min-width: 0;
max-width: 100%;
overflow: hidden;
}
.layout-mobile .infoText {
white-space: normal;
}
.detailPageSecondaryContainer {
@@ -696,66 +679,46 @@
margin: 1em 0;
}
.layout-mobile .detailImageContainer {
display: none;
}
.detailImageContainer .card {
// important is needed here to override :focus setting
// the position to relative in the tv layout
position: absolute !important;
top: 20%;
max-width: 25vw;
max-height: 80vh;
position: absolute;
top: 50%;
float: left;
width: 25vw;
z-index: 3;
transform: translateY(-50%);
}
.cardBox {
margin: 0;
}
.detailImageContainer .card.backdropCard {
top: 35%;
}
&.backdropCard {
top: 35%;
}
.detailImageContainer .card.squareCard {
top: 40%;
}
&.squareCard {
top: 40%;
}
.layout-mobile & {
left: 5%;
bottom: 1rem;
max-width: 30vw;
filter: drop-shadow(0 0 0.5rem #000);
@media all and (max-width: 32em) {
left: 0;
bottom: 0;
}
&,
&.backdropCard,
&.squareCard {
top: auto;
}
}
.layout-desktop & {
left: 3.3%;
top: -80%;
width: 25vw;
// FIXME: the fixed width + max height cause the card to be cropped this needs a proper fix
max-height: none;
}
.layout-tv & {
left: 5%;
top: 50%;
width: 25vw;
transform: translateY(-50%);
}
.layout-desktop .noBackdrop .detailImageContainer,
.layout-tv .noBackdrop .detailImageContainer {
margin-top: 0;
}
.detailPagePrimaryContent {
position: relative;
}
.layout-mobile .detailLogo {
.detailLogo {
width: 25vw;
height: 16vh;
position: absolute;
top: 10vh;
right: 25vw;
background-size: contain;
}
.noBackdrop .detailLogo {
display: none;
}
@@ -767,6 +730,7 @@
.itemDetailImage {
width: 100% !important;
-webkit-box-shadow: 0 0.1em 0.5em 0 rgba(0, 0, 0, 0.75);
box-shadow: 0 0.1em 0.5em 0 rgba(0, 0, 0, 0.75);
}
@@ -779,17 +743,6 @@ div.itemDetailGalleryLink.defaultCardBackground {
height: 23vw;
}
.sectionTitleTextButton > .material-icons {
font-size: 1.5em;
margin-bottom: 0.35em;
margin-top: 0;
}
.layout-mobile .sectionTitleTextButton > .material-icons {
margin-bottom: 0;
padding-top: 0.5em;
}
.itemDetailGalleryLink.defaultCardBackground > .material-icons {
font-size: 15vw;
margin-top: 50%;
@@ -801,7 +754,8 @@ div.itemDetailGalleryLink.defaultCardBackground {
position: relative;
}
.layout-desktop .itemBackdrop {
.layout-desktop .itemBackdrop,
.layout-tv .itemBackdrop {
height: 40vh;
}
@@ -827,8 +781,13 @@ div.itemDetailGalleryLink.defaultCardBackground {
}
.emby-button.detailFloatingButton {
font-size: 1.4em;
margin-right: 0.5em !important;
position: absolute;
background-color: rgba(0, 0, 0, 0.5);
z-index: 3;
top: 100%;
left: 90%;
margin: -2.2em 0 0 -2.2em;
padding: 0.4em;
color: rgba(255, 255, 255, 0.76);
}
@@ -873,6 +832,7 @@ div.itemDetailGalleryLink.defaultCardBackground {
.recordingFields button {
margin-left: 0;
margin-right: 0.5em;
-webkit-flex-shrink: 0;
flex-shrink: 0;
}
@@ -883,10 +843,14 @@ div.itemDetailGalleryLink.defaultCardBackground {
.detailButton {
display: flex;
flex-direction: column;
-webkit-box-pack: center;
-webkit-justify-content: center;
justify-content: center;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
margin: 0 !important;
padding: 0.7em 0.7em !important;
padding: 0.5em 0.7em !important;
}
@media all and (min-width: 29em) {
@@ -911,9 +875,18 @@ div.itemDetailGalleryLink.defaultCardBackground {
}
.detailButton-content {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
flex-direction: column;
-webkit-box-pack: center;
-webkit-justify-content: center;
justify-content: center;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
}
@@ -946,6 +919,10 @@ div.itemDetailGalleryLink.defaultCardBackground {
}
@media all and (min-width: 100em) {
.detailFloatingButton {
display: none !important;
}
.personBackdrop {
display: none !important;
}
@@ -954,11 +931,6 @@ div.itemDetailGalleryLink.defaultCardBackground {
font-size: 108%;
margin: 1.25em 0;
}
.layout-tv .mainDetailButtons {
font-size: 108%;
margin: 1em 0 1.25em;
}
}
@media all and (max-width: 50em) {
@@ -970,6 +942,8 @@ div.itemDetailGalleryLink.defaultCardBackground {
@media all and (max-width: 31.25em) {
.mobileDetails .itemMiscInfo {
text-align: center;
-webkit-box-pack: center;
-webkit-justify-content: center;
justify-content: center;
}
@@ -991,8 +965,9 @@ div.itemDetailGalleryLink.defaultCardBackground {
border-collapse: collapse;
}
.mediaInfoContent .btnCopy .material-icons {
font-size: inherit;
.layout-desktop .noBackdrop .detailPageWrapperContainer,
.layout-tv .noBackdrop .detailPageWrapperContainer {
margin-top: 3.8em;
}
.mediaInfoStream {
@@ -1003,10 +978,6 @@ div.itemDetailGalleryLink.defaultCardBackground {
.mediaInfoStreamType {
display: block;
margin: 0.622em 0; /* copy button height compensation */
}
.layout-tv .mediaInfoStreamType {
margin: 1em 0;
}
@@ -1058,9 +1029,14 @@ div.itemDetailGalleryLink.defaultCardBackground {
}
.mediaInfoIcons {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
margin: 1em 0;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
}
@@ -1075,7 +1051,7 @@ div.itemDetailGalleryLink.defaultCardBackground {
.sectionTitleButton,
.sectionTitleIconButton {
margin-right: 0 !important;
display: inline-flex;
display: inline-block;
vertical-align: middle;
}
@@ -1108,6 +1084,7 @@ div:not(.sectionTitleContainer-cards) > .sectionTitle-cards {
.sectionTitleButton {
margin-left: 1.5em !important;
-webkit-flex-shrink: 0;
flex-shrink: 0;
}
@@ -1117,17 +1094,22 @@ div:not(.sectionTitleContainer-cards) > .sectionTitle-cards {
.sectionTitleIconButton {
margin-left: 1.5em !important;
-webkit-flex-shrink: 0;
flex-shrink: 0;
font-size: 84% !important;
padding: 0.5em !important;
}
.horizontalItemsContainer {
display: -webkit-box;
display: -webkit-flex;
display: flex;
}
.sectionTitleTextButton {
margin: 0 !important;
display: -webkit-inline-box !important;
display: -webkit-inline-flex !important;
display: inline-flex !important;
color: inherit !important;
}
@@ -1164,13 +1146,13 @@ div:not(.sectionTitleContainer-cards) > .sectionTitle-cards {
}
.layout-tv .padded-top-focusscale {
padding-top: 1.5em;
margin-top: -1.5em;
padding-top: 1em;
margin-top: -1em;
}
.layout-tv .padded-bottom-focusscale {
padding-bottom: 1.5em;
margin-bottom: -1.5em;
padding-bottom: 1em;
margin-bottom: -1em;
}
@media all and (min-height: 31.25em) {
@@ -1195,6 +1177,8 @@ div:not(.sectionTitleContainer-cards) > .sectionTitle-cards {
}
.itemsViewSettingsContainer {
-webkit-box-pack: center;
-webkit-justify-content: center;
justify-content: center;
}
@@ -1219,7 +1203,7 @@ div:not(.sectionTitleContainer-cards) > .sectionTitle-cards {
}
.itemDetailsGroup {
margin-top: 1.5em;
margin-bottom: 1.5em;
}
.trackSelections {

View File

@@ -0,0 +1,9 @@
.guideVerticalScroller {
padding-bottom: 15em;
}
@media all and (min-width: 62.5em) {
#guideTab {
padding-left: 0.5em;
}
}

View File

@@ -1,14 +0,0 @@
.guideVerticalScroller {
padding-bottom: 15em;
}
#guideTab {
@media all and (min-width: 62.5em) {
padding-left: 0.5em;
}
}
// FIXME: background sizing for cards really needs revisited, but these are particularly terrible
#channelsTab .cardImageContainer {
background-size: contain;
}

View File

@@ -1,19 +1,14 @@
@mixin fullpage {
body,
html {
margin: 0;
padding: 0;
height: 100%;
}
html {
@include fullpage;
line-height: 1.35;
}
body {
@include fullpage;
overflow-x: hidden;
background-color: transparent !important;
-webkit-font-smoothing: antialiased;
.layout-mobile,
.layout-tv {
-webkit-touch-callout: none;
user-select: none;
}
.clipForScreenReader {
@@ -41,10 +36,14 @@ body {
contain: strict;
}
.layout-mobile,
.layout-tv {
-webkit-touch-callout: none;
user-select: none;
html {
line-height: 1.35;
}
body {
overflow-x: hidden;
background-color: transparent !important;
-webkit-font-smoothing: antialiased;
}
.mainAnimatedPage {
@@ -59,7 +58,7 @@ body {
overflow-y: hidden !important;
}
div[data-role="page"] {
div[data-role=page] {
outline: 0;
}
@@ -72,10 +71,10 @@ div[data-role="page"] {
padding-left: 0.15em;
font-weight: 400;
white-space: normal !important;
}
+ .fieldDescription {
margin-top: 0.3em;
}
.fieldDescription + .fieldDescription {
margin-top: 0.3em;
}
.content-primary,
@@ -86,14 +85,9 @@ div[data-role="page"] {
padding-bottom: 5em !important;
}
.readOnlyContent {
@media all and (min-width: 50em) {
max-width: 54em;
}
}
form {
@media all and (min-width: 50em) {
@media all and (min-width: 50em) {
.readOnlyContent,
form {
max-width: 54em;
}
}
@@ -113,14 +107,14 @@ form {
.headroom {
will-change: transform;
transition: transform 200ms linear;
}
&--pinned {
transform: translateY(0%);
}
.headroom--pinned {
transform: translateY(0%);
}
&--unpinned {
transform: translateY(-100%);
}
.headroom--unpinned {
transform: translateY(-100%);
}
.drawerContent {
@@ -135,17 +129,3 @@ form {
.hide-scroll {
overflow-y: hidden;
}
.w-100 {
width: 100%;
}
.margin-auto-x {
margin-left: auto;
margin-right: auto;
}
.margin-auto-y {
margin-top: auto;
margin-bottom: auto;
}

View File

@@ -6,45 +6,29 @@
-ms-user-select: none;
}
.osdPoster img,
.videoOsdBottom {
bottom: 0;
left: 0;
right: 0;
position: fixed;
background: linear-gradient(0deg, rgba(16, 16, 16, 0.75) 0%, rgba(16, 16, 16, 0) 100%);
padding-top: 7.5em;
padding-bottom: 1.75em;
display: flex;
flex-direction: row;
justify-content: center;
will-change: opacity;
transition: opacity 0.3s ease-out;
color: #fff;
user-select: none;
-webkit-touch-callout: none;
pointer-events: none;
}
.skinHeader-withBackground.osdHeader {
.osdHeader {
-webkit-transition: opacity 0.3s ease-out;
-o-transition: opacity 0.3s ease-out;
transition: opacity 0.3s ease-out;
position: relative;
z-index: 1;
background: linear-gradient(180deg, rgba(16, 16, 16, 0.75) 0%, rgba(16, 16, 16, 0) 100%);
backdrop-filter: none;
color: #eee;
height: 7.5em;
pointer-events: none;
background: rgba(0, 0, 0, 0.7) !important;
-webkit-backdrop-filter: none !important;
backdrop-filter: none !important;
color: #eee !important;
}
.osdHeader-hidden {
opacity: 0;
}
.osdHeader .headerTop {
pointer-events: all;
max-height: 3.5em;
}
.osdHeader .headerButton:not(.headerBackButton):not(.headerCastButton):not(.headerSyncButton) {
display: none;
}
@@ -102,18 +86,34 @@
opacity: 0.6;
}
.videoOsdBottom {
position: fixed;
background-color: rgba(0, 0, 0, 0.7);
padding: 1%;
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
flex-direction: row;
will-change: opacity;
-webkit-transition: opacity 0.3s ease-out;
-o-transition: opacity 0.3s ease-out;
transition: opacity 0.3s ease-out;
color: #fff;
user-select: none;
-webkit-touch-callout: none;
}
.videoOsdBottom-hidden {
opacity: 0;
}
.osdControls {
pointer-events: all;
-webkit-box-flex: 1;
-webkit-flex-grow: 1;
flex-grow: 1;
padding: 0 0.8em;
}
.layout-desktop .osdControls {
max-width: calc(100vh * 1.77 - 2vh);
}
.videoOsdBottom .buttons {
@@ -145,7 +145,7 @@
}
.volumeButtons {
margin: 0 1em 0 0.29em;
margin: 0 0.5em 0 auto;
display: flex;
-webkit-align-items: center;
align-items: center;
@@ -153,13 +153,33 @@
.osdTimeText {
margin-left: 1em;
margin-right: auto;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.osdPoster {
width: 10%;
position: relative;
margin-right: 0.5em;
}
.osdPoster img {
position: absolute;
height: auto;
width: 100%;
-webkit-box-shadow: 0 0 1.9vh #000;
box-shadow: 0 0 1.9vh #000;
border: 0.08em solid #222;
user-drag: none;
user-select: none;
-moz-user-select: none;
-webkit-user-drag: none;
-webkit-user-select: none;
-ms-user-select: none;
}
.osdTitle,
.osdTitleSmall {
margin: 0 1em 0 0;
@@ -228,6 +248,8 @@
}
@media all and (max-width: 30em) {
.btnFastForward,
.btnRewind,
.osdMediaInfo,
.osdPoster {
display: none !important;
@@ -259,119 +281,3 @@
display: none !important;
}
}
.syncPlayContainer {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
pointer-events: none;
top: 0;
bottom: 0;
right: 0;
left: 0;
}
.primary-icon {
position: absolute;
font-size: 64px;
align-self: center;
}
.primary-icon.spin {
font-size: 76px !important;
animation: spin 2s linear infinite;
}
.secondary-icon {
position: absolute;
font-size: 24px;
}
.secondary-icon.centered {
font-size: 28px !important;
align-self: center;
}
.secondary-icon.shifted {
right: 0;
bottom: 0;
font-size: 52px;
}
.syncPlayIconCircle {
position: relative;
visibility: hidden;
display: flex;
justify-content: center;
border-radius: 50%;
margin: 60px;
height: 96px;
width: 96px;
color: rgba(0, 164, 220, 0);
background: rgba(0, 164, 220, 0);
box-shadow: 0 0 0 0 rgba(0, 164, 220, 0);
transform: scale(1);
}
.syncPlayIconCircle.oneShotPulse {
animation: pulse 1.5s 1;
}
.syncPlayIconCircle.infinitePulse {
animation: infinite-pulse 1.5s infinite;
}
@keyframes pulse {
0% {
transform: scale(0.95);
color: rgba(0, 164, 220, 0.7);
background: rgba(0, 164, 220, 0.3);
box-shadow: 0 0 0 0 rgba(0, 164, 220, 0.3);
}
70% {
transform: scale(1);
color: rgba(0, 164, 220, 0);
background: rgba(0, 164, 220, 0);
box-shadow: 0 0 0 60px rgba(0, 164, 220, 0);
}
100% {
transform: scale(0.95);
color: rgba(0, 164, 220, 0);
background: rgba(0, 164, 220, 0);
box-shadow: 0 0 0 0 rgba(0, 164, 220, 0);
}
}
@keyframes infinite-pulse {
0% {
transform: scale(0.95);
color: rgba(0, 164, 220, 0.7);
background: rgba(0, 164, 220, 0.3);
box-shadow: 0 0 0 0 rgba(0, 164, 220, 0.3);
}
70% {
transform: scale(1);
color: rgba(0, 164, 220, 0.6);
background: rgba(0, 164, 220, 0);
box-shadow: 0 0 0 60px rgba(0, 164, 220, 0);
}
100% {
transform: scale(0.95);
color: rgba(0, 164, 220, 0.7);
background: rgba(0, 164, 220, 0.3);
box-shadow: 0 0 0 0 rgba(0, 164, 220, 0);
}
}
@keyframes spin {
100% {
transform: rotate(-360deg);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -1 +0,0 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Apple</title><path d="M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701" fill="#fff"/></svg>

Before

Width:  |  Height:  |  Size: 663 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 43 KiB

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