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

Merge branch 'master' of https://github.com/jellyfin/jellyfin-web into move-tvlatest

# Conflicts:
#	src/controllers/shows/tvlatest.js
#	src/controllers/shows/tvrecommended.js
This commit is contained in:
grafixeyehero 2020-09-13 01:50:38 +03:00
commit 5f56bb15c2
491 changed files with 36664 additions and 43163 deletions

View file

@ -36,6 +36,14 @@ jobs:
targetPath: '$(Build.SourcesDirectory)/deployment/dist' targetPath: '$(Build.SourcesDirectory)/deployment/dist'
artifactName: 'jellyfin-web-$(BuildConfiguration)' artifactName: 'jellyfin-web-$(BuildConfiguration)'
- task: SSH@0
displayName: 'Create target directory on repository server'
condition: or(startsWith(variables['Build.SourceBranch'], 'refs/tags'), startsWith(variables['Build.SourceBranch'], 'refs/heads/master'))
inputs:
sshEndpoint: repository
runOptions: 'inline'
inline: 'mkdir -p /srv/repository/incoming/azure/$(Build.BuildNumber)/$(BuildConfiguration)'
- task: CopyFilesOverSSH@0 - task: CopyFilesOverSSH@0
displayName: 'Upload artifacts to repository server' displayName: 'Upload artifacts to repository server'
condition: or(startsWith(variables['Build.SourceBranch'], 'refs/tags'), startsWith(variables['Build.SourceBranch'], 'refs/heads/master')) condition: or(startsWith(variables['Build.SourceBranch'], 'refs/tags'), startsWith(variables['Build.SourceBranch'], 'refs/heads/master'))
@ -51,7 +59,15 @@ jobs:
pool: pool:
vmImage: 'ubuntu-latest' vmImage: 'ubuntu-latest'
variables:
- name: JellyfinVersion
value: 0.0.0
steps: 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')
- task: Docker@2 - task: Docker@2
displayName: 'Push Unstable Image' displayName: 'Push Unstable Image'
condition: startsWith(variables['Build.SourceBranch'], 'refs/heads/master') condition: startsWith(variables['Build.SourceBranch'], 'refs/heads/master')
@ -76,7 +92,7 @@ jobs:
containerRegistry: Docker Hub containerRegistry: Docker Hub
tags: | tags: |
stable-$(Build.BuildNumber) stable-$(Build.BuildNumber)
stable $(JellyfinVersion)
- job: CollectArtifacts - job: CollectArtifacts
displayName: 'Collect Artifacts' displayName: 'Collect Artifacts'

View file

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

View file

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

View file

@ -1,6 +1,9 @@
const restrictedGlobals = require('confusing-browser-globals');
module.exports = { module.exports = {
root: true, root: true,
plugins: [ plugins: [
'@babel',
'promise', 'promise',
'import', 'import',
'eslint-comments' 'eslint-comments'
@ -28,7 +31,7 @@ module.exports = {
], ],
rules: { rules: {
'block-spacing': ['error'], 'block-spacing': ['error'],
'brace-style': ['error'], 'brace-style': ['error', '1tbs', { 'allowSingleLine': true }],
'comma-dangle': ['error', 'never'], 'comma-dangle': ['error', 'never'],
'comma-spacing': ['error'], 'comma-spacing': ['error'],
'eol-last': ['error'], 'eol-last': ['error'],
@ -38,19 +41,24 @@ module.exports = {
'no-floating-decimal': ['error'], 'no-floating-decimal': ['error'],
'no-multi-spaces': ['error'], 'no-multi-spaces': ['error'],
'no-multiple-empty-lines': ['error', { 'max': 1 }], 'no-multiple-empty-lines': ['error', { 'max': 1 }],
'no-restricted-globals': ['error'].concat(restrictedGlobals),
'no-trailing-spaces': ['error'], 'no-trailing-spaces': ['error'],
'@babel/no-unused-expressions': ['error', { 'allowShortCircuit': true, 'allowTernary': true, 'allowTaggedTemplates': true }],
'one-var': ['error', 'never'], 'one-var': ['error', 'never'],
'padded-blocks': ['error', 'never'],
'prefer-const': ['error', {'destructuring': 'all'}],
'quotes': ['error', 'single', { 'avoidEscape': true, 'allowTemplateLiterals': false }], 'quotes': ['error', 'single', { 'avoidEscape': true, 'allowTemplateLiterals': false }],
'semi': ['error'], '@babel/semi': ['error'],
'space-before-blocks': ['error'], 'space-before-blocks': ['error'],
'space-infix-ops': 'error' 'space-infix-ops': 'error',
'yoda': 'error'
}, },
overrides: [ overrides: [
{ {
files: [ files: [
'./src/**/*.js' './src/**/*.js'
], ],
parser: 'babel-eslint', parser: '@babel/eslint-parser',
env: { env: {
node: false, node: false,
amd: true, amd: true,
@ -75,7 +83,6 @@ module.exports = {
'ApiClient': 'writable', 'ApiClient': 'writable',
'AppInfo': 'writable', 'AppInfo': 'writable',
'chrome': 'writable', 'chrome': 'writable',
'ConnectionManager': 'writable',
'DlnaProfilePage': 'writable', 'DlnaProfilePage': 'writable',
'Dashboard': 'writable', 'Dashboard': 'writable',
'DashboardPage': 'writable', 'DashboardPage': 'writable',
@ -98,9 +105,9 @@ module.exports = {
}, },
rules: { rules: {
// TODO: Fix warnings and remove these rules // TODO: Fix warnings and remove these rules
'no-redeclare': ['warn'], 'no-redeclare': ['off'],
'no-unused-vars': ['warn'], 'no-useless-escape': ['off'],
'no-useless-escape': ['warn'], 'no-unused-vars': ['off'],
// TODO: Remove after ES6 migration is complete // TODO: Remove after ES6 migration is complete
'import/no-unresolved': ['off'] 'import/no-unresolved': ['off']
}, },
@ -193,4 +200,4 @@ module.exports = {
} }
} }
] ]
} };

4
.github/CODEOWNERS vendored
View file

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

View file

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

View file

@ -0,0 +1,22 @@
---
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

@ -0,0 +1,13 @@
---
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

@ -0,0 +1,9 @@
---
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]
* [ ] ...

8
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View file

@ -0,0 +1,8 @@
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 Normal file
View file

@ -0,0 +1,24 @@
# 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](https://webchat.freenode.net/#jellyfin)
* #jellyfin-troubleshooting on [Matrix](https://matrix.to/#/#jellyfin-troubleshooting:matrix.org) or [IRC](https://webchat.freenode.net/#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.

View file

@ -35,7 +35,10 @@
- [Thibault Nocchi](https://github.com/ThibaultNocchi) - [Thibault Nocchi](https://github.com/ThibaultNocchi)
- [MrTimscampi](https://github.com/MrTimscampi) - [MrTimscampi](https://github.com/MrTimscampi)
- [Sarab Singh](https://github.com/sarab97) - [Sarab Singh](https://github.com/sarab97)
- [GuilhermeHideki](https://github.com/GuilhermeHideki)
- [Andrei Oanca](https://github.com/OancaAndrei) - [Andrei Oanca](https://github.com/OancaAndrei)
- [Cromefire_](https://github.com/cromefire)
- [Orry Verducci](https://github.com/orryverducci)
# Emby Contributors # Emby Contributors

View file

@ -44,6 +44,7 @@ Jellyfin Web is the frontend used for most of the clients available for end user
### Dependencies ### Dependencies
- [Node.js](https://nodejs.org/en/download/)
- [Yarn 1.22.4](https://classic.yarnpkg.com/en/docs/install) - [Yarn 1.22.4](https://classic.yarnpkg.com/en/docs/install)
- Gulp-cli - Gulp-cli

View file

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

View file

@ -4,6 +4,7 @@
set -o errexit set -o errexit
set -o pipefail set -o pipefail
set -o xtrace
usage() { usage() {
echo -e "bump_version - increase the shared version and generate changelogs" echo -e "bump_version - increase the shared version and generate changelogs"
@ -23,10 +24,7 @@ build_file="./build.yaml"
new_version="$1" new_version="$1"
# Parse the version from shared version file # Parse the version from shared version file
old_version="$( old_version="$( grep "appVersion" ${shared_version_file} | head -1 | sed -E "s/var appVersion = '([0-9\.]+)';/\1/" | tr -d '[:space:]' )"
grep "appVersion" ${shared_version_file} | head -1 \
| sed -E 's/var appVersion = "([0-9\.]+)";/\1/'
)"
echo "Old version in appHost is: $old_version" echo "Old version in appHost is: $old_version"
# Set the shared version to the specified new_version # Set the shared version to the specified new_version
@ -34,11 +32,8 @@ old_version_sed="$( sed 's/\./\\./g' <<<"${old_version}" )" # Escape the '.' cha
new_version_sed="$( cut -f1 -d'-' <<<"${new_version}" )" new_version_sed="$( cut -f1 -d'-' <<<"${new_version}" )"
sed -i "s/${old_version_sed}/${new_version_sed}/g" ${shared_version_file} sed -i "s/${old_version_sed}/${new_version_sed}/g" ${shared_version_file}
old_version="$( old_version="$( grep "version:" ${build_file} | sed -E 's/version: "([0-9\.]+[-a-z0-9]*)"/\1/' )"
grep "version:" ${build_file} \ echo "Old version in ${build_file}: ${old_version}"
| 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 # Set the build.yaml version to the specified new_version
old_version_sed="$( sed 's/\./\\./g' <<<"${old_version}" )" # Escape the '.' chars old_version_sed="$( sed 's/\./\\./g' <<<"${old_version}" )" # Escape the '.' chars
@ -54,7 +49,7 @@ fi
debian_changelog_file="debian/changelog" debian_changelog_file="debian/changelog"
debian_changelog_temp="$( mktemp )" debian_changelog_temp="$( mktemp )"
# Create new temp file with our changelog # Create new temp file with our changelog
echo -e "jellyfin (${new_version_deb}) 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} * New upstream version ${new_version}; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v${new_version}
@ -65,15 +60,15 @@ cat ${debian_changelog_file} >> ${debian_changelog_temp}
mv ${debian_changelog_temp} ${debian_changelog_file} mv ${debian_changelog_temp} ${debian_changelog_file}
# Write out a temporary Yum changelog with our new stuff prepended and some templated formatting # Write out a temporary Yum changelog with our new stuff prepended and some templated formatting
fedora_spec_file="fedora/jellyfin.spec" fedora_spec_file="fedora/jellyfin-web.spec"
fedora_changelog_temp="$( mktemp )" fedora_changelog_temp="$( mktemp )"
fedora_spec_temp_dir="$( mktemp -d )" fedora_spec_temp_dir="$( mktemp -d )"
fedora_spec_temp="${fedora_spec_temp_dir}/jellyfin.spec.tmp" fedora_spec_temp="${fedora_spec_temp_dir}/jellyfin-web.spec.tmp"
# Make a copy of our spec file for hacking # Make a copy of our spec file for hacking
cp ${fedora_spec_file} ${fedora_spec_temp_dir}/ cp ${fedora_spec_file} ${fedora_spec_temp_dir}/
pushd ${fedora_spec_temp_dir} pushd ${fedora_spec_temp_dir}
# Split out the stuff before and after changelog # Split out the stuff before and after changelog
csplit jellyfin.spec "/^%changelog/" # produces xx00 xx01 csplit jellyfin-web.spec "/^%changelog/" # produces xx00 xx01
# Update the version in xx00 # Update the version in xx00
sed -i "s/${old_version_sed}/${new_version_sed}/g" xx00 sed -i "s/${old_version_sed}/${new_version_sed}/g" xx00
# Remove the header from xx01 # Remove the header from xx01
@ -92,5 +87,5 @@ mv ${fedora_spec_temp} ${fedora_spec_file}
rm -rf ${fedora_changelog_temp} ${fedora_spec_temp_dir} rm -rf ${fedora_changelog_temp} ${fedora_spec_temp_dir}
# Stage the changed files for commit # Stage the changed files for commit
git add ${shared_version_file} ${build_file} ${debian_changelog_file} ${fedora_spec_file} Dockerfile* git add ${shared_version_file} ${build_file} ${debian_changelog_file} ${fedora_spec_file}
git status git status

6
debian/changelog vendored
View file

@ -1,3 +1,9 @@
jellyfin-web (10.7.0-1) unstable; urgency=medium
* Forthcoming stable release
-- Jellyfin Packaging Team <packaging@jellyfin.org> Mon, 27 Jul 2020 19:13:31 -0400
jellyfin-web (10.6.0-1) unstable; urgency=medium jellyfin-web (10.6.0-1) unstable; urgency=medium
* New upstream version 10.6.0; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.6.0 * New upstream version 10.6.0; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.6.0

View file

@ -1,7 +1,7 @@
%global debug_package %{nil} %global debug_package %{nil}
Name: jellyfin-web Name: jellyfin-web
Version: 10.6.0 Version: 10.7.0
Release: 1%{?dist} Release: 1%{?dist}
Summary: The Free Software Media System web client Summary: The Free Software Media System web client
License: GPLv3 License: GPLv3
@ -11,6 +11,8 @@ Source0: jellyfin-web-%{version}.tar.gz
%if 0%{?centos} %if 0%{?centos}
BuildRequires: yarn BuildRequires: yarn
# sadly the yarn RPM at https://dl.yarnpkg.com/rpm/ uses git but doesn't Requires: it
BuildRequires: git
%else %else
BuildRequires: nodejs-yarn BuildRequires: nodejs-yarn
%endif %endif
@ -39,5 +41,7 @@ mv dist %{buildroot}%{_datadir}/jellyfin-web
%{_datadir}/licenses/jellyfin/LICENSE %{_datadir}/licenses/jellyfin/LICENSE
%changelog %changelog
* Mon Jul 27 2020 Jellyfin Packaging Team <packaging@jellyfin.org>
- Forthcoming stable release
* Mon Mar 23 2020 Jellyfin Packaging Team <packaging@jellyfin.org> * Mon Mar 23 2020 Jellyfin Packaging Team <packaging@jellyfin.org>
- Forthcoming stable release - Forthcoming stable release

View file

@ -184,7 +184,12 @@ function copy(query) {
function injectBundle() { function injectBundle() {
return src(options.injectBundle.query, { base: './src/' }) return src(options.injectBundle.query, { base: './src/' })
.pipe(inject( .pipe(inject(
src(['src/scripts/apploader.js'], { read: false }, { base: './src/' }), { relative: true } src(['src/scripts/apploader.js'], { read: false }, { base: './src/' }), {
relative: true,
transform: function (filepath) {
return `<script src="${filepath}" defer></script>`;
}
}
)) ))
.pipe(dest('dist/')) .pipe(dest('dist/'))
.pipe(browserSync.stream()); .pipe(browserSync.stream());

View file

@ -5,26 +5,28 @@
"repository": "https://github.com/jellyfin/jellyfin-web", "repository": "https://github.com/jellyfin/jellyfin-web",
"license": "GPL-2.0-or-later", "license": "GPL-2.0-or-later",
"devDependencies": { "devDependencies": {
"@babel/core": "^7.10.3", "@babel/core": "^7.11.6",
"@babel/eslint-parser": "^7.11.5",
"@babel/eslint-plugin": "^7.11.5",
"@babel/plugin-proposal-class-properties": "^7.10.1", "@babel/plugin-proposal-class-properties": "^7.10.1",
"@babel/plugin-proposal-private-methods": "^7.10.1", "@babel/plugin-proposal-private-methods": "^7.10.1",
"@babel/plugin-transform-modules-amd": "^7.9.6", "@babel/plugin-transform-modules-amd": "^7.10.5",
"@babel/polyfill": "^7.8.7", "@babel/polyfill": "^7.11.5",
"@babel/preset-env": "^7.10.3", "@babel/preset-env": "^7.11.5",
"autoprefixer": "^9.8.2", "autoprefixer": "^9.8.6",
"babel-eslint": "^11.0.0-beta.2",
"babel-loader": "^8.0.6", "babel-loader": "^8.0.6",
"browser-sync": "^2.26.7", "browser-sync": "^2.26.12",
"confusing-browser-globals": "^1.0.9",
"copy-webpack-plugin": "^5.1.1", "copy-webpack-plugin": "^5.1.1",
"css-loader": "^3.6.0", "css-loader": "^4.2.2",
"cssnano": "^4.1.10", "cssnano": "^4.1.10",
"del": "^5.1.0", "del": "^5.1.0",
"eslint": "^6.8.0", "eslint": "^7.8.1",
"eslint-plugin-compat": "^3.5.1", "eslint-plugin-compat": "^3.5.1",
"eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-import": "^2.21.2", "eslint-plugin-import": "^2.21.2",
"eslint-plugin-promise": "^4.2.1", "eslint-plugin-promise": "^4.2.1",
"file-loader": "^6.0.0", "file-loader": "^6.1.0",
"gulp": "^4.0.2", "gulp": "^4.0.2",
"gulp-babel": "^8.0.0", "gulp-babel": "^8.0.0",
"gulp-cli": "^2.3.0", "gulp-cli": "^2.3.0",
@ -37,51 +39,51 @@
"gulp-postcss": "^8.0.0", "gulp-postcss": "^8.0.0",
"gulp-sass": "^4.0.2", "gulp-sass": "^4.0.2",
"gulp-sourcemaps": "^2.6.5", "gulp-sourcemaps": "^2.6.5",
"gulp-terser": "^1.2.0", "gulp-terser": "^1.4.0",
"html-webpack-plugin": "^4.3.0", "html-webpack-plugin": "^4.4.1",
"lazypipe": "^1.0.2", "lazypipe": "^1.0.2",
"node-sass": "^4.13.1", "node-sass": "^4.13.1",
"postcss-loader": "^3.0.0", "postcss-loader": "^3.0.0",
"postcss-preset-env": "^6.7.0", "postcss-preset-env": "^6.7.0",
"style-loader": "^1.1.3", "style-loader": "^1.1.3",
"stylelint": "^13.6.1", "stylelint": "^13.7.0",
"stylelint-config-rational-order": "^0.1.2", "stylelint-config-rational-order": "^0.1.2",
"stylelint-no-browser-hacks": "^1.2.1", "stylelint-no-browser-hacks": "^1.2.1",
"stylelint-order": "^4.1.0", "stylelint-order": "^4.1.0",
"webpack": "^4.41.5", "webpack": "^4.44.1",
"webpack-merge": "^4.2.2", "webpack-merge": "^4.2.2",
"webpack-stream": "^5.2.1" "webpack-stream": "^6.1.0",
"worker-plugin": "^5.0.0"
}, },
"dependencies": { "dependencies": {
"alameda": "^1.4.0", "alameda": "^1.4.0",
"blurhash": "^1.1.3", "blurhash": "^1.1.3",
"classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz", "classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"date-fns": "^2.14.0", "date-fns": "^2.16.1",
"document-register-element": "^1.14.3",
"epubjs": "^0.3.85", "epubjs": "^0.3.85",
"fast-text-encoding": "^1.0.3", "fast-text-encoding": "^1.0.3",
"flv.js": "^1.5.0", "flv.js": "^1.5.0",
"headroom.js": "^0.11.0", "headroom.js": "^0.11.0",
"hls.js": "^0.13.1", "hls.js": "^0.14.11",
"howler": "^2.2.0", "howler": "^2.2.0",
"intersection-observer": "^0.10.0", "intersection-observer": "^0.11.0",
"jellyfin-apiclient": "^1.3.0", "jellyfin-apiclient": "^1.4.1",
"jellyfin-noto": "https://github.com/jellyfin/jellyfin-noto", "jellyfin-noto": "https://github.com/jellyfin/jellyfin-noto",
"jquery": "^3.5.1", "jquery": "^3.5.1",
"jstree": "^3.3.10", "jstree": "^3.3.10",
"libarchive.js": "^1.3.0",
"libass-wasm": "https://github.com/jellyfin/JavascriptSubtitlesOctopus#4.0.0-jf-smarttv", "libass-wasm": "https://github.com/jellyfin/JavascriptSubtitlesOctopus#4.0.0-jf-smarttv",
"material-design-icons-iconfont": "^5.0.1", "material-design-icons-iconfont": "^6.1.0",
"native-promise-only": "^0.8.0-a", "native-promise-only": "^0.8.0-a",
"page": "^1.11.6", "page": "^1.11.6",
"query-string": "^6.13.1", "query-string": "^6.13.1",
"resize-observer-polyfill": "^1.5.1", "resize-observer-polyfill": "^1.5.1",
"screenfull": "^5.0.2", "screenfull": "^5.0.2",
"shaka-player": "^3.0.1",
"sortablejs": "^1.10.2", "sortablejs": "^1.10.2",
"swiper": "^5.4.5", "swiper": "^6.2.0",
"webcomponents.js": "^0.7.24", "webcomponents.js": "^0.7.24",
"whatwg-fetch": "^3.0.0" "whatwg-fetch": "^3.4.1"
}, },
"babel": { "babel": {
"presets": [ "presets": [
@ -92,48 +94,273 @@
"test": [ "test": [
"src/components/accessSchedule/accessSchedule.js", "src/components/accessSchedule/accessSchedule.js",
"src/components/actionSheet/actionSheet.js", "src/components/actionSheet/actionSheet.js",
"src/components/activitylog.js",
"src/components/alert.js",
"src/components/alphaPicker/alphaPicker.js",
"src/components/appFooter/appFooter.js",
"src/components/apphost.js",
"src/components/appRouter.js",
"src/components/autoFocuser.js", "src/components/autoFocuser.js",
"src/components/backdrop/backdrop.js",
"src/components/cardbuilder/cardBuilder.js", "src/components/cardbuilder/cardBuilder.js",
"src/components/cardbuilder/chaptercardbuilder.js", "src/components/cardbuilder/chaptercardbuilder.js",
"src/components/cardbuilder/peoplecardbuilder.js", "src/components/cardbuilder/peoplecardbuilder.js",
"src/components/channelMapper/channelMapper.js",
"src/components/collectionEditor/collectionEditor.js",
"src/components/confirm/confirm.js",
"src/components/dialog/dialog.js",
"src/components/dialogHelper/dialogHelper.js",
"src/components/directorybrowser/directorybrowser.js",
"src/components/displaySettings/displaySettings.js",
"src/components/favoriteitems.js",
"src/components/fetchhelper.js",
"src/components/filterdialog/filterdialog.js",
"src/components/filtermenu/filtermenu.js",
"src/components/focusManager.js",
"src/components/groupedcards.js",
"src/components/guide/guide.js",
"src/components/guide/guide-settings.js",
"src/components/homeScreenSettings/homeScreenSettings.js",
"src/components/homesections/homesections.js",
"src/components/htmlMediaHelper.js",
"src/components/imageOptionsEditor/imageOptionsEditor.js",
"src/components/images/imageLoader.js", "src/components/images/imageLoader.js",
"src/components/imageDownloader/imageDownloader.js",
"src/components/imageeditor/imageeditor.js",
"src/components/imageUploader/imageUploader.js",
"src/components/indicators/indicators.js", "src/components/indicators/indicators.js",
"src/components/itemContextMenu.js",
"src/components/itemHelper.js",
"src/components/itemidentifier/itemidentifier.js",
"src/components/itemMediaInfo/itemMediaInfo.js",
"src/components/itemsrefresher.js",
"src/components/layoutManager.js",
"src/components/lazyLoader/lazyLoaderIntersectionObserver.js", "src/components/lazyLoader/lazyLoaderIntersectionObserver.js",
"src/components/libraryoptionseditor/libraryoptionseditor.js",
"src/components/listview/listview.js",
"src/components/loading/loading.js",
"src/components/maintabsmanager.js",
"src/components/mediainfo/mediainfo.js",
"src/components/mediaLibraryCreator/mediaLibraryCreator.js",
"src/components/mediaLibraryEditor/mediaLibraryEditor.js",
"src/components/metadataEditor/metadataEditor.js",
"src/components/metadataEditor/personEditor.js",
"src/components/multiSelect/multiSelect.js",
"src/components/notifications/notifications.js",
"src/components/nowPlayingBar/nowPlayingBar.js",
"src/components/packageManager.js",
"src/components/playback/brightnessosd.js", "src/components/playback/brightnessosd.js",
"src/components/playback/mediasession.js", "src/components/playback/mediasession.js",
"src/components/playback/nowplayinghelper.js", "src/components/playback/nowplayinghelper.js",
"src/components/playback/playbackorientation.js", "src/components/playback/playbackorientation.js",
"src/components/playback/playbackmanager.js",
"src/components/playback/playerSelectionMenu.js", "src/components/playback/playerSelectionMenu.js",
"src/components/playback/playersettingsmenu.js", "src/components/playback/playersettingsmenu.js",
"src/components/playback/playmethodhelper.js", "src/components/playback/playmethodhelper.js",
"src/components/playback/playqueuemanager.js",
"src/components/playback/remotecontrolautoplay.js", "src/components/playback/remotecontrolautoplay.js",
"src/components/playback/volumeosd.js", "src/components/playback/volumeosd.js",
"src/components/playbackSettings/playbackSettings.js",
"src/components/playerstats/playerstats.js",
"src/components/playlisteditor/playlisteditor.js",
"src/components/playmenu.js", "src/components/playmenu.js",
"src/components/pluginManager.js",
"src/components/prompt/prompt.js",
"src/components/recordingcreator/recordingbutton.js",
"src/components/recordingcreator/recordingcreator.js",
"src/components/recordingcreator/seriesrecordingeditor.js",
"src/components/recordingcreator/recordinghelper.js",
"src/components/refreshdialog/refreshdialog.js",
"src/components/recordingcreator/recordingeditor.js",
"src/components/recordingcreator/recordingfields.js",
"src/components/qualityOptions.js",
"src/components/remotecontrol/remotecontrol.js",
"src/components/sanatizefilename.js", "src/components/sanatizefilename.js",
"src/components/scrollManager.js", "src/components/scrollManager.js",
"src/plugins/experimentalWarnings/plugin.js",
"src/plugins/sessionPlayer/plugin.js",
"src/plugins/htmlAudioPlayer/plugin.js",
"src/plugins/comicsPlayer/plugin.js",
"src/plugins/chromecastPlayer/plugin.js",
"src/components/slideshow/slideshow.js",
"src/components/sortmenu/sortmenu.js",
"src/plugins/htmlVideoPlayer/plugin.js",
"src/plugins/logoScreensaver/plugin.js",
"src/plugins/playAccessValidation/plugin.js",
"src/components/search/searchfields.js",
"src/components/search/searchresults.js",
"src/components/settingshelper.js",
"src/components/shortcuts.js",
"src/components/subtitleeditor/subtitleeditor.js",
"src/components/subtitlesync/subtitlesync.js",
"src/components/subtitlesettings/subtitleappearancehelper.js",
"src/components/subtitlesettings/subtitlesettings.js",
"src/components/syncPlay/groupSelectionMenu.js", "src/components/syncPlay/groupSelectionMenu.js",
"src/components/syncPlay/playbackPermissionManager.js", "src/components/syncPlay/playbackPermissionManager.js",
"src/components/syncPlay/syncPlayManager.js", "src/components/syncPlay/syncPlayManager.js",
"src/components/syncPlay/timeSyncManager.js", "src/components/syncPlay/timeSyncManager.js",
"src/components/themeMediaPlayer.js",
"src/components/tabbedview/tabbedview.js",
"src/components/viewManager/viewManager.js",
"src/components/tvproviders/schedulesdirect.js",
"src/components/tvproviders/xmltv.js",
"src/components/toast/toast.js",
"src/components/tunerPicker.js",
"src/components/upnextdialog/upnextdialog.js",
"src/components/userdatabuttons/userdatabuttons.js",
"src/components/viewContainer.js",
"src/components/viewSettings/viewSettings.js",
"src/components/castSenderApi.js",
"src/controllers/session/addServer/index.js",
"src/controllers/session/forgotPassword/index.js",
"src/controllers/session/redeemPassword/index.js",
"src/controllers/session/login/index.js",
"src/controllers/session/selectServer/index.js",
"src/controllers/dashboard/apikeys.js",
"src/controllers/dashboard/dashboard.js",
"src/controllers/dashboard/devices/device.js",
"src/controllers/dashboard/devices/devices.js",
"src/controllers/dashboard/dlna/profile.js",
"src/controllers/dashboard/dlna/profiles.js",
"src/controllers/dashboard/dlna/settings.js",
"src/controllers/dashboard/encodingsettings.js",
"src/controllers/dashboard/general.js",
"src/controllers/dashboard/librarydisplay.js",
"src/controllers/dashboard/logs.js", "src/controllers/dashboard/logs.js",
"src/controllers/dashboard/plugins/repositories.js", "src/controllers/music/musicalbums.js",
"src/controllers/music/musicartists.js",
"src/controllers/music/musicgenres.js",
"src/controllers/music/musicplaylists.js",
"src/controllers/music/musicrecommended.js",
"src/controllers/music/songs.js",
"src/controllers/dashboard/library.js",
"src/controllers/dashboard/metadataImages.js",
"src/controllers/dashboard/metadatanfo.js",
"src/controllers/dashboard/networking.js",
"src/controllers/dashboard/notifications/notification/index.js",
"src/controllers/dashboard/notifications/notifications/index.js",
"src/controllers/dashboard/playback.js",
"src/controllers/dashboard/plugins/add/index.js",
"src/controllers/dashboard/plugins/installed/index.js",
"src/controllers/dashboard/plugins/available/index.js",
"src/controllers/dashboard/plugins/repositories/index.js",
"src/controllers/dashboard/scheduledtasks/scheduledtask.js",
"src/controllers/dashboard/scheduledtasks/scheduledtasks.js",
"src/controllers/dashboard/serveractivity.js",
"src/controllers/dashboard/streaming.js",
"src/controllers/dashboard/users/useredit.js",
"src/controllers/dashboard/users/userlibraryaccess.js",
"src/controllers/dashboard/users/usernew.js",
"src/controllers/dashboard/users/userparentalcontrol.js",
"src/controllers/dashboard/users/userpasswordpage.js",
"src/controllers/dashboard/users/userprofilespage.js",
"src/controllers/home.js",
"src/controllers/list.js",
"src/controllers/edititemmetadata.js",
"src/controllers/favorites.js",
"src/controllers/hometab.js",
"src/controllers/movies/moviecollections.js",
"src/controllers/movies/moviegenres.js",
"src/controllers/movies/movies.js",
"src/controllers/movies/moviesrecommended.js",
"src/controllers/movies/movietrailers.js",
"src/controllers/playback/nowplaying.js",
"src/controllers/playback/videoosd.js",
"src/controllers/itemDetails/index.js",
"src/controllers/playback/queue/index.js",
"src/controllers/playback/video/index.js",
"src/controllers/searchpage.js",
"src/controllers/livetv/livetvguide.js",
"src/controllers/livetvtuner.js",
"src/controllers/livetv/livetvsuggested.js",
"src/controllers/livetvstatus.js",
"src/controllers/livetvguideprovider.js",
"src/controllers/livetvsettings.js",
"src/controllers/livetv/livetvrecordings.js",
"src/controllers/livetv/livetvschedule.js",
"src/controllers/livetv/livetvseriestimers.js",
"src/controllers/livetv/livetvchannels.js",
"src/controllers/shows/episodes.js",
"src/controllers/shows/tvgenres.js",
"src/controllers/shows/tvlatest.js",
"src/controllers/shows/tvrecommended.js",
"src/controllers/shows/tvshows.js",
"src/controllers/shows/tvstudios.js",
"src/controllers/shows/tvupcoming.js",
"src/controllers/user/display/index.js",
"src/controllers/user/home/index.js",
"src/controllers/user/menu/index.js",
"src/controllers/user/playback/index.js",
"src/controllers/user/profile/index.js",
"src/controllers/user/subtitles/index.js",
"src/controllers/wizard/finish/index.js",
"src/controllers/wizard/remote/index.js",
"src/controllers/wizard/settings/index.js",
"src/controllers/wizard/start/index.js",
"src/controllers/wizard/user/index.js",
"src/elements/emby-button/emby-button.js",
"src/elements/emby-button/paper-icon-button-light.js",
"src/elements/emby-checkbox/emby-checkbox.js",
"src/elements/emby-collapse/emby-collapse.js",
"src/elements/emby-input/emby-input.js",
"src/elements/emby-itemrefreshindicator/emby-itemrefreshindicator.js",
"src/elements/emby-itemscontainer/emby-itemscontainer.js",
"src/elements/emby-playstatebutton/emby-playstatebutton.js",
"src/elements/emby-programcell/emby-programcell.js",
"src/elements/emby-progressbar/emby-progressbar.js",
"src/elements/emby-progressring/emby-progressring.js",
"src/elements/emby-radio/emby-radio.js",
"src/elements/emby-ratingbutton/emby-ratingbutton.js",
"src/elements/emby-scrollbuttons/emby-scrollbuttons.js",
"src/elements/emby-scroller/emby-scroller.js",
"src/elements/emby-select/emby-select.js",
"src/elements/emby-slider/emby-slider.js",
"src/elements/emby-tabs/emby-tabs.js",
"src/elements/emby-textarea/emby-textarea.js",
"src/elements/emby-toggle/emby-toggle.js",
"src/libraries/screensavermanager.js",
"src/libraries/navdrawer/navdrawer.js",
"src/libraries/scroller.js",
"src/plugins/backdropScreensaver/plugin.js",
"src/plugins/bookPlayer/plugin.js", "src/plugins/bookPlayer/plugin.js",
"src/plugins/bookPlayer/tableOfContents.js", "src/plugins/bookPlayer/tableOfContents.js",
"src/plugins/chromecastPlayer/chromecastHelper.js",
"src/plugins/photoPlayer/plugin.js", "src/plugins/photoPlayer/plugin.js",
"src/plugins/youtubePlayer/plugin.js",
"src/scripts/alphanumericshortcuts.js",
"src/scripts/autoBackdrops.js",
"src/scripts/browser.js",
"src/scripts/clientUtils.js",
"src/scripts/datetime.js",
"src/scripts/deleteHelper.js", "src/scripts/deleteHelper.js",
"src/scripts/dfnshelper.js", "src/scripts/dfnshelper.js",
"src/scripts/dom.js", "src/scripts/dom.js",
"src/scripts/editorsidebar.js",
"src/scripts/fileDownloader.js", "src/scripts/fileDownloader.js",
"src/scripts/filesystem.js", "src/scripts/filesystem.js",
"src/scripts/globalize.js",
"src/scripts/imagehelper.js", "src/scripts/imagehelper.js",
"src/scripts/itembynamedetailpage.js",
"src/scripts/inputManager.js", "src/scripts/inputManager.js",
"src/plugins/backdropScreensaver/plugin.js", "src/scripts/autoThemes.js",
"src/components/filterdialog/filterdialog.js", "src/scripts/themeManager.js",
"src/components/fetchhelper.js",
"src/scripts/keyboardNavigation.js", "src/scripts/keyboardNavigation.js",
"src/scripts/libraryMenu.js",
"src/scripts/libraryBrowser.js",
"src/scripts/livetvcomponents.js",
"src/scripts/mouseManager.js",
"src/scripts/multiDownload.js",
"src/scripts/playlists.js",
"src/scripts/scrollHelper.js",
"src/scripts/serverNotifications.js",
"src/scripts/routes.js",
"src/scripts/settings/appSettings.js", "src/scripts/settings/appSettings.js",
"src/scripts/settings/userSettings.js", "src/scripts/settings/userSettings.js",
"src/scripts/settings/webSettings.js" "src/scripts/settings/webSettings.js",
"src/scripts/shell.js",
"src/scripts/taskbutton.js",
"src/scripts/themeLoader.js",
"src/scripts/touchHelper.js"
], ],
"plugins": [ "plugins": [
"@babel/plugin-transform-modules-amd", "@babel/plugin-transform-modules-amd",
@ -148,7 +375,7 @@
"last 2 Chrome versions", "last 2 Chrome versions",
"last 2 ChromeAndroid versions", "last 2 ChromeAndroid versions",
"last 2 Safari versions", "last 2 Safari versions",
"last 2 iOS versions", "iOS > 10",
"last 2 Edge versions", "last 2 Edge versions",
"Chrome 27", "Chrome 27",
"Chrome 38", "Chrome 38",
@ -156,9 +383,11 @@
"Chrome 53", "Chrome 53",
"Chrome 56", "Chrome 56",
"Chrome 63", "Chrome 63",
"Edge 18",
"Firefox ESR" "Firefox ESR"
], ],
"scripts": { "scripts": {
"start": "yarn serve",
"serve": "gulp serve --development", "serve": "gulp serve --development",
"prepare": "gulp --production", "prepare": "gulp --production",
"build:development": "gulp --development", "build:development": "gulp --development",

33
scripts/duplicates.py Normal file
View file

@ -0,0 +1,33 @@
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

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

View file

@ -16,7 +16,7 @@ langlst.append('en-us.json')
dep = [] dep = []
def grep(key): 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) p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output = p.stdout.readlines() output = p.stdout.readlines()
if output: if output:

View file

@ -235,6 +235,15 @@ div[data-role=controlgroup] a.ui-btn-active {
width: 50%; width: 50%;
} }
.localUsers .cardText-secondary {
white-space: pre-wrap;
height: 3em;
}
.customCssContainer textarea {
resize: none;
}
@media all and (min-width: 70em) { @media all and (min-width: 70em) {
.dashboardSections { .dashboardSections {
-webkit-flex-wrap: wrap; -webkit-flex-wrap: wrap;

View file

@ -30,6 +30,10 @@
align-items: flex-start; align-items: flex-start;
} }
.align-items-flex-end {
align-items: flex-end;
}
.justify-content-center { .justify-content-center {
justify-content: center; justify-content: center;
} }
@ -38,6 +42,10 @@
justify-content: flex-end; justify-content: flex-end;
} }
.justify-content-space-between {
justify-content: space-between;
}
.flex-wrap-wrap { .flex-wrap-wrap {
flex-wrap: wrap; flex-wrap: wrap;
} }

View file

@ -1,7 +1,5 @@
html { html {
font-family: "Noto Sans", sans-serif; font-family: "Noto Sans", sans-serif;
font-size: 93%;
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%; text-size-adjust: 100%;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility; text-rendering: optimizeLegibility;
@ -29,7 +27,9 @@ h3 {
} }
.layout-tv { .layout-tv {
font-size: 130%; /* 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 { .layout-mobile {

View file

@ -1,8 +1,3 @@
html { html {
font-size: 82% !important; font-size: 82% !important;
} }
.formDialogFooter {
position: static !important;
margin: 0 -1em !important;
}

View file

@ -28,6 +28,10 @@
padding-top: 0 !important; padding-top: 0 !important;
} }
.layout-tv .itemDetailPage {
padding-top: 4.2em !important;
}
.standalonePage { .standalonePage {
padding-top: 4.5em !important; padding-top: 4.5em !important;
} }
@ -163,6 +167,12 @@
transition: background ease-in-out 0.5s; 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 { .hiddenViewMenuBar .skinHeader {
display: none; display: none;
} }
@ -175,6 +185,10 @@
width: 100%; width: 100%;
} }
.layout-tv .sectionTabs {
width: 55%;
}
.selectedMediaFolder { .selectedMediaFolder {
background-color: #f2f2f2 !important; background-color: #f2f2f2 !important;
} }
@ -232,12 +246,6 @@
text-align: center; text-align: center;
} }
.layout-desktop .searchTabButton,
.layout-mobile .searchTabButton,
.layout-tv .headerSearchButton {
display: none !important;
}
.mainDrawer-scrollContainer { .mainDrawer-scrollContainer {
padding-bottom: 10vh; padding-bottom: 10vh;
} }
@ -269,7 +277,7 @@
} }
} }
@media all and (max-width: 84em) { @media all and (max-width: 100em) {
.withSectionTabs .headerTop { .withSectionTabs .headerTop {
padding-bottom: 0.55em; padding-bottom: 0.55em;
} }
@ -277,9 +285,13 @@
.sectionTabs { .sectionTabs {
font-size: 83.5%; font-size: 83.5%;
} }
.layout-tv .sectionTabs {
width: 100%;
}
} }
@media all and (min-width: 84em) { @media all and (min-width: 100em) {
.headerTop { .headerTop {
padding: 0.8em 0.8em; padding: 0.8em 0.8em;
} }
@ -445,8 +457,7 @@
height: 26.5vh; height: 26.5vh;
} }
.layout-desktop .itemBackdrop::after, .layout-desktop .itemBackdrop::after {
.layout-tv .itemBackdrop::after {
content: ""; content: "";
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -454,8 +465,8 @@
display: block; display: block;
} }
.layout-desktop .noBackdrop .itemBackdrop, .layout-tv .itemBackdrop,
.layout-tv .noBackdrop .itemBackdrop { .layout-desktop .noBackdrop .itemBackdrop {
display: none; display: none;
} }
@ -622,6 +633,10 @@
z-index: 2; z-index: 2;
} }
.layout-tv .detailPagePrimaryContainer {
display: block;
}
.layout-mobile .detailPagePrimaryContainer { .layout-mobile .detailPagePrimaryContainer {
display: block; display: block;
position: relative; position: relative;
@ -635,10 +650,14 @@
padding-left: 32.45vw; padding-left: 32.45vw;
} }
.layout-desktop .detailRibbon, .layout-desktop .detailRibbon {
.layout-tv .detailRibbon {
margin-top: -7.2em; margin-top: -7.2em;
height: 7.18em; height: 7.2em;
}
.layout-tv .detailRibbon {
margin-top: 0;
height: inherit;
} }
.layout-desktop .noBackdrop .detailRibbon, .layout-desktop .noBackdrop .detailRibbon,
@ -746,8 +765,7 @@ div.itemDetailGalleryLink.defaultCardBackground {
position: relative; position: relative;
} }
.layout-desktop .itemBackdrop, .layout-desktop .itemBackdrop {
.layout-tv .itemBackdrop {
height: 40vh; height: 40vh;
} }
@ -773,13 +791,8 @@ div.itemDetailGalleryLink.defaultCardBackground {
} }
.emby-button.detailFloatingButton { .emby-button.detailFloatingButton {
position: absolute; font-size: 1.4em;
background-color: rgba(0, 0, 0, 0.5); margin-right: 0.5em !important;
z-index: 3;
top: 100%;
left: 90%;
margin: -2.2em 0 0 -2.2em;
padding: 0.4em;
color: rgba(255, 255, 255, 0.76); color: rgba(255, 255, 255, 0.76);
} }
@ -842,7 +855,7 @@ div.itemDetailGalleryLink.defaultCardBackground {
-webkit-align-items: center; -webkit-align-items: center;
align-items: center; align-items: center;
margin: 0 !important; margin: 0 !important;
padding: 0.5em 0.7em !important; padding: 0.7em 0.7em !important;
} }
@media all and (min-width: 29em) { @media all and (min-width: 29em) {
@ -910,25 +923,7 @@ div.itemDetailGalleryLink.defaultCardBackground {
} }
} }
@media all and (min-width: 62.5em) { @media all and (min-width: 100em) {
.headerTop {
padding-left: 0.8em;
padding-right: 0.8em;
}
.headerTabs {
align-self: center;
width: auto;
align-items: center;
justify-content: center;
margin-top: -4.2em;
position: relative;
}
.detailFloatingButton {
display: none !important;
}
.personBackdrop { .personBackdrop {
display: none !important; display: none !important;
} }
@ -937,6 +932,11 @@ div.itemDetailGalleryLink.defaultCardBackground {
font-size: 108%; font-size: 108%;
margin: 1.25em 0; margin: 1.25em 0;
} }
.layout-tv .mainDetailButtons {
font-size: 108%;
margin: 1em 0 1.25em;
}
} }
@media all and (max-width: 50em) { @media all and (max-width: 50em) {
@ -1152,13 +1152,13 @@ div:not(.sectionTitleContainer-cards) > .sectionTitle-cards {
} }
.layout-tv .padded-top-focusscale { .layout-tv .padded-top-focusscale {
padding-top: 1em; padding-top: 1.5em;
margin-top: -1em; margin-top: -1.5em;
} }
.layout-tv .padded-bottom-focusscale { .layout-tv .padded-bottom-focusscale {
padding-bottom: 1em; padding-bottom: 1.5em;
margin-bottom: -1em; margin-bottom: -1.5em;
} }
@media all and (min-height: 31.25em) { @media all and (min-height: 31.25em) {

View file

@ -12,6 +12,7 @@
.hiddenScrollX, .hiddenScrollX,
.layout-tv .scrollX { .layout-tv .scrollX {
-ms-overflow-style: none; -ms-overflow-style: none;
scrollbar-width: none;
} }
.hiddenScrollX-forced { .hiddenScrollX-forced {
@ -40,6 +41,7 @@
.hiddenScrollY, .hiddenScrollY,
.layout-tv .smoothScrollY { .layout-tv .smoothScrollY {
-ms-overflow-style: none; -ms-overflow-style: none;
scrollbar-width: none;
/* Can't do this because it not only hides the scrollbar, but also prevents scrolling */ /* Can't do this because it not only hides the scrollbar, but also prevents scrolling */

View file

@ -5,6 +5,12 @@ html {
height: 100%; height: 100%;
} }
.layout-mobile,
.layout-tv {
-webkit-touch-callout: none;
user-select: none;
}
.clipForScreenReader { .clipForScreenReader {
clip: rect(1px, 1px, 1px, 1px); clip: rect(1px, 1px, 1px, 1px);
clip-path: inset(50%); clip-path: inset(50%);
@ -18,7 +24,7 @@ html {
.material-icons { .material-icons {
/* Fix font ligatures on older WebOS versions */ /* Fix font ligatures on older WebOS versions */
-webkit-font-feature-settings: "liga"; font-feature-settings: "liga";
} }
.backgroundContainer { .backgroundContainer {
@ -34,16 +40,6 @@ html {
line-height: 1.35; line-height: 1.35;
} }
.layout-mobile,
.layout-tv {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
body { body {
overflow-x: hidden; overflow-x: hidden;
background-color: transparent !important; background-color: transparent !important;
@ -133,3 +129,17 @@ div[data-role=page] {
.hide-scroll { .hide-scroll {
overflow-y: hidden; 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

@ -7,7 +7,6 @@
} }
.osdPoster img, .osdPoster img,
.pageContainer,
.videoOsdBottom { .videoOsdBottom {
bottom: 0; bottom: 0;
left: 0; left: 0;
@ -248,14 +247,7 @@
animation: spin 4s linear infinite; animation: spin 4s linear infinite;
} }
.pageContainer {
top: 0;
position: fixed;
}
@media all and (max-width: 30em) { @media all and (max-width: 30em) {
.btnFastForward,
.btnRewind,
.osdMediaInfo, .osdMediaInfo,
.osdPoster { .osdPoster {
display: none !important; display: none !important;

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24"><title>Microsoft Edge icon</title><path d="M21.86 17.86q.14 0 .25.12.1.13.1.25t-.11.33l-.32.46-.43.53-.44.5q-.21.25-.38.42l-.22.23q-.58.53-1.34 1.04-.76.51-1.6.91-.86.4-1.74.64t-1.67.24q-.9 0-1.69-.28-.8-.28-1.48-.78-.68-.5-1.22-1.17-.53-.66-.92-1.44-.38-.77-.58-1.6-.2-.83-.2-1.67 0-1 .32-1.96.33-.97.87-1.8.14.95.55 1.77.41.82 1.02 1.5.6.68 1.38 1.21.78.54 1.64.9.86.36 1.77.56.92.2 1.8.2 1.12 0 2.18-.24 1.06-.23 2.06-.72l.2-.1.2-.05zm-15.5-1.27q0 1.1.27 2.15.27 1.06.78 2.03.51.96 1.24 1.77.74.82 1.66 1.4-1.47-.2-2.8-.74-1.33-.55-2.48-1.37-1.15-.83-2.08-1.9-.92-1.07-1.58-2.33T.36 14.94Q0 13.54 0 12.06q0-.81.32-1.49.31-.68.83-1.23.53-.55 1.2-.96.66-.4 1.35-.66.74-.27 1.5-.39.78-.12 1.55-.12.7 0 1.42.1.72.12 1.4.35.68.23 1.32.57.63.35 1.16.83-.35 0-.7.07-.33.07-.65.23v-.02q-.63.28-1.2.74-.57.46-1.05 1.04-.48.58-.87 1.26-.38.67-.65 1.39-.27.71-.42 1.44-.15.72-.15 1.38zM11.96.06q1.7 0 3.33.39 1.63.38 3.07 1.15 1.43.77 2.62 1.93 1.18 1.16 1.98 2.7.49.94.76 1.96.28 1 .28 2.08 0 .89-.23 1.7-.24.8-.69 1.48-.45.68-1.1 1.22-.64.53-1.45.88-.54.24-1.11.36-.58.13-1.16.13-.42 0-.97-.03-.54-.03-1.1-.12-.55-.1-1.05-.28-.5-.19-.84-.5-.12-.09-.23-.24-.1-.16-.1-.33 0-.15.16-.35.16-.2.35-.5.2-.28.36-.68.16-.4.16-.95 0-1.06-.4-1.96-.4-.91-1.06-1.64-.66-.74-1.52-1.28-.86-.55-1.79-.89-.84-.3-1.72-.44-.87-.14-1.76-.14-1.55 0-3.06.45T.94 7.55q.71-1.74 1.81-3.13 1.1-1.38 2.52-2.35Q6.68 1.1 8.37.58q1.7-.52 3.58-.52Z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -2,171 +2,159 @@
* require.js module definitions bundled by webpack * require.js module definitions bundled by webpack
*/ */
// Use define from require.js not webpack's define // Use define from require.js not webpack's define
var _define = window.define; const _define = window.define;
// document-register-element
var docRegister = require('document-register-element');
_define('document-register-element', function() {
return docRegister;
});
// fetch // fetch
var fetch = require('whatwg-fetch'); const fetch = require('whatwg-fetch');
_define('fetch', function() { _define('fetch', function() {
return fetch; return fetch;
}); });
// Blurhash // Blurhash
var blurhash = require('blurhash'); const blurhash = require('blurhash');
_define('blurhash', function() { _define('blurhash', function() {
return blurhash; return blurhash;
}); });
// query-string // query-string
var query = require('query-string'); const query = require('query-string');
_define('queryString', function() { _define('queryString', function() {
return query; return query;
}); });
// flvjs // flvjs
var flvjs = require('flv.js/dist/flv').default; const flvjs = require('flv.js/dist/flv').default;
_define('flvjs', function() { _define('flvjs', function() {
return flvjs; return flvjs;
}); });
// jstree // jstree
var jstree = require('jstree'); const jstree = require('jstree');
require('jstree/dist/themes/default/style.css'); require('jstree/dist/themes/default/style.css');
_define('jstree', function() { _define('jstree', function() {
return jstree; return jstree;
}); });
// jquery // jquery
var jquery = require('jquery'); const jquery = require('jquery');
_define('jQuery', function() { _define('jQuery', function() {
return jquery; return jquery;
}); });
// hlsjs // hlsjs
var hlsjs = require('hls.js'); const hlsjs = require('hls.js');
_define('hlsjs', function() { _define('hlsjs', function() {
return hlsjs; return hlsjs;
}); });
// howler // howler
var howler = require('howler'); const howler = require('howler');
_define('howler', function() { _define('howler', function() {
return howler; return howler;
}); });
// resize-observer-polyfill // resize-observer-polyfill
var resize = require('resize-observer-polyfill').default; const resize = require('resize-observer-polyfill').default;
_define('resize-observer-polyfill', function() { _define('resize-observer-polyfill', function() {
return resize; return resize;
}); });
// shaka
var shaka = require('shaka-player');
_define('shaka', function() {
return shaka;
});
// swiper // swiper
var swiper = require('swiper/js/swiper'); const swiper = require('swiper/swiper-bundle');
require('swiper/css/swiper.min.css'); require('swiper/swiper-bundle.css');
_define('swiper', function() { _define('swiper', function() {
return swiper; return swiper;
}); });
// sortable // sortable
var sortable = require('sortablejs').default; const sortable = require('sortablejs').default;
_define('sortable', function() { _define('sortable', function() {
return sortable; return sortable;
}); });
// webcomponents // webcomponents
var webcomponents = require('webcomponents.js/webcomponents-lite'); const webcomponents = require('webcomponents.js/webcomponents-lite');
_define('webcomponents', function() { _define('webcomponents', function() {
return webcomponents; return webcomponents;
}); });
// libass-wasm // libass-wasm
var libassWasm = require('libass-wasm'); const libassWasm = require('libass-wasm');
_define('JavascriptSubtitlesOctopus', function() { _define('JavascriptSubtitlesOctopus', function() {
return libassWasm; return libassWasm;
}); });
// material-icons // material-icons
var materialIcons = require('material-design-icons-iconfont/dist/material-design-icons.css'); const materialIcons = require('material-design-icons-iconfont/dist/material-design-icons.css');
_define('material-icons', function() { _define('material-icons', function() {
return materialIcons; return materialIcons;
}); });
// noto font // noto font
var noto = require('jellyfin-noto'); const noto = require('jellyfin-noto');
_define('jellyfin-noto', function () { _define('jellyfin-noto', function () {
return noto; return noto;
}); });
var epubjs = require('epubjs'); const epubjs = require('epubjs');
_define('epubjs', function () { _define('epubjs', function () {
return epubjs; return epubjs;
}); });
// page.js // page.js
var page = require('page'); const page = require('page');
_define('page', function() { _define('page', function() {
return page; return page;
}); });
// core-js // core-js
var polyfill = require('@babel/polyfill/dist/polyfill'); const polyfill = require('@babel/polyfill/dist/polyfill');
_define('polyfill', function () { _define('polyfill', function () {
return polyfill; return polyfill;
}); });
// domtokenlist-shim // domtokenlist-shim
var classlist = require('classlist.js'); const classlist = require('classlist.js');
_define('classlist-polyfill', function () { _define('classlist-polyfill', function () {
return classlist; return classlist;
}); });
// Date-FNS // Date-FNS
var dateFns = require('date-fns'); const dateFns = require('date-fns');
_define('date-fns', function () { _define('date-fns', function () {
return dateFns; return dateFns;
}); });
var dateFnsLocale = require('date-fns/locale'); const dateFnsLocale = require('date-fns/locale');
_define('date-fns/locale', function () { _define('date-fns/locale', function () {
return dateFnsLocale; return dateFnsLocale;
}); });
var fast_text_encoding = require('fast-text-encoding'); const fast_text_encoding = require('fast-text-encoding');
_define('fast-text-encoding', function () { _define('fast-text-encoding', function () {
return fast_text_encoding; return fast_text_encoding;
}); });
// intersection-observer // intersection-observer
var intersection_observer = require('intersection-observer'); const intersection_observer = require('intersection-observer');
_define('intersection-observer', function () { _define('intersection-observer', function () {
return intersection_observer; return intersection_observer;
}); });
// screenfull // screenfull
var screenfull = require('screenfull'); const screenfull = require('screenfull');
_define('screenfull', function () { _define('screenfull', function () {
return screenfull; return screenfull;
}); });
// headroom.js // headroom.js
var headroom = require('headroom.js/dist/headroom'); const headroom = require('headroom.js/dist/headroom');
_define('headroom', function () { _define('headroom', function () {
return headroom; return headroom;
}); });
// apiclient // apiclient
var apiclient = require('jellyfin-apiclient'); const apiclient = require('jellyfin-apiclient');
_define('apiclient', function () { _define('apiclient', function () {
return apiclient.ApiClient; return apiclient.ApiClient;
@ -187,3 +175,9 @@ _define('connectionManagerFactory', function () {
_define('appStorage', function () { _define('appStorage', function () {
return apiclient.AppStorage; return apiclient.AppStorage;
}); });
// libarchive.js
var libarchive = require('libarchive.js');
_define('libarchive', function () {
return libarchive;
});

View file

@ -49,7 +49,7 @@ import 'formDialogStyle';
}; };
if (parseFloat(updatedSchedule.StartHour) >= parseFloat(updatedSchedule.EndHour)) { if (parseFloat(updatedSchedule.StartHour) >= parseFloat(updatedSchedule.EndHour)) {
return void alert(globalize.translate('ErrorMessageStartHourGreaterThanEnd')); return void alert(globalize.translate('ErrorStartHourGreaterThanEnd'));
} }
context.submitted = true; context.submitted = true;
@ -59,15 +59,14 @@ import 'formDialogStyle';
export function show(options) { export function show(options) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// TODO: remove require import('text!./accessSchedule.template.html').then(({default: template}) => {
require(['text!./components/accessSchedule/accessSchedule.template.html'], template => {
const dlg = dialogHelper.createDialog({ const dlg = dialogHelper.createDialog({
removeOnClose: true, removeOnClose: true,
size: 'small' size: 'small'
}); });
dlg.classList.add('formDialog'); dlg.classList.add('formDialog');
let html = ''; let html = '';
html += globalize.translateDocument(template); html += globalize.translateHtml(template);
dlg.innerHTML = html; dlg.innerHTML = html;
populateHours(dlg); populateHours(dlg);
loadSchedule(dlg, options.schedule); loadSchedule(dlg, options.schedule);

View file

@ -1,5 +1,5 @@
<div class="formDialogHeader"> <div class="formDialogHeader">
<button is="paper-icon-button-light" class="btnCancel autoSize" title="${LabelPrevious}" tabindex="-1"> <button is="paper-icon-button-light" class="btnCancel autoSize" title="${Previous}" tabindex="-1">
<span class="material-icons arrow_back" aria-hidden="true"></span> <span class="material-icons arrow_back" aria-hidden="true"></span>
</button> </button>
<h3 class="formDialogHeaderTitle"> <h3 class="formDialogHeaderTitle">
@ -12,13 +12,13 @@
<div class="selectContainer"> <div class="selectContainer">
<select is="emby-select" id="selectDay" label="${LabelAccessDay}"> <select is="emby-select" id="selectDay" label="${LabelAccessDay}">
<option value="Sunday">${OptionSunday}</option> <option value="Sunday">${Sunday}</option>
<option value="Monday">${OptionMonday}</option> <option value="Monday">${Monday}</option>
<option value="Tuesday">${OptionTuesday}</option> <option value="Tuesday">${Tuesday}</option>
<option value="Wednesday">${OptionWednesday}</option> <option value="Wednesday">${Wednesday}</option>
<option value="Thursday">${OptionThursday}</option> <option value="Thursday">${Thursday}</option>
<option value="Friday">${OptionFriday}</option> <option value="Friday">${Friday}</option>
<option value="Saturday">${OptionSaturday}</option> <option value="Saturday">${Saturday}</option>
<option value="Everyday">${OptionEveryday}</option> <option value="Everyday">${OptionEveryday}</option>
<option value="Weekday">${OptionWeekdays}</option> <option value="Weekday">${OptionWeekdays}</option>
<option value="Weekend">${OptionWeekends}</option> <option value="Weekend">${OptionWeekends}</option>
@ -33,7 +33,7 @@
<div class="formDialogFooter"> <div class="formDialogFooter">
<button is="emby-button" type="submit" class="raised button-submit block formDialogFooterItem"> <button is="emby-button" type="submit" class="raised button-submit block formDialogFooterItem">
<span>${ButtonAdd}</span> <span>${Add}</span>
</button> </button>
</div> </div>
</form> </form>

View file

@ -9,15 +9,14 @@ import 'scrollStyles';
import 'listViewStyle'; import 'listViewStyle';
function getOffsets(elems) { function getOffsets(elems) {
const results = [];
let results = [];
if (!document) { if (!document) {
return results; return results;
} }
for (const elem of elems) { for (const elem of elems) {
let box = elem.getBoundingClientRect(); const box = elem.getBoundingClientRect();
results.push({ results.push({
top: box.top, top: box.top,
@ -31,12 +30,11 @@ function getOffsets(elems) {
} }
function getPosition(options, dlg) { function getPosition(options, dlg) {
const windowSize = dom.getWindowSize(); const windowSize = dom.getWindowSize();
const windowHeight = windowSize.innerHeight; const windowHeight = windowSize.innerHeight;
const windowWidth = windowSize.innerWidth; const windowWidth = windowSize.innerWidth;
let pos = getOffsets([options.positionTo])[0]; const pos = getOffsets([options.positionTo])[0];
if (options.positionY !== 'top') { if (options.positionY !== 'top') {
pos.top += (pos.height || 0) / 2; pos.top += (pos.height || 0) / 2;
@ -73,19 +71,18 @@ function getPosition(options, dlg) {
} }
function centerFocus(elem, horiz, on) { function centerFocus(elem, horiz, on) {
require(['scrollHelper'], function (scrollHelper) { import('scrollHelper').then(({default: scrollHelper}) => {
const fn = on ? 'on' : 'off'; const fn = on ? 'on' : 'off';
scrollHelper.centerFocus[fn](elem, horiz); scrollHelper.centerFocus[fn](elem, horiz);
}); });
} }
export function show(options) { export function show(options) {
// items // items
// positionTo // positionTo
// showCancel // showCancel
// title // title
let dialogOptions = { const dialogOptions = {
removeOnClose: true, removeOnClose: true,
enableHistory: options.enableHistory, enableHistory: options.enableHistory,
scrollY: false scrollY: false
@ -98,7 +95,6 @@ export function show(options) {
isFullscreen = true; isFullscreen = true;
dialogOptions.autoFocus = true; dialogOptions.autoFocus = true;
} else { } else {
dialogOptions.modal = false; dialogOptions.modal = false;
dialogOptions.entryAnimation = options.entryAnimation; dialogOptions.entryAnimation = options.entryAnimation;
dialogOptions.exitAnimation = options.exitAnimation; dialogOptions.exitAnimation = options.exitAnimation;
@ -107,7 +103,7 @@ export function show(options) {
dialogOptions.autoFocus = false; dialogOptions.autoFocus = false;
} }
let dlg = dialogHelper.createDialog(dialogOptions); const dlg = dialogHelper.createDialog(dialogOptions);
if (isFullscreen) { if (isFullscreen) {
dlg.classList.add('actionsheet-fullscreen'); dlg.classList.add('actionsheet-fullscreen');
@ -133,10 +129,9 @@ export function show(options) {
} }
let renderIcon = false; let renderIcon = false;
let icons = []; const icons = [];
let itemIcon; let itemIcon;
for (const item of options.items) { for (const item of options.items) {
itemIcon = item.icon || (item.selected ? 'check' : null); itemIcon = item.icon || (item.selected ? 'check' : null);
if (itemIcon) { if (itemIcon) {
@ -161,7 +156,6 @@ export function show(options) {
} }
if (options.title) { if (options.title) {
html += '<h1 class="actionSheetTitle">' + options.title + '</h1>'; html += '<h1 class="actionSheetTitle">' + options.title + '</h1>';
} }
if (options.text) { if (options.text) {
@ -197,7 +191,6 @@ export function show(options) {
const item = options.items[i]; const item = options.items[i];
if (item.divider) { if (item.divider) {
html += '<div class="actionsheetDivider"></div>'; html += '<div class="actionsheetDivider"></div>';
continue; continue;
} }
@ -248,15 +241,13 @@ export function show(options) {
centerFocus(dlg.querySelector('.actionSheetScroller'), false, true); centerFocus(dlg.querySelector('.actionSheetScroller'), false, true);
} }
let btnCloseActionSheet = dlg.querySelector('.btnCloseActionSheet'); const btnCloseActionSheet = dlg.querySelector('.btnCloseActionSheet');
if (btnCloseActionSheet) { if (btnCloseActionSheet) {
btnCloseActionSheet.addEventListener('click', function () { btnCloseActionSheet.addEventListener('click', function () {
dialogHelper.close(dlg); dialogHelper.close(dlg);
}); });
} }
// Seeing an issue in some non-chrome browsers where this is requiring a double click
//var eventName = browser.firefox ? 'mousedown' : 'click';
let selectedId; let selectedId;
let timeout; let timeout;
@ -267,26 +258,20 @@ export function show(options) {
} }
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
let isResolved; let isResolved;
dlg.addEventListener('click', function (e) { dlg.addEventListener('click', function (e) {
const actionSheetMenuItem = dom.parentWithClass(e.target, 'actionSheetMenuItem'); const actionSheetMenuItem = dom.parentWithClass(e.target, 'actionSheetMenuItem');
if (actionSheetMenuItem) { if (actionSheetMenuItem) {
selectedId = actionSheetMenuItem.getAttribute('data-id'); selectedId = actionSheetMenuItem.getAttribute('data-id');
if (options.resolveOnClick) { if (options.resolveOnClick) {
if (options.resolveOnClick.indexOf) { if (options.resolveOnClick.indexOf) {
if (options.resolveOnClick.indexOf(selectedId) !== -1) { if (options.resolveOnClick.indexOf(selectedId) !== -1) {
resolve(selectedId); resolve(selectedId);
isResolved = true; isResolved = true;
} }
} else { } else {
resolve(selectedId); resolve(selectedId);
isResolved = true; isResolved = true;
@ -295,11 +280,9 @@ export function show(options) {
dialogHelper.close(dlg); dialogHelper.close(dlg);
} }
}); });
dlg.addEventListener('close', function () { dlg.addEventListener('close', function () {
if (layoutManager.tv) { if (layoutManager.tv) {
centerFocus(dlg.querySelector('.actionSheetScroller'), false, false); centerFocus(dlg.querySelector('.actionSheetScroller'), false, false);
} }

View file

@ -1,13 +1,21 @@
define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings', 'serverNotifications', 'connectionManager', 'emby-button', 'listViewStyle'], function (events, globalize, dom, datefns, dfnshelper, userSettings, serverNotifications, connectionManager) { import events from 'events';
'use strict'; import globalize from 'globalize';
import dom from 'dom';
import * as datefns from 'date-fns';
import dfnshelper from 'dfnshelper';
import serverNotifications from 'serverNotifications';
import 'emby-button';
import 'listViewStyle';
/* eslint-disable indent */
function getEntryHtml(entry, apiClient) { function getEntryHtml(entry, apiClient) {
var html = ''; let html = '';
html += '<div class="listItem listItem-border">'; html += '<div class="listItem listItem-border">';
var color = '#00a4dc'; let color = '#00a4dc';
var icon = 'notifications'; let icon = 'notifications';
if ('Error' == entry.Severity || 'Fatal' == entry.Severity || 'Warn' == entry.Severity) { if (entry.Severity == 'Error' || entry.Severity == 'Fatal' || entry.Severity == 'Warn') {
color = '#cc0000'; color = '#cc0000';
icon = 'notification_important'; icon = 'notification_important';
} }
@ -51,14 +59,15 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings',
} }
function reloadData(instance, elem, apiClient, startIndex, limit) { function reloadData(instance, elem, apiClient, startIndex, limit) {
if (null == startIndex) { if (startIndex == null) {
startIndex = parseInt(elem.getAttribute('data-activitystartindex') || '0'); startIndex = parseInt(elem.getAttribute('data-activitystartindex') || '0');
} }
limit = limit || parseInt(elem.getAttribute('data-activitylimit') || '7'); limit = limit || parseInt(elem.getAttribute('data-activitylimit') || '7');
var minDate = new Date(); const minDate = new Date();
var hasUserId = 'false' !== elem.getAttribute('data-useractivity'); const hasUserId = elem.getAttribute('data-useractivity') !== 'false';
// TODO: Use date-fns
if (hasUserId) { if (hasUserId) {
minDate.setTime(minDate.getTime() - 24 * 60 * 60 * 1000); // one day back minDate.setTime(minDate.getTime() - 24 * 60 * 60 * 1000); // one day back
} else { } else {
@ -74,7 +83,7 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings',
elem.setAttribute('data-activitystartindex', startIndex); elem.setAttribute('data-activitystartindex', startIndex);
elem.setAttribute('data-activitylimit', limit); elem.setAttribute('data-activitylimit', limit);
if (!startIndex) { if (!startIndex) {
var activityContainer = dom.parentWithClass(elem, 'activityContainer'); const activityContainer = dom.parentWithClass(elem, 'activityContainer');
if (activityContainer) { if (activityContainer) {
if (result.Items.length) { if (result.Items.length) {
@ -91,7 +100,7 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings',
} }
function onActivityLogUpdate(e, apiClient, data) { function onActivityLogUpdate(e, apiClient, data) {
var options = this.options; const options = this.options;
if (options && options.serverId === apiClient.serverId()) { if (options && options.serverId === apiClient.serverId()) {
reloadData(this, options.element, apiClient); reloadData(this, options.element, apiClient);
@ -99,14 +108,14 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings',
} }
function onListClick(e) { function onListClick(e) {
var btnEntryInfo = dom.parentWithClass(e.target, 'btnEntryInfo'); const btnEntryInfo = dom.parentWithClass(e.target, 'btnEntryInfo');
if (btnEntryInfo) { if (btnEntryInfo) {
var id = btnEntryInfo.getAttribute('data-id'); const id = btnEntryInfo.getAttribute('data-id');
var items = this.items; const items = this.items;
if (items) { if (items) {
var item = items.filter(function (i) { const item = items.filter(function (i) {
return i.Id.toString() === id; return i.Id.toString() === id;
})[0]; })[0];
@ -118,35 +127,35 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings',
} }
function showItemOverview(item) { function showItemOverview(item) {
require(['alert'], function (alert) { import('alert').then(({default: alert}) => {
alert({ alert({
text: item.Overview text: item.Overview
}); });
}); });
} }
function ActivityLog(options) { class ActivityLog {
constructor(options) {
this.options = options; this.options = options;
var element = options.element; const element = options.element;
element.classList.add('activityLogListWidget'); element.classList.add('activityLogListWidget');
element.addEventListener('click', onListClick.bind(this)); element.addEventListener('click', onListClick.bind(this));
var apiClient = connectionManager.getApiClient(options.serverId); const apiClient = window.connectionManager.getApiClient(options.serverId);
reloadData(this, element, apiClient); reloadData(this, element, apiClient);
var onUpdate = onActivityLogUpdate.bind(this); const onUpdate = onActivityLogUpdate.bind(this);
this.updateFn = onUpdate; this.updateFn = onUpdate;
events.on(serverNotifications, 'ActivityLogEntry', onUpdate); events.on(serverNotifications, 'ActivityLogEntry', onUpdate);
apiClient.sendMessage('ActivityLogEntryStart', '0,1500'); apiClient.sendMessage('ActivityLogEntryStart', '0,1500');
} }
destroy() {
ActivityLog.prototype.destroy = function () { const options = this.options;
var options = this.options;
if (options) { if (options) {
options.element.classList.remove('activityLogListWidget'); options.element.classList.remove('activityLogListWidget');
connectionManager.getApiClient(options.serverId).sendMessage('ActivityLogEntryStop', '0,1500'); window.connectionManager.getApiClient(options.serverId).sendMessage('ActivityLogEntryStop', '0,1500');
} }
var onUpdate = this.updateFn; const onUpdate = this.updateFn;
if (onUpdate) { if (onUpdate) {
events.off(serverNotifications, 'ActivityLogEntry', onUpdate); events.off(serverNotifications, 'ActivityLogEntry', onUpdate);
@ -154,7 +163,9 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings',
this.items = null; this.items = null;
this.options = null; this.options = null;
}; }
}
return ActivityLog; export default ActivityLog;
});
/* eslint-enable indent */

View file

@ -1,14 +1,16 @@
define(['browser', 'dialog', 'globalize'], function (browser, dialog, globalize) { import browser from 'browser';
'use strict'; import dialog from 'dialog';
import globalize from 'globalize';
/* eslint-disable indent */
function replaceAll(originalString, strReplace, strWith) { function replaceAll(originalString, strReplace, strWith) {
var reg = new RegExp(strReplace, 'ig'); const reg = new RegExp(strReplace, 'ig');
return originalString.replace(reg, strWith); return originalString.replace(reg, strWith);
} }
return function (text, title) { export default function (text, title) {
let options;
var options;
if (typeof text === 'string') { if (typeof text === 'string') {
options = { options = {
title: title, title: title,
@ -21,7 +23,7 @@ define(['browser', 'dialog', 'globalize'], function (browser, dialog, globalize)
if (browser.tv && window.alert) { if (browser.tv && window.alert) {
alert(replaceAll(options.text || '', '<br/>', '\n')); alert(replaceAll(options.text || '', '<br/>', '\n'));
} else { } else {
var items = []; const items = [];
items.push({ items.push({
name: globalize.translate('ButtonGotIt'), name: globalize.translate('ButtonGotIt'),
@ -31,7 +33,7 @@ define(['browser', 'dialog', 'globalize'], function (browser, dialog, globalize)
options.buttons = items; options.buttons = items;
return dialog(options).then(function (result) { return dialog.show(options).then(function (result) {
if (result === 'ok') { if (result === 'ok') {
return Promise.resolve(); return Promise.resolve();
} }
@ -41,5 +43,6 @@ define(['browser', 'dialog', 'globalize'], function (browser, dialog, globalize)
} }
return Promise.resolve(); return Promise.resolve();
}; }
});
/* eslint-enable indent */

View file

@ -1,11 +1,22 @@
define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-button-light', 'material-icons'], function (focusManager, layoutManager, dom) { /* eslint-disable indent */
'use strict';
var selectedButtonClass = 'alphaPickerButton-selected'; /**
* Module alphaPicker.
* @module components/alphaPicker/alphaPicker
*/
import focusManager from 'focusManager';
import layoutManager from 'layoutManager';
import dom from 'dom';
import 'css!./style.css';
import 'paper-icon-button-light';
import 'material-icons';
const selectedButtonClass = 'alphaPickerButton-selected';
function focus() { function focus() {
var scope = this; const scope = this;
var selected = scope.querySelector('.' + selectedButtonClass); const selected = scope.querySelector(`.${selectedButtonClass}`);
if (selected) { if (selected) {
focusManager.focus(selected); focusManager.focus(selected);
@ -15,8 +26,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
} }
function getAlphaPickerButtonClassName(vertical) { function getAlphaPickerButtonClassName(vertical) {
let alphaPickerButtonClassName = 'alphaPickerButton';
var alphaPickerButtonClassName = 'alphaPickerButton';
if (layoutManager.tv) { if (layoutManager.tv) {
alphaPickerButtonClassName += ' alphaPickerButton-tv'; alphaPickerButtonClassName += ' alphaPickerButton-tv';
@ -30,44 +40,42 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
} }
function getLetterButton(l, vertical) { function getLetterButton(l, vertical) {
return '<button data-value="' + l + '" class="' + getAlphaPickerButtonClassName(vertical) + '">' + l + '</button>'; return `<button data-value="${l}" class="${getAlphaPickerButtonClassName(vertical)}">${l}</button>`;
} }
function mapLetters(letters, vertical) { function mapLetters(letters, vertical) {
return letters.map(l => {
return letters.map(function (l) {
return getLetterButton(l, vertical); return getLetterButton(l, vertical);
}); });
} }
function render(element, options) { function render(element, options) {
element.classList.add('alphaPicker'); element.classList.add('alphaPicker');
if (layoutManager.tv) { if (layoutManager.tv) {
element.classList.add('alphaPicker-tv'); element.classList.add('alphaPicker-tv');
} }
var vertical = element.classList.contains('alphaPicker-vertical'); const vertical = element.classList.contains('alphaPicker-vertical');
if (!vertical) { if (!vertical) {
element.classList.add('focuscontainer-x'); element.classList.add('focuscontainer-x');
} }
var html = ''; let html = '';
var letters; let letters;
var alphaPickerButtonClassName = getAlphaPickerButtonClassName(vertical); const alphaPickerButtonClassName = getAlphaPickerButtonClassName(vertical);
var rowClassName = 'alphaPickerRow'; let rowClassName = 'alphaPickerRow';
if (vertical) { if (vertical) {
rowClassName += ' alphaPickerRow-vertical'; rowClassName += ' alphaPickerRow-vertical';
} }
html += '<div class="' + rowClassName + '">'; html += `<div class="${rowClassName}">`;
if (options.mode === 'keyboard') { if (options.mode === 'keyboard') {
html += '<button data-value=" " is="paper-icon-button-light" class="' + alphaPickerButtonClassName + '"><span class="material-icons alphaPickerButtonIcon space_bar"></span></button>'; html += `<button data-value=" " is="paper-icon-button-light" class="${alphaPickerButtonClassName}"><span class="material-icons alphaPickerButtonIcon space_bar"></span></button>`;
} else { } else {
letters = ['#']; letters = ['#'];
html += mapLetters(letters, vertical).join(''); html += mapLetters(letters, vertical).join('');
@ -77,11 +85,11 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
html += mapLetters(letters, vertical).join(''); html += mapLetters(letters, vertical).join('');
if (options.mode === 'keyboard') { if (options.mode === 'keyboard') {
html += '<button data-value="backspace" is="paper-icon-button-light" class="' + alphaPickerButtonClassName + '"><span class="material-icons alphaPickerButtonIcon backspace"></span></button>'; html += `<button data-value="backspace" is="paper-icon-button-light" class="${alphaPickerButtonClassName}"><span class="material-icons alphaPickerButtonIcon backspace"></span></button>`;
html += '</div>'; html += '</div>';
letters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; letters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
html += '<div class="' + rowClassName + '">'; html += `<div class="${rowClassName}">`;
html += '<br/>'; html += '<br/>';
html += mapLetters(letters, vertical).join(''); html += mapLetters(letters, vertical).join('');
html += '</div>'; html += '</div>';
@ -95,74 +103,71 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
element.focus = focus; element.focus = focus;
} }
function AlphaPicker(options) { export class AlphaPicker {
constructor(options) {
const self = this;
var self = this;
this.options = options; this.options = options;
var element = options.element; const element = options.element;
var itemsContainer = options.itemsContainer; const itemsContainer = options.itemsContainer;
var itemClass = options.itemClass; const itemClass = options.itemClass;
var itemFocusValue; let itemFocusValue;
var itemFocusTimeout; let itemFocusTimeout;
function onItemFocusTimeout() { function onItemFocusTimeout() {
itemFocusTimeout = null; itemFocusTimeout = null;
self.value(itemFocusValue); self.value(itemFocusValue);
} }
var alphaFocusedElement; let alphaFocusedElement;
var alphaFocusTimeout; let alphaFocusTimeout;
function onAlphaFocusTimeout() { function onAlphaFocusTimeout() {
alphaFocusTimeout = null; alphaFocusTimeout = null;
if (document.activeElement === alphaFocusedElement) { if (document.activeElement === alphaFocusedElement) {
var value = alphaFocusedElement.getAttribute('data-value'); const value = alphaFocusedElement.getAttribute('data-value');
self.value(value, true); self.value(value, true);
} }
} }
function onAlphaPickerInKeyboardModeClick(e) { function onAlphaPickerInKeyboardModeClick(e) {
const alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton');
var alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton');
if (alphaPickerButton) { if (alphaPickerButton) {
var value = alphaPickerButton.getAttribute('data-value'); const value = alphaPickerButton.getAttribute('data-value');
element.dispatchEvent(new CustomEvent('alphavalueclicked', { element.dispatchEvent(new CustomEvent('alphavalueclicked', {
cancelable: false, cancelable: false,
detail: { detail: {
value: value value
} }
})); }));
} }
} }
function onAlphaPickerClick(e) { function onAlphaPickerClick(e) {
const alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton');
var alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton');
if (alphaPickerButton) { if (alphaPickerButton) {
var value = alphaPickerButton.getAttribute('data-value'); const value = alphaPickerButton.getAttribute('data-value');
if ((this._currentValue || '').toUpperCase() === value.toUpperCase()) { if ((this._currentValue || '').toUpperCase() === value.toUpperCase()) {
self.value(null, true); this.value(null, true);
} else { } else {
self.value(value, true); this.value(value, true);
} }
} }
} }
function onAlphaPickerFocusIn(e) { function onAlphaPickerFocusIn(e) {
if (alphaFocusTimeout) { if (alphaFocusTimeout) {
clearTimeout(alphaFocusTimeout); clearTimeout(alphaFocusTimeout);
alphaFocusTimeout = null; alphaFocusTimeout = null;
} }
var alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton'); const alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton');
if (alphaPickerButton) { if (alphaPickerButton) {
alphaFocusedElement = alphaPickerButton; alphaFocusedElement = alphaPickerButton;
@ -171,13 +176,11 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
} }
function onItemsFocusIn(e) { function onItemsFocusIn(e) {
const item = dom.parentWithClass(e.target, itemClass);
var item = dom.parentWithClass(e.target, itemClass);
if (item) { if (item) {
var prefix = item.getAttribute('data-prefix'); const prefix = item.getAttribute('data-prefix');
if (prefix && prefix.length) { if (prefix && prefix.length) {
itemFocusValue = prefix[0]; itemFocusValue = prefix[0];
if (itemFocusTimeout) { if (itemFocusTimeout) {
clearTimeout(itemFocusTimeout); clearTimeout(itemFocusTimeout);
@ -187,10 +190,8 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
} }
} }
self.enabled = function (enabled) { this.enabled = function (enabled) {
if (enabled) { if (enabled) {
if (itemsContainer) { if (itemsContainer) {
itemsContainer.addEventListener('focus', onItemsFocusIn, true); itemsContainer.addEventListener('focus', onItemsFocusIn, true);
} }
@ -204,9 +205,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
} else { } else {
element.addEventListener('click', onAlphaPickerClick.bind(this)); element.addEventListener('click', onAlphaPickerClick.bind(this));
} }
} else { } else {
if (itemsContainer) { if (itemsContainer) {
itemsContainer.removeEventListener('focus', onItemsFocusIn, true); itemsContainer.removeEventListener('focus', onItemsFocusIn, true);
} }
@ -223,25 +222,23 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
this.visible(true); this.visible(true);
} }
AlphaPicker.prototype.value = function (value, applyValue) { value(value, applyValue) {
const element = this.options.element;
var element = this.options.element; let btn;
var btn; let selected;
var selected;
if (value !== undefined) { if (value !== undefined) {
if (value != null) { if (value != null) {
value = value.toUpperCase(); value = value.toUpperCase();
this._currentValue = value; this._currentValue = value;
if (this.options.mode !== 'keyboard') { if (this.options.mode !== 'keyboard') {
selected = element.querySelector('.' + selectedButtonClass); selected = element.querySelector(`.${selectedButtonClass}`);
try { try {
btn = element.querySelector('.alphaPickerButton[data-value=\'' + value + '\']'); btn = element.querySelector(`.alphaPickerButton[data-value='${value}']`);
} catch (err) { } catch (err) {
console.error('error in querySelector: ' + err); console.error('error in querySelector:', err);
} }
if (btn && btn !== selected) { if (btn && btn !== selected) {
@ -254,7 +251,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
} else { } else {
this._currentValue = value; this._currentValue = value;
selected = element.querySelector('.' + selectedButtonClass); selected = element.querySelector(`.${selectedButtonClass}`);
if (selected) { if (selected) {
selected.classList.remove(selectedButtonClass); selected.classList.remove(selectedButtonClass);
} }
@ -265,57 +262,52 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
element.dispatchEvent(new CustomEvent('alphavaluechanged', { element.dispatchEvent(new CustomEvent('alphavaluechanged', {
cancelable: false, cancelable: false,
detail: { detail: {
value: value value
} }
})); }));
} }
return this._currentValue; return this._currentValue;
}; }
AlphaPicker.prototype.on = function (name, fn) { on(name, fn) {
var element = this.options.element; const element = this.options.element;
element.addEventListener(name, fn); element.addEventListener(name, fn);
}; }
AlphaPicker.prototype.off = function (name, fn) { off(name, fn) {
var element = this.options.element; const element = this.options.element;
element.removeEventListener(name, fn); element.removeEventListener(name, fn);
}; }
AlphaPicker.prototype.visible = function (visible) { visible(visible) {
const element = this.options.element;
var element = this.options.element;
element.style.visibility = visible ? 'visible' : 'hidden'; element.style.visibility = visible ? 'visible' : 'hidden';
}; }
AlphaPicker.prototype.values = function () {
var element = this.options.element;
var elems = element.querySelectorAll('.alphaPickerButton');
var values = [];
for (var i = 0, length = elems.length; i < length; i++) {
values() {
const element = this.options.element;
const elems = element.querySelectorAll('.alphaPickerButton');
const values = [];
for (let i = 0, length = elems.length; i < length; i++) {
values.push(elems[i].getAttribute('data-value')); values.push(elems[i].getAttribute('data-value'));
} }
return values; return values;
}; }
AlphaPicker.prototype.focus = function () { focus() {
const element = this.options.element;
var element = this.options.element;
focusManager.autoFocus(element, true); focusManager.autoFocus(element, true);
}; }
AlphaPicker.prototype.destroy = function () { destroy() {
const element = this.options.element;
var element = this.options.element;
this.enabled(false); this.enabled(false);
element.classList.remove('focuscontainer-x'); element.classList.remove('focuscontainer-x');
this.options = null; this.options = null;
}; }
}
return AlphaPicker; /* eslint-enable indent */
}); export default AlphaPicker;

View file

@ -1,17 +1,17 @@
define(['browser', 'css!./appFooter'], function (browser) { import 'css!./appFooter';
'use strict';
function render(options) { function render(options) {
var elem = document.createElement('div'); const elem = document.createElement('div');
elem.classList.add('appfooter'); elem.classList.add('appfooter');
document.body.appendChild(elem); document.body.appendChild(elem);
return elem; return elem;
} }
function appFooter(options) { class appFooter {
var self = this; constructor(options) {
const self = this;
self.element = render(options); self.element = render(options);
self.add = function (elem) { self.add = function (elem) {
@ -26,12 +26,11 @@ define(['browser', 'css!./appFooter'], function (browser) {
} }
}; };
} }
destroy() {
appFooter.prototype.destroy = function () {
var self = this; var self = this;
self.element = null; self.element = null;
}; }
}
return appFooter; export default appFooter;
});

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,12 @@
define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'globalize'], function (appSettings, browser, events, htmlMediaHelper, webSettings, globalize) { import appSettings from 'appSettings';
'use strict'; import browser from 'browser';
import events from 'events';
import * as htmlMediaHelper from 'htmlMediaHelper';
import * as webSettings from 'webSettings';
import globalize from 'globalize';
function getBaseProfileOptions(item) { function getBaseProfileOptions(item) {
var disableHlsVideoAudioCodecs = []; const disableHlsVideoAudioCodecs = [];
if (item && htmlMediaHelper.enableHlsJsPlayer(item.RunTimeTicks, item.MediaType)) { if (item && htmlMediaHelper.enableHlsJsPlayer(item.RunTimeTicks, item.MediaType)) {
if (browser.edge) { if (browser.edge) {
@ -18,68 +22,50 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
enableMkvProgressive: false, enableMkvProgressive: false,
disableHlsVideoAudioCodecs: disableHlsVideoAudioCodecs disableHlsVideoAudioCodecs: disableHlsVideoAudioCodecs
}; };
} }
function getDeviceProfileForWindowsUwp(item) {
return new Promise(function (resolve, reject) {
require(['browserdeviceprofile', 'environments/windows-uwp/mediacaps'], function (profileBuilder, uwpMediaCaps) {
var profileOptions = getBaseProfileOptions(item);
profileOptions.supportsDts = uwpMediaCaps.supportsDTS();
profileOptions.supportsTrueHd = uwpMediaCaps.supportsDolby();
profileOptions.audioChannels = uwpMediaCaps.getAudioChannels();
resolve(profileBuilder(profileOptions));
});
});
}
function getDeviceProfile(item, options) {
options = options || {};
if (self.Windows) {
return getDeviceProfileForWindowsUwp(item);
}
function getDeviceProfile(item, options = {}) {
return new Promise(function (resolve) { return new Promise(function (resolve) {
require(['browserdeviceprofile'], function (profileBuilder) { import('browserdeviceprofile').then(({default: profileBuilder}) => {
var profile; let profile;
if (window.NativeShell) { if (window.NativeShell) {
profile = window.NativeShell.AppHost.getDeviceProfile(profileBuilder); profile = window.NativeShell.AppHost.getDeviceProfile(profileBuilder);
} else { } else {
var builderOpts = getBaseProfileOptions(item); const builderOpts = getBaseProfileOptions(item);
builderOpts.enableSsaRender = (item && !options.isRetry && 'allcomplexformats' !== appSettings.get('subtitleburnin')); builderOpts.enableSsaRender = (item && !options.isRetry && appSettings.get('subtitleburnin') !== 'allcomplexformats');
profile = profileBuilder(builderOpts); profile = profileBuilder(builderOpts);
} }
resolve(profile); resolve(profile);
}); });
}); });
} }
function escapeRegExp(str) { function escapeRegExp(str) {
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1'); return str.replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1');
} }
function replaceAll(originalString, strReplace, strWith) { function replaceAll(originalString, strReplace, strWith) {
var strReplace2 = escapeRegExp(strReplace); const strReplace2 = escapeRegExp(strReplace);
var reg = new RegExp(strReplace2, 'ig'); const reg = new RegExp(strReplace2, 'ig');
return originalString.replace(reg, strWith); return originalString.replace(reg, strWith);
} }
function generateDeviceId() { function generateDeviceId() {
var keys = []; const keys = [];
if (keys.push(navigator.userAgent), keys.push(new Date().getTime()), self.btoa) { if (keys.push(navigator.userAgent), keys.push(new Date().getTime()), window.btoa) {
var result = replaceAll(btoa(keys.join('|')), '=', '1'); const result = replaceAll(btoa(keys.join('|')), '=', '1');
return Promise.resolve(result); return Promise.resolve(result);
} }
return Promise.resolve(new Date().getTime()); return Promise.resolve(new Date().getTime());
} }
function getDeviceId() { function getDeviceId() {
var key = '_deviceId2'; const key = '_deviceId2';
var deviceId = appSettings.get(key); const deviceId = appSettings.get(key);
if (deviceId) { if (deviceId) {
return Promise.resolve(deviceId); return Promise.resolve(deviceId);
@ -89,9 +75,9 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
appSettings.set(key, deviceId); appSettings.set(key, deviceId);
return deviceId; return deviceId;
}); });
} }
function getDeviceName() { function getDeviceName() {
var deviceName; var deviceName;
if (browser.tizen) { if (browser.tizen) {
deviceName = 'Samsung Smart TV'; deviceName = 'Samsung Smart TV';
@ -105,6 +91,8 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
deviceName = 'Sony PS4'; deviceName = 'Sony PS4';
} else if (browser.chrome) { } else if (browser.chrome) {
deviceName = 'Chrome'; deviceName = 'Chrome';
} else if (browser.edgeChromium) {
deviceName = 'Edge Chromium';
} else if (browser.edge) { } else if (browser.edge) {
deviceName = 'Edge'; deviceName = 'Edge';
} else if (browser.firefox) { } else if (browser.firefox) {
@ -126,47 +114,30 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
} }
return deviceName; return deviceName;
} }
function supportsVoiceInput() { function supportsVoiceInput() {
if (!browser.tv) { if (!browser.tv) {
return window.SpeechRecognition || window.webkitSpeechRecognition || window.mozSpeechRecognition || window.oSpeechRecognition || window.msSpeechRecognition; return window.SpeechRecognition || window.webkitSpeechRecognition || window.mozSpeechRecognition || window.oSpeechRecognition || window.msSpeechRecognition;
} }
return false; return false;
} }
function supportsFullscreen() { function supportsFullscreen() {
if (browser.tv) { if (browser.tv) {
return false; return false;
} }
var element = document.documentElement; const element = document.documentElement;
return (element.requestFullscreen || element.mozRequestFullScreen || element.webkitRequestFullscreen || element.msRequestFullscreen) || document.createElement('video').webkitEnterFullscreen; return (element.requestFullscreen || element.mozRequestFullScreen || element.webkitRequestFullscreen || element.msRequestFullscreen) || document.createElement('video').webkitEnterFullscreen;
} }
function getSyncProfile() { function getDefaultLayout() {
return new Promise(function (resolve) {
require(['browserdeviceprofile', 'appSettings'], function (profileBuilder, appSettings) {
var profile;
if (window.NativeShell) {
profile = window.NativeShell.AppHost.getSyncProfile(profileBuilder, appSettings);
} else {
profile = profileBuilder();
profile.MaxStaticMusicBitrate = appSettings.maxStaticMusicBitrate();
}
resolve(profile);
});
});
}
function getDefaultLayout() {
return 'desktop'; return 'desktop';
} }
function supportsHtmlMediaAutoplay() { function supportsHtmlMediaAutoplay() {
if (browser.edgeUwp || browser.tizen || browser.web0s || browser.orsay || browser.operaTv || browser.ps4 || browser.xboxOne) { if (browser.edgeUwp || browser.tizen || browser.web0s || browser.orsay || browser.operaTv || browser.ps4 || browser.xboxOne) {
return true; return true;
} }
@ -176,18 +147,18 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
} }
return true; return true;
} }
function supportsCue() { function supportsCue() {
try { try {
var video = document.createElement('video'); const video = document.createElement('video');
var style = document.createElement('style'); const style = document.createElement('style');
style.textContent = 'video::cue {background: inherit}'; style.textContent = 'video::cue {background: inherit}';
document.body.appendChild(style); document.body.appendChild(style);
document.body.appendChild(video); document.body.appendChild(video);
var cue = window.getComputedStyle(video, '::cue').background; const cue = window.getComputedStyle(video, '::cue').background;
document.body.removeChild(style); document.body.removeChild(style);
document.body.removeChild(video); document.body.removeChild(video);
@ -196,25 +167,25 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
console.error('error detecting cue support: ' + err); console.error('error detecting cue support: ' + err);
return false; return false;
} }
} }
function onAppVisible() { function onAppVisible() {
if (isHidden) { if (isHidden) {
isHidden = false; isHidden = false;
console.debug('triggering app resume event'); console.debug('triggering app resume event');
events.trigger(appHost, 'resume'); events.trigger(appHost, 'resume');
} }
} }
function onAppHidden() { function onAppHidden() {
if (!isHidden) { if (!isHidden) {
isHidden = true; isHidden = true;
console.debug('app is hidden'); console.debug('app is hidden');
} }
} }
var supportedFeatures = function () { const supportedFeatures = function () {
var features = []; const features = [];
if (navigator.share) { if (navigator.share) {
features.push('sharing'); features.push('sharing');
@ -257,12 +228,6 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
features.push('fullscreenchange'); features.push('fullscreenchange');
} }
if (browser.chrome || browser.edge && !browser.slow) {
if (!browser.noAnimation && !browser.edgeUwp && !browser.xboxOne) {
features.push('imageanalysis');
}
}
if (browser.tv || browser.xboxOne || browser.ps4 || browser.mobile) { if (browser.tv || browser.xboxOne || browser.ps4 || browser.mobile) {
features.push('physicalvolumecontrol'); features.push('physicalvolumecontrol');
} }
@ -281,7 +246,7 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
features.push('targetblank'); features.push('targetblank');
features.push('screensaver'); features.push('screensaver');
webSettings.enableMultiServer().then(enabled => { webSettings.getMultiServer().then(enabled => {
if (enabled) features.push('multiserver'); if (enabled) features.push('multiserver');
}); });
@ -297,17 +262,17 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
features.push('fileinput'); features.push('fileinput');
} }
if (browser.chrome) { if (browser.chrome || browser.edgeChromium) {
features.push('chromecast'); features.push('chromecast');
} }
return features; return features;
}(); }();
/** /**
* Do exit according to platform * Do exit according to platform
*/ */
function doExit() { function doExit() {
try { try {
if (window.NativeShell) { if (window.NativeShell) {
window.NativeShell.AppHost.exit(); window.NativeShell.AppHost.exit();
@ -321,19 +286,19 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
} catch (err) { } catch (err) {
console.error('error closing application: ' + err); console.error('error closing application: ' + err);
} }
} }
var exitPromise; let exitPromise;
/** /**
* Ask user for exit * Ask user for exit
*/ */
function askForExit() { function askForExit() {
if (exitPromise) { if (exitPromise) {
return; return;
} }
require(['actionsheet'], function (actionsheet) { import('actionsheet').then(({default: actionsheet}) => {
exitPromise = actionsheet.show({ exitPromise = actionsheet.show({
title: globalize.translate('MessageConfirmAppExit'), title: globalize.translate('MessageConfirmAppExit'),
items: [ items: [
@ -348,18 +313,18 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
exitPromise = null; exitPromise = null;
}); });
}); });
} }
var deviceId; let deviceId;
var deviceName; let deviceName;
var appName = 'Jellyfin Web'; const appName = 'Jellyfin Web';
var appVersion = '10.6.0'; const appVersion = '10.7.0';
var appHost = { const appHost = {
getWindowState: function () { getWindowState: function () {
return document.windowState || 'Normal'; return document.windowState || 'Normal';
}, },
setWindowState: function (state) { setWindowState: function () {
alert('setWindowState is not supported and should not be called'); alert('setWindowState is not supported and should not be called');
}, },
exit: function () { exit: function () {
@ -374,10 +339,9 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
return window.NativeShell.AppHost.supports(command); return window.NativeShell.AppHost.supports(command);
} }
return -1 !== supportedFeatures.indexOf(command.toLowerCase()); return supportedFeatures.indexOf(command.toLowerCase()) !== -1;
}, },
preferVisualCards: browser.android || browser.chrome, preferVisualCards: browser.android || browser.chrome,
getSyncProfile: getSyncProfile,
getDefaultLayout: function () { getDefaultLayout: function () {
if (window.NativeShell) { if (window.NativeShell) {
return window.NativeShell.AppHost.getDefaultLayout(); return window.NativeShell.AppHost.getDefaultLayout();
@ -411,46 +375,38 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
getPushTokenInfo: function () { getPushTokenInfo: function () {
return {}; return {};
}, },
setThemeColor: function (color) {
var metaThemeColor = document.querySelector('meta[name=theme-color]');
if (metaThemeColor) {
metaThemeColor.setAttribute('content', color);
}
},
setUserScalable: function (scalable) { setUserScalable: function (scalable) {
if (!browser.tv) { if (!browser.tv) {
var att = scalable ? 'width=device-width, initial-scale=1, minimum-scale=1, user-scalable=yes' : 'width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no'; const att = scalable ? 'width=device-width, initial-scale=1, minimum-scale=1, user-scalable=yes' : 'width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no';
document.querySelector('meta[name=viewport]').setAttribute('content', att); document.querySelector('meta[name=viewport]').setAttribute('content', att);
} }
} }
}; };
var isHidden = false; let isHidden = false;
var hidden; let hidden;
var visibilityChange; let visibilityChange;
if (typeof document.hidden !== 'undefined') { /* eslint-disable-line compat/compat */ if (typeof document.hidden !== 'undefined') { /* eslint-disable-line compat/compat */
hidden = 'hidden'; hidden = 'hidden';
visibilityChange = 'visibilitychange'; visibilityChange = 'visibilitychange';
} else if (typeof document.webkitHidden !== 'undefined') { } else if (typeof document.webkitHidden !== 'undefined') {
hidden = 'webkitHidden'; hidden = 'webkitHidden';
visibilityChange = 'webkitvisibilitychange'; visibilityChange = 'webkitvisibilitychange';
} }
document.addEventListener(visibilityChange, function () { document.addEventListener(visibilityChange, function () {
/* eslint-disable-next-line compat/compat */ /* eslint-disable-next-line compat/compat */
if (document[hidden]) { if (document[hidden]) {
onAppHidden(); onAppHidden();
} else { } else {
onAppVisible(); onAppVisible();
} }
}, false); }, false);
if (self.addEventListener) { if (window.addEventListener) {
self.addEventListener('focus', onAppVisible); window.addEventListener('focus', onAppVisible);
self.addEventListener('blur', onAppHidden); window.addEventListener('blur', onAppHidden);
} }
return appHost; export default appHost;
});

View file

@ -1,5 +1,10 @@
define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings', 'css!./backdrop'], function (browser, connectionManager, playbackManager, dom, userSettings) { import browser from 'browser';
'use strict'; import playbackManager from 'playbackManager';
import dom from 'dom';
import * as userSettings from 'userSettings';
import 'css!./backdrop';
/* eslint-disable indent */
function enableAnimation(elem) { function enableAnimation(elem) {
if (browser.slow) { if (browser.slow) {
@ -22,22 +27,20 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
return true; return true;
} }
function Backdrop() { class Backdrop {
} load(url, parent, existingBackdropImage) {
const img = new Image();
const self = this;
Backdrop.prototype.load = function (url, parent, existingBackdropImage) { img.onload = () => {
var img = new Image();
var self = this;
img.onload = function () {
if (self.isDestroyed) { if (self.isDestroyed) {
return; return;
} }
var backdropImage = document.createElement('div'); const backdropImage = document.createElement('div');
backdropImage.classList.add('backdropImage'); backdropImage.classList.add('backdropImage');
backdropImage.classList.add('displayingBackdropImage'); backdropImage.classList.add('displayingBackdropImage');
backdropImage.style.backgroundImage = "url('" + url + "')"; backdropImage.style.backgroundImage = `url('${url}')`;
backdropImage.setAttribute('data-url', url); backdropImage.setAttribute('data-url', url);
backdropImage.classList.add('backdropImageFadeIn'); backdropImage.classList.add('backdropImageFadeIn');
@ -51,7 +54,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
return; return;
} }
var onAnimationComplete = function () { const onAnimationComplete = () => {
dom.removeEventListener(backdropImage, dom.whichAnimationEvent(), onAnimationComplete, { dom.removeEventListener(backdropImage, dom.whichAnimationEvent(), onAnimationComplete, {
once: true once: true
}); });
@ -71,22 +74,23 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
}; };
img.src = url; img.src = url;
}; }
Backdrop.prototype.cancelAnimation = function () { cancelAnimation() {
var elem = this.currentAnimatingElement; const elem = this.currentAnimatingElement;
if (elem) { if (elem) {
elem.classList.remove('backdropImageFadeIn'); elem.classList.remove('backdropImageFadeIn');
this.currentAnimatingElement = null; this.currentAnimatingElement = null;
} }
}; }
Backdrop.prototype.destroy = function () { destroy() {
this.isDestroyed = true; this.isDestroyed = true;
this.cancelAnimation(); this.cancelAnimation();
}; }
}
var backdropContainer; let backdropContainer;
function getBackdropContainer() { function getBackdropContainer() {
if (!backdropContainer) { if (!backdropContainer) {
backdropContainer = document.querySelector('.backdropContainer'); backdropContainer = document.querySelector('.backdropContainer');
@ -101,7 +105,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
return backdropContainer; return backdropContainer;
} }
function clearBackdrop(clearAll) { export function clearBackdrop(clearAll) {
clearRotation(); clearRotation();
if (currentLoadingBackdrop) { if (currentLoadingBackdrop) {
@ -109,7 +113,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
currentLoadingBackdrop = null; currentLoadingBackdrop = null;
} }
var elem = getBackdropContainer(); const elem = getBackdropContainer();
elem.innerHTML = ''; elem.innerHTML = '';
if (clearAll) { if (clearAll) {
@ -119,7 +123,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
internalBackdrop(false); internalBackdrop(false);
} }
var backgroundContainer; let backgroundContainer;
function getBackgroundContainer() { function getBackgroundContainer() {
if (!backgroundContainer) { if (!backgroundContainer) {
backgroundContainer = document.querySelector('.backgroundContainer'); backgroundContainer = document.querySelector('.backgroundContainer');
@ -135,31 +139,27 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
} }
} }
var hasInternalBackdrop; let hasInternalBackdrop;
function internalBackdrop(enabled) { function internalBackdrop(enabled) {
hasInternalBackdrop = enabled; hasInternalBackdrop = enabled;
setBackgroundContainerBackgroundEnabled(); setBackgroundContainerBackgroundEnabled();
} }
var hasExternalBackdrop; let hasExternalBackdrop;
function externalBackdrop(enabled) { export function externalBackdrop(enabled) {
hasExternalBackdrop = enabled; hasExternalBackdrop = enabled;
setBackgroundContainerBackgroundEnabled(); setBackgroundContainerBackgroundEnabled();
} }
function getRandom(min, max) { let currentLoadingBackdrop;
return Math.floor(Math.random() * (max - min) + min);
}
var currentLoadingBackdrop;
function setBackdropImage(url) { function setBackdropImage(url) {
if (currentLoadingBackdrop) { if (currentLoadingBackdrop) {
currentLoadingBackdrop.destroy(); currentLoadingBackdrop.destroy();
currentLoadingBackdrop = null; currentLoadingBackdrop = null;
} }
var elem = getBackdropContainer(); const elem = getBackdropContainer();
var existingBackdropImage = elem.querySelector('.displayingBackdropImage'); const existingBackdropImage = elem.querySelector('.displayingBackdropImage');
if (existingBackdropImage && existingBackdropImage.getAttribute('data-url') === url) { if (existingBackdropImage && existingBackdropImage.getAttribute('data-url') === url) {
if (existingBackdropImage.getAttribute('data-url') === url) { if (existingBackdropImage.getAttribute('data-url') === url) {
@ -168,7 +168,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
existingBackdropImage.classList.remove('displayingBackdropImage'); existingBackdropImage.classList.remove('displayingBackdropImage');
} }
var instance = new Backdrop(); const instance = new Backdrop();
instance.load(url, elem, existingBackdropImage); instance.load(url, elem, existingBackdropImage);
currentLoadingBackdrop = instance; currentLoadingBackdrop = instance;
} }
@ -176,9 +176,9 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
function getItemImageUrls(item, imageOptions) { function getItemImageUrls(item, imageOptions) {
imageOptions = imageOptions || {}; imageOptions = imageOptions || {};
var apiClient = connectionManager.getApiClient(item.ServerId); const apiClient = window.connectionManager.getApiClient(item.ServerId);
if (item.BackdropImageTags && item.BackdropImageTags.length > 0) { if (item.BackdropImageTags && item.BackdropImageTags.length > 0) {
return item.BackdropImageTags.map(function (imgTag, index) { return item.BackdropImageTags.map((imgTag, index) => {
return apiClient.getScaledImageUrl(item.BackdropItemId || item.Id, Object.assign(imageOptions, { return apiClient.getScaledImageUrl(item.BackdropItemId || item.Id, Object.assign(imageOptions, {
type: 'Backdrop', type: 'Backdrop',
tag: imgTag, tag: imgTag,
@ -189,7 +189,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
} }
if (item.ParentBackdropItemId && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) { if (item.ParentBackdropItemId && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) {
return item.ParentBackdropImageTags.map(function (imgTag, index) { return item.ParentBackdropImageTags.map((imgTag, index) => {
return apiClient.getScaledImageUrl(item.ParentBackdropItemId, Object.assign(imageOptions, { return apiClient.getScaledImageUrl(item.ParentBackdropItemId, Object.assign(imageOptions, {
type: 'Backdrop', type: 'Backdrop',
tag: imgTag, tag: imgTag,
@ -203,13 +203,13 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
} }
function getImageUrls(items, imageOptions) { function getImageUrls(items, imageOptions) {
var list = []; const list = [];
var onImg = function (img) { const onImg = img => {
list.push(img); list.push(img);
}; };
for (var i = 0, length = items.length; i < length; i++) { for (let i = 0, length = items.length; i < length; i++) {
var itemImages = getItemImageUrls(items[i], imageOptions); const itemImages = getItemImageUrls(items[i], imageOptions);
itemImages.forEach(onImg); itemImages.forEach(onImg);
} }
@ -229,7 +229,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
// If you don't care about the order of the elements inside // If you don't care about the order of the elements inside
// the array, you should sort both arrays here. // the array, you should sort both arrays here.
for (var i = 0; i < a.length; ++i) { for (let i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) { if (a[i] !== b[i]) {
return false; return false;
} }
@ -242,12 +242,12 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
return userSettings.enableBackdrops(); return userSettings.enableBackdrops();
} }
var rotationInterval; let rotationInterval;
var currentRotatingImages = []; let currentRotatingImages = [];
var currentRotationIndex = -1; let currentRotationIndex = -1;
function setBackdrops(items, imageOptions, enableImageRotation) { export function setBackdrops(items, imageOptions, enableImageRotation) {
if (enabled()) { if (enabled()) {
var images = getImageUrls(items, imageOptions); const images = getImageUrls(items, imageOptions);
if (images.length) { if (images.length) {
startRotation(images, enableImageRotation); startRotation(images, enableImageRotation);
@ -279,7 +279,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
return; return;
} }
var newIndex = currentRotationIndex + 1; let newIndex = currentRotationIndex + 1;
if (newIndex >= currentRotatingImages.length) { if (newIndex >= currentRotatingImages.length) {
newIndex = 0; newIndex = 0;
} }
@ -289,7 +289,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
} }
function clearRotation() { function clearRotation() {
var interval = rotationInterval; const interval = rotationInterval;
if (interval) { if (interval) {
clearInterval(interval); clearInterval(interval);
} }
@ -299,7 +299,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
currentRotationIndex = -1; currentRotationIndex = -1;
} }
function setBackdrop(url, imageOptions) { export function setBackdrop(url, imageOptions) {
if (url && typeof url !== 'string') { if (url && typeof url !== 'string') {
url = getImageUrls([url], imageOptions)[0]; url = getImageUrls([url], imageOptions)[0];
} }
@ -312,10 +312,11 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
} }
} }
return { /* eslint-enable indent */
export default {
setBackdrops: setBackdrops, setBackdrops: setBackdrops,
setBackdrop: setBackdrop, setBackdrop: setBackdrop,
clear: clearBackdrop, clearBackdrop: clearBackdrop,
externalBackdrop: externalBackdrop externalBackdrop: externalBackdrop
}; };
});

View file

@ -167,8 +167,9 @@ button::-moz-focus-inner {
position: relative; position: relative;
background-clip: content-box !important; background-clip: content-box !important;
color: inherit; color: inherit;
}
/* This is only needed for scalable cards */ .cardScalable .cardImageContainer {
height: 100%; height: 100%;
contain: strict; contain: strict;
} }
@ -208,6 +209,10 @@ button::-moz-focus-inner {
contain: strict; contain: strict;
} }
.defaultCardBackground {
display: flex;
}
.cardContent:not(.defaultCardBackground) { .cardContent:not(.defaultCardBackground) {
background-color: transparent; background-color: transparent;
} }
@ -238,33 +243,13 @@ button::-moz-focus-inner {
border: none; border: none;
} }
.cardImage-img {
max-height: 100%;
max-width: 100%;
/* This is simply for lazy image purposes, to ensure the image is visible sooner when scrolling */
min-height: 70%;
min-width: 70%;
margin: auto;
}
.coveredImage-img {
width: 100%;
height: 100%;
}
.coveredImage-noscale-img {
max-height: none;
max-width: none;
}
.coveredImage { .coveredImage {
background-size: cover; background-size: cover;
background-position: center center; background-position: center center;
} }
.coveredImage-noScale { .coveredImage.coveredImage-contain {
background-size: cover; background-size: contain;
} }
.cardFooter { .cardFooter {
@ -371,6 +356,8 @@ button::-moz-focus-inner {
.cardDefaultText { .cardDefaultText {
white-space: normal; white-space: normal;
text-align: center; text-align: center;
font-size: 2em;
font-weight: bold;
} }
.cardImageContainer .cardImageIcon { .cardImageContainer .cardImageIcon {

View file

@ -7,7 +7,6 @@
import datetime from 'datetime'; import datetime from 'datetime';
import imageLoader from 'imageLoader'; import imageLoader from 'imageLoader';
import connectionManager from 'connectionManager';
import itemHelper from 'itemHelper'; import itemHelper from 'itemHelper';
import focusManager from 'focusManager'; import focusManager from 'focusManager';
import indicators from 'indicators'; import indicators from 'indicators';
@ -277,7 +276,7 @@ import 'programStyles';
*/ */
function getImageWidth(shape, screenWidth, isOrientationLandscape) { function getImageWidth(shape, screenWidth, isOrientationLandscape) {
const imagesPerRow = getPostersPerRow(shape, screenWidth, isOrientationLandscape); const imagesPerRow = getPostersPerRow(shape, screenWidth, isOrientationLandscape);
return Math.round(screenWidth / imagesPerRow) * 2; return Math.round(screenWidth / imagesPerRow);
} }
/** /**
@ -291,12 +290,10 @@ import 'programStyles';
const primaryImageAspectRatio = imageLoader.getPrimaryImageAspectRatio(items); const primaryImageAspectRatio = imageLoader.getPrimaryImageAspectRatio(items);
if (['auto', 'autohome', 'autooverflow', 'autoVertical'].includes(options.shape)) { if (['auto', 'autohome', 'autooverflow', 'autoVertical'].includes(options.shape)) {
const requestedShape = options.shape; const requestedShape = options.shape;
options.shape = null; options.shape = null;
if (primaryImageAspectRatio) { if (primaryImageAspectRatio) {
if (primaryImageAspectRatio >= 3) { if (primaryImageAspectRatio >= 3) {
options.shape = 'banner'; options.shape = 'banner';
options.coverImage = true; options.coverImage = true;
@ -364,16 +361,16 @@ import 'programStyles';
let hasOpenRow; let hasOpenRow;
let hasOpenSection; let hasOpenSection;
let sectionTitleTagName = options.sectionTitleTagName || 'div'; const sectionTitleTagName = options.sectionTitleTagName || 'div';
let apiClient; let apiClient;
let lastServerId; let lastServerId;
for (const [i, item] of items.entries()) { for (const [i, item] of items.entries()) {
let serverId = item.ServerId || options.serverId; const serverId = item.ServerId || options.serverId;
if (serverId !== lastServerId) { if (serverId !== lastServerId) {
lastServerId = serverId; lastServerId = serverId;
apiClient = connectionManager.getApiClient(lastServerId); apiClient = window.connectionManager.getApiClient(lastServerId);
} }
if (options.indexBy) { if (options.indexBy) {
@ -394,7 +391,6 @@ import 'programStyles';
} }
if (newIndexValue !== currentIndexValue) { if (newIndexValue !== currentIndexValue) {
if (hasOpenRow) { if (hasOpenRow) {
html += '</div>'; html += '</div>';
hasOpenRow = false; hasOpenRow = false;
@ -402,7 +398,6 @@ import 'programStyles';
} }
if (hasOpenSection) { if (hasOpenSection) {
html += '</div>'; html += '</div>';
if (isVertical) { if (isVertical) {
@ -426,7 +421,6 @@ import 'programStyles';
} }
if (options.rows && itemsInRow === 0) { if (options.rows && itemsInRow === 0) {
if (hasOpenRow) { if (hasOpenRow) {
html += '</div>'; html += '</div>';
hasOpenRow = false; hasOpenRow = false;
@ -626,7 +620,7 @@ import 'programStyles';
}); });
} }
let blurHashes = options.imageBlurhashes || item.ImageBlurHashes || {}; const blurHashes = options.imageBlurhashes || item.ImageBlurHashes || {};
return { return {
imgUrl: imgUrl, imgUrl: imgUrl,
@ -661,7 +655,7 @@ import 'programStyles';
for (let i = 0; i < character.length; i++) { for (let i = 0; i < character.length; i++) {
sum += parseInt(character.charAt(i)); sum += parseInt(character.charAt(i));
} }
let index = String(sum).substr(-1); const index = String(sum).substr(-1);
return (index % numRandomColors) + 1; return (index % numRandomColors) + 1;
} else { } else {
@ -686,9 +680,8 @@ import 'programStyles';
let valid = 0; let valid = 0;
for (let i = 0; i < lines.length; i++) { for (let i = 0; i < lines.length; i++) {
let currentCssClass = cssClass; let currentCssClass = cssClass;
let text = lines[i]; const text = lines[i];
if (valid > 0 && isOuterFooter) { if (valid > 0 && isOuterFooter) {
currentCssClass += ' cardText-secondary'; currentCssClass += ' cardText-secondary';
@ -713,8 +706,7 @@ import 'programStyles';
} }
if (forceLines) { if (forceLines) {
const linesLength = maxLines || Math.min(lines.length, maxLines || lines.length);
let linesLength = maxLines || Math.min(lines.length, maxLines || lines.length);
while (valid < linesLength) { while (valid < linesLength) {
html += "<div class='" + cssClass + "'>&nbsp;</div>"; html += "<div class='" + cssClass + "'>&nbsp;</div>";
@ -745,7 +737,6 @@ import 'programStyles';
let airTimeText = ''; let airTimeText = '';
if (item.StartDate) { if (item.StartDate) {
try { try {
let date = datetime.parseISO8601Date(item.StartDate); let date = datetime.parseISO8601Date(item.StartDate);
@ -792,7 +783,6 @@ import 'programStyles';
const showOtherText = isOuterFooter ? !overlayText : overlayText; const showOtherText = isOuterFooter ? !overlayText : overlayText;
if (isOuterFooter && options.cardLayout && layoutManager.mobile) { if (isOuterFooter && options.cardLayout && layoutManager.mobile) {
if (options.cardFooterAside !== 'none') { if (options.cardFooterAside !== 'none') {
html += '<button is="paper-icon-button-light" class="itemAction btnCardOptions cardText-secondary" data-action="menu"><span class="material-icons more_vert"></span></button>'; html += '<button is="paper-icon-button-light" class="itemAction btnCardOptions cardText-secondary" data-action="menu"><span class="material-icons more_vert"></span></button>';
} }
@ -807,9 +797,7 @@ import 'programStyles';
if (showOtherText) { if (showOtherText) {
if ((options.showParentTitle || options.showParentTitleOrTitle) && !parentTitleUnderneath) { if ((options.showParentTitle || options.showParentTitleOrTitle) && !parentTitleUnderneath) {
if (isOuterFooter && item.Type === 'Episode' && item.SeriesName) { if (isOuterFooter && item.Type === 'Episode' && item.SeriesName) {
if (item.SeriesId) { if (item.SeriesId) {
lines.push(getTextActionButton({ lines.push(getTextActionButton({
Id: item.SeriesId, Id: item.SeriesId,
@ -822,15 +810,12 @@ import 'programStyles';
lines.push(item.SeriesName); lines.push(item.SeriesName);
} }
} else { } else {
if (isUsingLiveTvNaming(item)) { if (isUsingLiveTvNaming(item)) {
lines.push(item.Name); lines.push(item.Name);
if (!item.EpisodeTitle) { if (!item.EpisodeTitle) {
titleAdded = true; titleAdded = true;
} }
} else { } else {
const parentTitle = item.SeriesName || item.Series || item.Album || item.AlbumArtist || ''; const parentTitle = item.SeriesName || item.Series || item.Album || item.AlbumArtist || '';
@ -848,7 +833,6 @@ import 'programStyles';
} }
if (showMediaTitle) { if (showMediaTitle) {
const name = options.showTitle === 'auto' && !item.IsFolder && item.MediaType === 'Photo' ? '' : itemHelper.getDisplayName(item, { const name = options.showTitle === 'auto' && !item.IsFolder && item.MediaType === 'Photo' ? '' : itemHelper.getDisplayName(item, {
includeParentInfo: options.includeParentInfoInTitle includeParentInfo: options.includeParentInfoInTitle
}); });
@ -865,7 +849,6 @@ import 'programStyles';
if (showOtherText) { if (showOtherText) {
if (options.showParentTitle && parentTitleUnderneath) { if (options.showParentTitle && parentTitleUnderneath) {
if (isOuterFooter && item.AlbumArtists && item.AlbumArtists.length) { if (isOuterFooter && item.AlbumArtists && item.AlbumArtists.length) {
item.AlbumArtists[0].Type = 'MusicArtist'; item.AlbumArtists[0].Type = 'MusicArtist';
item.AlbumArtists[0].IsFolder = true; item.AlbumArtists[0].IsFolder = true;
@ -899,7 +882,6 @@ import 'programStyles';
} }
if (options.showPremiereDate) { if (options.showPremiereDate) {
if (item.PremiereDate) { if (item.PremiereDate) {
try { try {
lines.push(datetime.toLocaleDateString( lines.push(datetime.toLocaleDateString(
@ -908,7 +890,6 @@ import 'programStyles';
)); ));
} catch (err) { } catch (err) {
lines.push(''); lines.push('');
} }
} else { } else {
lines.push(''); lines.push('');
@ -916,14 +897,10 @@ import 'programStyles';
} }
if (options.showYear || options.showSeriesYear) { if (options.showYear || options.showSeriesYear) {
if (item.Type === 'Series') { if (item.Type === 'Series') {
if (item.Status === 'Continuing') { if (item.Status === 'Continuing') {
lines.push(globalize.translate('SeriesYearToPresent', item.ProductionYear || '')); lines.push(globalize.translate('SeriesYearToPresent', item.ProductionYear || ''));
} else { } else {
if (item.EndDate && item.ProductionYear) { if (item.EndDate && item.ProductionYear) {
const endYear = datetime.parseISO8601Date(item.EndDate).getFullYear(); const endYear = datetime.parseISO8601Date(item.EndDate).getFullYear();
lines.push(item.ProductionYear + ((endYear === item.ProductionYear) ? '' : (' - ' + endYear))); lines.push(item.ProductionYear + ((endYear === item.ProductionYear) ? '' : (' - ' + endYear)));
@ -937,9 +914,7 @@ import 'programStyles';
} }
if (options.showRuntime) { if (options.showRuntime) {
if (item.RunTimeTicks) { if (item.RunTimeTicks) {
lines.push(datetime.getDisplayRunningTime(item.RunTimeTicks)); lines.push(datetime.getDisplayRunningTime(item.RunTimeTicks));
} else { } else {
lines.push(''); lines.push('');
@ -947,14 +922,11 @@ import 'programStyles';
} }
if (options.showAirTime) { if (options.showAirTime) {
lines.push(getAirTimeText(item, options.showAirDateTime, options.showAirEndTime) || ''); lines.push(getAirTimeText(item, options.showAirDateTime, options.showAirEndTime) || '');
} }
if (options.showChannelName) { if (options.showChannelName) {
if (item.ChannelId) { if (item.ChannelId) {
lines.push(getTextActionButton({ lines.push(getTextActionButton({
Id: item.ChannelId, Id: item.ChannelId,
@ -971,7 +943,6 @@ import 'programStyles';
} }
if (options.showCurrentProgram && item.Type === 'TvChannel') { if (options.showCurrentProgram && item.Type === 'TvChannel') {
if (item.CurrentProgram) { if (item.CurrentProgram) {
lines.push(item.CurrentProgram.Name); lines.push(item.CurrentProgram.Name);
} else { } else {
@ -980,7 +951,6 @@ import 'programStyles';
} }
if (options.showCurrentProgramTime && item.Type === 'TvChannel') { if (options.showCurrentProgramTime && item.Type === 'TvChannel') {
if (item.CurrentProgram) { if (item.CurrentProgram) {
lines.push(getAirTimeText(item.CurrentProgram, false, true) || ''); lines.push(getAirTimeText(item.CurrentProgram, false, true) || '');
} else { } else {
@ -990,7 +960,6 @@ import 'programStyles';
if (options.showSeriesTimerTime) { if (options.showSeriesTimerTime) {
if (item.RecordAnyTime) { if (item.RecordAnyTime) {
lines.push(globalize.translate('Anytime')); lines.push(globalize.translate('Anytime'));
} else { } else {
lines.push(datetime.getDisplayTime(item.StartDate)); lines.push(datetime.getDisplayTime(item.StartDate));
@ -1016,6 +985,10 @@ import 'programStyles';
lines = []; lines = [];
} }
if (overlayText && showTitle) {
lines = [item.Name];
}
const addRightTextMargin = isOuterFooter && options.cardLayout && !options.centerText && options.cardFooterAside !== 'none' && layoutManager.mobile; const addRightTextMargin = isOuterFooter && options.cardLayout && !options.centerText && options.cardFooterAside !== 'none' && layoutManager.mobile;
html += getCardTextLines(lines, cssClass, !options.overlayText, isOuterFooter, options.cardLayout, addRightTextMargin, options.lines); html += getCardTextLines(lines, cssClass, !options.overlayText, isOuterFooter, options.cardLayout, addRightTextMargin, options.lines);
@ -1025,7 +998,6 @@ import 'programStyles';
} }
if (html) { if (html) {
if (!isOuterFooter || logoUrl || options.cardLayout) { if (!isOuterFooter || logoUrl || options.cardLayout) {
html = '<div class="' + footerClass + '">' + html; html = '<div class="' + footerClass + '">' + html;
@ -1067,31 +1039,25 @@ import 'programStyles';
* @returns {string} HTML markup for the item count indicator. * @returns {string} HTML markup for the item count indicator.
*/ */
function getItemCountsHtml(options, item) { function getItemCountsHtml(options, item) {
let counts = []; const counts = [];
let childText; let childText;
if (item.Type === 'Playlist') { if (item.Type === 'Playlist') {
childText = ''; childText = '';
if (item.RunTimeTicks) { if (item.RunTimeTicks) {
let minutes = item.RunTimeTicks / 600000000; let minutes = item.RunTimeTicks / 600000000;
minutes = minutes || 1; minutes = minutes || 1;
childText += globalize.translate('ValueMinutes', Math.round(minutes)); childText += globalize.translate('ValueMinutes', Math.round(minutes));
} else { } else {
childText += globalize.translate('ValueMinutes', 0); childText += globalize.translate('ValueMinutes', 0);
} }
counts.push(childText); counts.push(childText);
} else if (item.Type === 'Genre' || item.Type === 'Studio') { } else if (item.Type === 'Genre' || item.Type === 'Studio') {
if (item.MovieCount) { if (item.MovieCount) {
childText = item.MovieCount === 1 ? childText = item.MovieCount === 1 ?
globalize.translate('ValueOneMovie') : globalize.translate('ValueOneMovie') :
globalize.translate('ValueMovieCount', item.MovieCount); globalize.translate('ValueMovieCount', item.MovieCount);
@ -1100,7 +1066,6 @@ import 'programStyles';
} }
if (item.SeriesCount) { if (item.SeriesCount) {
childText = item.SeriesCount === 1 ? childText = item.SeriesCount === 1 ?
globalize.translate('ValueOneSeries') : globalize.translate('ValueOneSeries') :
globalize.translate('ValueSeriesCount', item.SeriesCount); globalize.translate('ValueSeriesCount', item.SeriesCount);
@ -1108,18 +1073,14 @@ import 'programStyles';
counts.push(childText); counts.push(childText);
} }
if (item.EpisodeCount) { if (item.EpisodeCount) {
childText = item.EpisodeCount === 1 ? childText = item.EpisodeCount === 1 ?
globalize.translate('ValueOneEpisode') : globalize.translate('ValueOneEpisode') :
globalize.translate('ValueEpisodeCount', item.EpisodeCount); globalize.translate('ValueEpisodeCount', item.EpisodeCount);
counts.push(childText); counts.push(childText);
} }
} else if (item.Type === 'MusicGenre' || options.context === 'MusicArtist') { } else if (item.Type === 'MusicGenre' || options.context === 'MusicArtist') {
if (item.AlbumCount) { if (item.AlbumCount) {
childText = item.AlbumCount === 1 ? childText = item.AlbumCount === 1 ?
globalize.translate('ValueOneAlbum') : globalize.translate('ValueOneAlbum') :
globalize.translate('ValueAlbumCount', item.AlbumCount); globalize.translate('ValueAlbumCount', item.AlbumCount);
@ -1127,7 +1088,6 @@ import 'programStyles';
counts.push(childText); counts.push(childText);
} }
if (item.SongCount) { if (item.SongCount) {
childText = item.SongCount === 1 ? childText = item.SongCount === 1 ?
globalize.translate('ValueOneSong') : globalize.translate('ValueOneSong') :
globalize.translate('ValueSongCount', item.SongCount); globalize.translate('ValueSongCount', item.SongCount);
@ -1135,16 +1095,13 @@ import 'programStyles';
counts.push(childText); counts.push(childText);
} }
if (item.MusicVideoCount) { if (item.MusicVideoCount) {
childText = item.MusicVideoCount === 1 ? childText = item.MusicVideoCount === 1 ?
globalize.translate('ValueOneMusicVideo') : globalize.translate('ValueOneMusicVideo') :
globalize.translate('ValueMusicVideoCount', item.MusicVideoCount); globalize.translate('ValueMusicVideoCount', item.MusicVideoCount);
counts.push(childText); counts.push(childText);
} }
} else if (item.Type === 'Series') { } else if (item.Type === 'Series') {
childText = item.RecursiveItemCount === 1 ? childText = item.RecursiveItemCount === 1 ?
globalize.translate('ValueOneEpisode') : globalize.translate('ValueOneEpisode') :
globalize.translate('ValueEpisodeCount', item.RecursiveItemCount); globalize.translate('ValueEpisodeCount', item.RecursiveItemCount);
@ -1160,10 +1117,11 @@ import 'programStyles';
/** /**
* Imports the refresh indicator element. * Imports the refresh indicator element.
*/ */
function requireRefreshIndicator() { function importRefreshIndicator() {
if (!refreshIndicatorLoaded) { if (!refreshIndicatorLoaded) {
refreshIndicatorLoaded = true; refreshIndicatorLoaded = true;
require(['emby-itemrefreshindicator']); /* eslint-disable-next-line @babel/no-unused-expressions */
import('emby-itemrefreshindicator');
} }
} }
@ -1197,13 +1155,11 @@ import 'programStyles';
let shape = options.shape; let shape = options.shape;
if (shape === 'mixed') { if (shape === 'mixed') {
shape = null; shape = null;
const primaryImageAspectRatio = item.PrimaryImageAspectRatio; const primaryImageAspectRatio = item.PrimaryImageAspectRatio;
if (primaryImageAspectRatio) { if (primaryImageAspectRatio) {
if (primaryImageAspectRatio >= 1.33) { if (primaryImageAspectRatio >= 1.33) {
shape = 'mixedBackdrop'; shape = 'mixedBackdrop';
} else if (primaryImageAspectRatio > 0.71) { } else if (primaryImageAspectRatio > 0.71) {
@ -1259,8 +1215,8 @@ import 'programStyles';
if (coveredImage) { if (coveredImage) {
cardImageContainerClass += ' coveredImage'; cardImageContainerClass += ' coveredImage';
if (item.MediaType === 'Photo' || item.Type === 'PhotoAlbum' || item.Type === 'Folder' || item.ProgramInfo || item.Type === 'Program' || item.Type === 'Recording') { if (item.Type === 'TvChannel') {
cardImageContainerClass += ' coveredImage-noScale'; cardImageContainerClass += ' coveredImage-contain';
} }
} }
@ -1295,7 +1251,6 @@ import 'programStyles';
} }
if (overlayText) { if (overlayText) {
logoUrl = null; logoUrl = null;
footerCssClass = progressHtml ? 'innerCardFooter fullInnerCardFooter' : 'innerCardFooter'; footerCssClass = progressHtml ? 'innerCardFooter fullInnerCardFooter' : 'innerCardFooter';
@ -1366,7 +1321,7 @@ import 'programStyles';
let cardBoxClose = ''; let cardBoxClose = '';
let cardScalableClose = ''; let cardScalableClose = '';
let cardContentClass = 'cardContent'; const cardContentClass = 'cardContent';
let blurhashAttrib = ''; let blurhashAttrib = '';
if (blurhash && blurhash.length > 0) { if (blurhash && blurhash.length > 0) {
@ -1385,7 +1340,7 @@ import 'programStyles';
cardImageContainerClose = '</button>'; cardImageContainerClose = '</button>';
} }
let cardScalableClass = 'cardScalable'; const cardScalableClass = 'cardScalable';
cardImageContainerOpen = '<div class="' + cardBoxClass + '"><div class="' + cardScalableClass + '"><div class="cardPadder cardPadder-' + shape + '"></div>' + cardImageContainerOpen; cardImageContainerOpen = '<div class="' + cardBoxClass + '"><div class="' + cardScalableClass + '"><div class="cardPadder cardPadder-' + shape + '"></div>' + cardImageContainerOpen;
cardBoxClose = '</div>'; cardBoxClose = '</div>';
@ -1404,7 +1359,6 @@ import 'programStyles';
indicatorsHtml += indicators.getTypeIndicator(item); indicatorsHtml += indicators.getTypeIndicator(item);
if (options.showGroupCount) { if (options.showGroupCount) {
indicatorsHtml += indicators.getChildCountIndicatorHtml(item, { indicatorsHtml += indicators.getChildCountIndicatorHtml(item, {
minCount: 1 minCount: 1
}); });
@ -1415,7 +1369,7 @@ import 'programStyles';
if (item.Type === 'CollectionFolder' || item.CollectionType) { if (item.Type === 'CollectionFolder' || item.CollectionType) {
const refreshClass = item.RefreshProgress ? '' : ' class="hide"'; const refreshClass = item.RefreshProgress ? '' : ' class="hide"';
indicatorsHtml += '<div is="emby-itemrefreshindicator"' + refreshClass + ' data-progress="' + (item.RefreshProgress || 0) + '" data-status="' + item.RefreshStatus + '"></div>'; indicatorsHtml += '<div is="emby-itemrefreshindicator"' + refreshClass + ' data-progress="' + (item.RefreshProgress || 0) + '" data-status="' + item.RefreshStatus + '"></div>';
requireRefreshIndicator(); importRefreshIndicator();
} }
if (indicatorsHtml) { if (indicatorsHtml) {
@ -1468,7 +1422,7 @@ import 'programStyles';
let additionalCardContent = ''; let additionalCardContent = '';
if (layoutManager.desktop) { if (layoutManager.desktop && !options.disableHoverMenu) {
additionalCardContent += getHoverMenuHtml(item, action, options); additionalCardContent += getHoverMenuHtml(item, action, options);
} }
@ -1497,23 +1451,21 @@ import 'programStyles';
const userData = item.UserData || {}; const userData = item.UserData || {};
if (itemHelper.canMarkPlayed(item) && !options.disableHoverMenu) { if (itemHelper.canMarkPlayed(item)) {
require(['emby-playstatebutton']); /* eslint-disable-next-line @babel/no-unused-expressions */
import('emby-playstatebutton');
html += '<button is="emby-playstatebutton" type="button" data-action="none" class="' + btnCssClass + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-played="' + (userData.Played) + '"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover check"></span></button>'; html += '<button is="emby-playstatebutton" type="button" data-action="none" class="' + btnCssClass + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-played="' + (userData.Played) + '"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover check"></span></button>';
} }
if (itemHelper.canRate(item) && !options.disableHoverMenu) { if (itemHelper.canRate(item)) {
const likes = userData.Likes == null ? '' : userData.Likes; const likes = userData.Likes == null ? '' : userData.Likes;
require(['emby-ratingbutton']); /* eslint-disable-next-line @babel/no-unused-expressions */
import('emby-ratingbutton');
html += '<button is="emby-ratingbutton" type="button" data-action="none" class="' + btnCssClass + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-likes="' + likes + '" data-isfavorite="' + (userData.IsFavorite) + '"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover favorite"></span></button>'; html += '<button is="emby-ratingbutton" type="button" data-action="none" class="' + btnCssClass + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-likes="' + likes + '" data-isfavorite="' + (userData.IsFavorite) + '"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover favorite"></span></button>';
} }
if (!options.disableHoverMenu) {
html += '<button is="paper-icon-button-light" class="' + btnCssClass + '" data-action="menu"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover more_vert"></span></button>'; html += '<button is="paper-icon-button-light" class="' + btnCssClass + '" data-action="menu"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover more_vert"></span></button>';
}
html += '</div>'; html += '</div>';
html += '</div>'; html += '</div>';
@ -1537,6 +1489,8 @@ import 'programStyles';
case 'MusicArtist': case 'MusicArtist':
case 'Person': case 'Person':
return '<span class="cardImageIcon material-icons person"></span>'; return '<span class="cardImageIcon material-icons person"></span>';
case 'Audio':
return '<span class="cardImageIcon material-icons audiotrack"></span>';
case 'Movie': case 'Movie':
return '<span class="cardImageIcon material-icons movie"></span>'; return '<span class="cardImageIcon material-icons movie"></span>';
case 'Series': case 'Series':
@ -1545,6 +1499,12 @@ import 'programStyles';
return '<span class="cardImageIcon material-icons book"></span>'; return '<span class="cardImageIcon material-icons book"></span>';
case 'Folder': case 'Folder':
return '<span class="cardImageIcon material-icons folder"></span>'; return '<span class="cardImageIcon material-icons folder"></span>';
case 'BoxSet':
return '<span class="cardImageIcon material-icons collections"></span>';
case 'Playlist':
return '<span class="cardImageIcon material-icons view_list"></span>';
case 'PhotoAlbum':
return '<span class="cardImageIcon material-icons photo_album"></span>';
} }
if (options && options.defaultCardImageIcon) { if (options && options.defaultCardImageIcon) {
@ -1578,7 +1538,6 @@ import 'programStyles';
const html = buildCardsHtmlInternal(items, options); const html = buildCardsHtmlInternal(items, options);
if (html) { if (html) {
if (options.itemsContainer.cardBuilderHtml !== html) { if (options.itemsContainer.cardBuilderHtml !== html) {
options.itemsContainer.innerHTML = html; options.itemsContainer.innerHTML = html;
@ -1591,7 +1550,6 @@ import 'programStyles';
imageLoader.lazyChildren(options.itemsContainer); imageLoader.lazyChildren(options.itemsContainer);
} else { } else {
options.itemsContainer.innerHTML = html; options.itemsContainer.innerHTML = html;
options.itemsContainer.cardBuilderHtml = null; options.itemsContainer.cardBuilderHtml = null;
} }
@ -1615,7 +1573,6 @@ import 'programStyles';
indicatorsElem = card.querySelector('.cardIndicators'); indicatorsElem = card.querySelector('.cardIndicators');
if (!indicatorsElem) { if (!indicatorsElem) {
const cardImageContainer = card.querySelector('.cardImageContainer'); const cardImageContainer = card.querySelector('.cardImageContainer');
indicatorsElem = document.createElement('div'); indicatorsElem = document.createElement('div');
indicatorsElem.classList.add('cardIndicators'); indicatorsElem.classList.add('cardIndicators');
@ -1639,11 +1596,9 @@ import 'programStyles';
let itemProgressBar = null; let itemProgressBar = null;
if (userData.Played) { if (userData.Played) {
playedIndicator = card.querySelector('.playedIndicator'); playedIndicator = card.querySelector('.playedIndicator');
if (!playedIndicator) { if (!playedIndicator) {
playedIndicator = document.createElement('div'); playedIndicator = document.createElement('div');
playedIndicator.classList.add('playedIndicator'); playedIndicator.classList.add('playedIndicator');
playedIndicator.classList.add('indicator'); playedIndicator.classList.add('indicator');
@ -1652,10 +1607,8 @@ import 'programStyles';
} }
playedIndicator.innerHTML = '<span class="material-icons indicatorIcon check"></span>'; playedIndicator.innerHTML = '<span class="material-icons indicatorIcon check"></span>';
} else { } else {
playedIndicator = card.querySelector('.playedIndicator'); playedIndicator = card.querySelector('.playedIndicator');
if (playedIndicator) { if (playedIndicator) {
playedIndicator.parentNode.removeChild(playedIndicator); playedIndicator.parentNode.removeChild(playedIndicator);
} }
} }
@ -1663,7 +1616,6 @@ import 'programStyles';
countIndicator = card.querySelector('.countIndicator'); countIndicator = card.querySelector('.countIndicator');
if (!countIndicator) { if (!countIndicator) {
countIndicator = document.createElement('div'); countIndicator = document.createElement('div');
countIndicator.classList.add('countIndicator'); countIndicator.classList.add('countIndicator');
indicatorsElem = ensureIndicators(card, indicatorsElem); indicatorsElem = ensureIndicators(card, indicatorsElem);
@ -1671,10 +1623,8 @@ import 'programStyles';
} }
countIndicator.innerHTML = userData.UnplayedItemCount; countIndicator.innerHTML = userData.UnplayedItemCount;
} else if (enableCountIndicator) { } else if (enableCountIndicator) {
countIndicator = card.querySelector('.countIndicator'); countIndicator = card.querySelector('.countIndicator');
if (countIndicator) { if (countIndicator) {
countIndicator.parentNode.removeChild(countIndicator); countIndicator.parentNode.removeChild(countIndicator);
} }
} }
@ -1686,7 +1636,6 @@ import 'programStyles';
}); });
if (progressHtml) { if (progressHtml) {
itemProgressBar = card.querySelector('.itemProgressBar'); itemProgressBar = card.querySelector('.itemProgressBar');
if (!itemProgressBar) { if (!itemProgressBar) {
@ -1705,7 +1654,6 @@ import 'programStyles';
itemProgressBar.innerHTML = progressHtml; itemProgressBar.innerHTML = progressHtml;
} else { } else {
itemProgressBar = card.querySelector('.itemProgressBar'); itemProgressBar = card.querySelector('.itemProgressBar');
if (itemProgressBar) { if (itemProgressBar) {
itemProgressBar.parentNode.removeChild(itemProgressBar); itemProgressBar.parentNode.removeChild(itemProgressBar);
@ -1736,7 +1684,7 @@ import 'programStyles';
const cells = itemsContainer.querySelectorAll('.card[data-id="' + programId + '"]'); const cells = itemsContainer.querySelectorAll('.card[data-id="' + programId + '"]');
for (let i = 0, length = cells.length; i < length; i++) { for (let i = 0, length = cells.length; i < length; i++) {
let cell = cells[i]; const cell = cells[i];
const icon = cell.querySelector('.timerIndicator'); const icon = cell.querySelector('.timerIndicator');
if (!icon) { if (!icon) {
const indicatorsElem = ensureIndicators(cell); const indicatorsElem = ensureIndicators(cell);
@ -1755,8 +1703,8 @@ import 'programStyles';
const cells = itemsContainer.querySelectorAll('.card[data-timerid="' + timerId + '"]'); const cells = itemsContainer.querySelectorAll('.card[data-timerid="' + timerId + '"]');
for (let i = 0; i < cells.length; i++) { for (let i = 0; i < cells.length; i++) {
let cell = cells[i]; const cell = cells[i];
let icon = cell.querySelector('.timerIndicator'); const icon = cell.querySelector('.timerIndicator');
if (icon) { if (icon) {
icon.parentNode.removeChild(icon); icon.parentNode.removeChild(icon);
} }
@ -1773,8 +1721,8 @@ import 'programStyles';
const cells = itemsContainer.querySelectorAll('.card[data-seriestimerid="' + cancelledTimerId + '"]'); const cells = itemsContainer.querySelectorAll('.card[data-seriestimerid="' + cancelledTimerId + '"]');
for (let i = 0; i < cells.length; i++) { for (let i = 0; i < cells.length; i++) {
let cell = cells[i]; const cell = cells[i];
let icon = cell.querySelector('.timerIndicator'); const icon = cell.querySelector('.timerIndicator');
if (icon) { if (icon) {
icon.parentNode.removeChild(icon); icon.parentNode.removeChild(icon);
} }

View file

@ -7,14 +7,12 @@
import datetime from 'datetime'; import datetime from 'datetime';
import imageLoader from 'imageLoader'; import imageLoader from 'imageLoader';
import connectionManager from 'connectionManager';
import layoutManager from 'layoutManager'; import layoutManager from 'layoutManager';
import browser from 'browser'; import browser from 'browser';
const enableFocusTransform = !browser.slow && !browser.edge; const enableFocusTransform = !browser.slow && !browser.edge;
function buildChapterCardsHtml(item, chapters, options) { function buildChapterCardsHtml(item, chapters, options) {
// TODO move card creation code to Card component // TODO move card creation code to Card component
let className = 'card itemAction chapterCard'; let className = 'card itemAction chapterCard';
@ -35,7 +33,6 @@ import browser from 'browser';
let shape = (options.backdropShape || 'backdrop'); let shape = (options.backdropShape || 'backdrop');
if (videoStream.Width && videoStream.Height) { if (videoStream.Width && videoStream.Height) {
if ((videoStream.Width / videoStream.Height) <= 1.2) { if ((videoStream.Width / videoStream.Height) <= 1.2) {
shape = (options.squareShape || 'square'); shape = (options.squareShape || 'square');
} }
@ -50,10 +47,9 @@ import browser from 'browser';
let html = ''; let html = '';
let itemsInRow = 0; let itemsInRow = 0;
const apiClient = connectionManager.getApiClient(item.ServerId); const apiClient = window.connectionManager.getApiClient(item.ServerId);
for (let i = 0, length = chapters.length; i < length; i++) { for (let i = 0, length = chapters.length; i < length; i++) {
if (options.rows && itemsInRow === 0) { if (options.rows && itemsInRow === 0) {
html += '<div class="cardColumn">'; html += '<div class="cardColumn">';
} }
@ -73,12 +69,10 @@ import browser from 'browser';
} }
function getImgUrl({Id}, {ImageTag}, index, maxWidth, apiClient) { function getImgUrl({Id}, {ImageTag}, index, maxWidth, apiClient) {
if (ImageTag) { if (ImageTag) {
return apiClient.getScaledImageUrl(Id, { return apiClient.getScaledImageUrl(Id, {
maxWidth: maxWidth * 2, maxWidth: maxWidth,
tag: ImageTag, tag: ImageTag,
type: 'Chapter', type: 'Chapter',
index index
@ -89,7 +83,6 @@ import browser from 'browser';
} }
function buildChapterCard(item, apiClient, chapter, index, {width, coverImage}, className, shape) { function buildChapterCard(item, apiClient, chapter, index, {width, coverImage}, className, shape) {
const imgUrl = getImgUrl(item, chapter, index, width || 400, apiClient); const imgUrl = getImgUrl(item, chapter, index, width || 400, apiClient);
let cardImageContainerClass = 'cardContent cardContent-shadow cardImageContainer chapterCardImageContainer'; let cardImageContainerClass = 'cardContent cardContent-shadow cardImageContainer chapterCardImageContainer';
@ -110,13 +103,10 @@ import browser from 'browser';
const cardBoxCssClass = 'cardBox'; const cardBoxCssClass = 'cardBox';
const cardScalableClass = 'cardScalable'; const cardScalableClass = 'cardScalable';
const html = `<button type="button" class="${className}"${dataAttributes}><div class="${cardBoxCssClass}"><div class="${cardScalableClass}"><div class="cardPadder-${shape}"></div>${cardImageContainer}</div><div class="innerCardFooter">${nameHtml}</div></div></div></button>`; return `<button type="button" class="${className}"${dataAttributes}><div class="${cardBoxCssClass}"><div class="${cardScalableClass}"><div class="cardPadder-${shape}"></div>${cardImageContainer}</div><div class="innerCardFooter">${nameHtml}</div></div></div></button>`;
return html;
} }
export function buildChapterCards(item, chapters, options) { export function buildChapterCards(item, chapters, options) {
if (options.parentContainer) { if (options.parentContainer) {
// Abort if the container has been disposed // Abort if the container has been disposed
if (!document.body.contains(options.parentContainer)) { if (!document.body.contains(options.parentContainer)) {

View file

@ -8,7 +8,6 @@
import cardBuilder from 'cardBuilder'; import cardBuilder from 'cardBuilder';
export function buildPeopleCards(items, options) { export function buildPeopleCards(items, options) {
options = Object.assign(options || {}, { options = Object.assign(options || {}, {
cardLayout: false, cardLayout: false,
centerText: true, centerText: true,

View file

@ -1,23 +1,16 @@
define([], function() { class CastSenderApi {
'use strict'; load() {
if (window.appMode === 'cordova' || window.appMode === 'android') { if (window.appMode === 'cordova' || window.appMode === 'android') {
return {
load: function () {
window.chrome = window.chrome || {}; window.chrome = window.chrome || {};
return Promise.resolve(); return Promise.resolve();
}
};
} else { } else {
var ccLoaded = false; let ccLoaded = false;
return {
load: function () {
if (ccLoaded) { if (ccLoaded) {
return Promise.resolve(); return Promise.resolve();
} }
return new Promise(function (resolve, reject) { return new Promise(function (resolve) {
var fileref = document.createElement('script'); const fileref = document.createElement('script');
fileref.setAttribute('type', 'text/javascript'); fileref.setAttribute('type', 'text/javascript');
fileref.onload = function () { fileref.onload = function () {
@ -29,6 +22,7 @@ define([], function() {
document.querySelector('head').appendChild(fileref); document.querySelector('head').appendChild(fileref);
}); });
} }
};
} }
}); }
export default CastSenderApi;

View file

@ -1,21 +1,32 @@
define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'actionsheet', 'emby-input', 'paper-icon-button-light', 'emby-button', 'listViewStyle', 'material-icons', 'formDialogStyle'], function (dom, dialogHelper, loading, connectionManager, globalize, actionsheet) { import dom from 'dom';
'use strict'; import dialogHelper from 'dialogHelper';
import loading from 'loading';
import globalize from 'globalize';
import actionsheet from 'actionsheet';
import 'emby-input';
import 'paper-icon-button-light';
import 'emby-button';
import 'listViewStyle';
import 'material-icons';
import 'formDialogStyle';
return function (options) { export default class channelMapper {
constructor(options) {
function mapChannel(button, channelId, providerChannelId) { function mapChannel(button, channelId, providerChannelId) {
loading.show(); loading.show();
var providerId = options.providerId; const providerId = options.providerId;
connectionManager.getApiClient(options.serverId).ajax({ window.connectionManager.getApiClient(options.serverId).ajax({
type: 'POST', type: 'POST',
url: ApiClient.getUrl('LiveTv/ChannelMappings'), url: ApiClient.getUrl('LiveTv/ChannelMappings'),
data: { data: JSON.stringify({
providerId: providerId, providerId: providerId,
tunerChannelId: channelId, tunerChannelId: channelId,
providerChannelId: providerChannelId providerChannelId: providerChannelId
}, }),
contentType: 'application/json',
dataType: 'json' dataType: 'json'
}).then(function (mapping) { }).then(mapping => {
var listItem = dom.parentWithClass(button, 'listItem'); const listItem = dom.parentWithClass(button, 'listItem');
button.setAttribute('data-providerid', mapping.ProviderChannelId); button.setAttribute('data-providerid', mapping.ProviderChannelId);
listItem.querySelector('.secondary').innerHTML = getMappingSecondaryName(mapping, currentMappingOptions.ProviderName); listItem.querySelector('.secondary').innerHTML = getMappingSecondaryName(mapping, currentMappingOptions.ProviderName);
loading.hide(); loading.hide();
@ -23,42 +34,42 @@ define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'act
} }
function onChannelsElementClick(e) { function onChannelsElementClick(e) {
var btnMap = dom.parentWithClass(e.target, 'btnMap'); const btnMap = dom.parentWithClass(e.target, 'btnMap');
if (btnMap) { if (btnMap) {
var channelId = btnMap.getAttribute('data-id'); const channelId = btnMap.getAttribute('data-id');
var providerChannelId = btnMap.getAttribute('data-providerid'); const providerChannelId = btnMap.getAttribute('data-providerid');
var menuItems = currentMappingOptions.ProviderChannels.map(function (m) { const menuItems = currentMappingOptions.ProviderChannels.map(m => {
return { return {
name: m.Name, name: m.Name,
id: m.Id, id: m.Id,
selected: m.Id.toLowerCase() === providerChannelId.toLowerCase() selected: m.Id.toLowerCase() === providerChannelId.toLowerCase()
}; };
}).sort(function (a, b) { }).sort((a, b) => {
return a.name.localeCompare(b.name); return a.name.localeCompare(b.name);
}); });
actionsheet.show({ actionsheet.show({
positionTo: btnMap, positionTo: btnMap,
items: menuItems items: menuItems
}).then(function (newChannelId) { }).then(newChannelId => {
mapChannel(btnMap, channelId, newChannelId); mapChannel(btnMap, channelId, newChannelId);
}); });
} }
} }
function getChannelMappingOptions(serverId, providerId) { function getChannelMappingOptions(serverId, providerId) {
var apiClient = connectionManager.getApiClient(serverId); const apiClient = window.connectionManager.getApiClient(serverId);
return apiClient.getJSON(apiClient.getUrl('LiveTv/ChannelMappingOptions', { return apiClient.getJSON(apiClient.getUrl('LiveTv/ChannelMappingOptions', {
providerId: providerId providerId: providerId
})); }));
} }
function getMappingSecondaryName(mapping, providerName) { function getMappingSecondaryName(mapping, providerName) {
return (mapping.ProviderChannelName || '') + ' - ' + providerName; return `${mapping.ProviderChannelName || ''} - ${providerName}`;
} }
function getTunerChannelHtml(channel, providerName) { function getTunerChannelHtml(channel, providerName) {
var html = ''; let html = '';
html += '<div class="listItem">'; html += '<div class="listItem">';
html += '<span class="material-icons listItemIcon dvr"></span>'; html += '<span class="material-icons listItemIcon dvr"></span>';
html += '<div class="listItemBody two-line">'; html += '<div class="listItemBody two-line">';
@ -73,16 +84,16 @@ define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'act
html += '</div>'; html += '</div>';
html += '</div>'; html += '</div>';
html += '<button class="btnMap autoSize" is="paper-icon-button-light" type="button" data-id="' + channel.Id + '" data-providerid="' + channel.ProviderChannelId + '"><span class="material-icons mode_edit"></span></button>'; html += `<button class="btnMap autoSize" is="paper-icon-button-light" type="button" data-id="${channel.Id}" data-providerid="${channel.ProviderChannelId}"><span class="material-icons mode_edit"></span></button>`;
return html += '</div>'; return html += '</div>';
} }
function getEditorHtml() { function getEditorHtml() {
var html = ''; let html = '';
html += '<div class="formDialogContent smoothScrollY">'; html += '<div class="formDialogContent smoothScrollY">';
html += '<div class="dialogContentInner dialog-content-centered">'; html += '<div class="dialogContentInner dialog-content-centered">';
html += '<form style="margin:auto;">'; html += '<form style="margin:auto;">';
html += '<h1>' + globalize.translate('HeaderChannels') + '</h1>'; html += `<h1>${globalize.translate('Channels')}</h1>`;
html += '<div class="channels paperList">'; html += '<div class="channels paperList">';
html += '</div>'; html += '</div>';
html += '</form>'; html += '</form>';
@ -91,30 +102,29 @@ define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'act
} }
function initEditor(dlg, options) { function initEditor(dlg, options) {
getChannelMappingOptions(options.serverId, options.providerId).then(function (result) { getChannelMappingOptions(options.serverId, options.providerId).then(result => {
currentMappingOptions = result; currentMappingOptions = result;
var channelsElement = dlg.querySelector('.channels'); const channelsElement = dlg.querySelector('.channels');
channelsElement.innerHTML = result.TunerChannels.map(function (channel) { channelsElement.innerHTML = result.TunerChannels.map(channel => {
return getTunerChannelHtml(channel, result.ProviderName); return getTunerChannelHtml(channel, result.ProviderName);
}).join(''); }).join('');
channelsElement.addEventListener('click', onChannelsElementClick); channelsElement.addEventListener('click', onChannelsElementClick);
}); });
} }
var currentMappingOptions; let currentMappingOptions;
var self = this;
self.show = function () { this.show = () => {
var dialogOptions = { const dialogOptions = {
removeOnClose: true removeOnClose: true
}; };
dialogOptions.size = 'small'; dialogOptions.size = 'small';
var dlg = dialogHelper.createDialog(dialogOptions); const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog'); dlg.classList.add('formDialog');
dlg.classList.add('ui-body-a'); dlg.classList.add('ui-body-a');
dlg.classList.add('background-theme-a'); dlg.classList.add('background-theme-a');
var html = ''; let html = '';
var title = globalize.translate('MapChannels'); const title = globalize.translate('MapChannels');
html += '<div class="formDialogHeader">'; html += '<div class="formDialogHeader">';
html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>'; html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
html += '<h3 class="formDialogHeaderTitle">'; html += '<h3 class="formDialogHeaderTitle">';
@ -124,13 +134,13 @@ define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'act
html += getEditorHtml(); html += getEditorHtml();
dlg.innerHTML = html; dlg.innerHTML = html;
initEditor(dlg, options); initEditor(dlg, options);
dlg.querySelector('.btnCancel').addEventListener('click', function () { dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg); dialogHelper.close(dlg);
}); });
return new Promise(function (resolve, reject) { return new Promise(resolve => {
dlg.addEventListener('close', resolve); dlg.addEventListener('close', resolve);
dialogHelper.open(dlg); dialogHelper.open(dlg);
}); });
}; };
}; }
}); }

View file

@ -1,16 +1,30 @@
define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'flexStyles'], function (dom, dialogHelper, loading, appHost, layoutManager, connectionManager, appRouter, globalize) { import dom from 'dom';
'use strict'; import dialogHelper from 'dialogHelper';
import loading from 'loading';
import layoutManager from 'layoutManager';
import appRouter from 'appRouter';
import globalize from 'globalize';
import 'emby-checkbox';
import 'emby-input';
import 'paper-icon-button-light';
import 'emby-select';
import 'material-icons';
import 'css!./../formdialog';
import 'emby-button';
import 'flexStyles';
var currentServerId; /* eslint-disable indent */
let currentServerId;
function onSubmit(e) { function onSubmit(e) {
loading.show(); loading.show();
var panel = dom.parentWithClass(this, 'dialog'); const panel = dom.parentWithClass(this, 'dialog');
var collectionId = panel.querySelector('#selectCollectionToAddTo').value; const collectionId = panel.querySelector('#selectCollectionToAddTo').value;
var apiClient = connectionManager.getApiClient(currentServerId); const apiClient = window.connectionManager.getApiClient(currentServerId);
if (collectionId) { if (collectionId) {
addToCollection(apiClient, panel, collectionId); addToCollection(apiClient, panel, collectionId);
@ -23,8 +37,7 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
} }
function createCollection(apiClient, dlg) { function createCollection(apiClient, dlg) {
const url = apiClient.getUrl('Collections', {
var url = apiClient.getUrl('Collections', {
Name: dlg.querySelector('#txtNewCollectionName').value, Name: dlg.querySelector('#txtNewCollectionName').value,
IsLocked: !dlg.querySelector('#chkEnableInternetMetadata').checked, IsLocked: !dlg.querySelector('#chkEnableInternetMetadata').checked,
@ -36,27 +49,23 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
url: url, url: url,
dataType: 'json' dataType: 'json'
}).then(function (result) { }).then(result => {
loading.hide(); loading.hide();
var id = result.Id; const id = result.Id;
dlg.submitted = true; dlg.submitted = true;
dialogHelper.close(dlg); dialogHelper.close(dlg);
redirectToCollection(apiClient, id); redirectToCollection(apiClient, id);
}); });
} }
function redirectToCollection(apiClient, id) { function redirectToCollection(apiClient, id) {
appRouter.showItem(id, apiClient.serverId()); appRouter.showItem(id, apiClient.serverId());
} }
function addToCollection(apiClient, dlg, id) { function addToCollection(apiClient, dlg, id) {
const url = apiClient.getUrl(`Collections/${id}/Items`, {
var url = apiClient.getUrl('Collections/' + id + '/Items', {
Ids: dlg.querySelector('.fldSelectedItemIds').value || '' Ids: dlg.querySelector('.fldSelectedItemIds').value || ''
}); });
@ -65,14 +74,13 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
type: 'POST', type: 'POST',
url: url url: url
}).then(function () { }).then(() => {
loading.hide(); loading.hide();
dlg.submitted = true; dlg.submitted = true;
dialogHelper.close(dlg); dialogHelper.close(dlg);
require(['toast'], function (toast) { import('toast').then(({default: toast}) => {
toast(globalize.translate('MessageItemsAdded')); toast(globalize.translate('MessageItemsAdded'));
}); });
}); });
@ -83,14 +91,13 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
} }
function populateCollections(panel) { function populateCollections(panel) {
loading.show(); loading.show();
var select = panel.querySelector('#selectCollectionToAddTo'); const select = panel.querySelector('#selectCollectionToAddTo');
panel.querySelector('.newCollectionInfo').classList.add('hide'); panel.querySelector('.newCollectionInfo').classList.add('hide');
var options = { const options = {
Recursive: true, Recursive: true,
IncludeItemTypes: 'BoxSet', IncludeItemTypes: 'BoxSet',
@ -98,16 +105,14 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
EnableTotalRecordCount: false EnableTotalRecordCount: false
}; };
var apiClient = connectionManager.getApiClient(currentServerId); const apiClient = window.connectionManager.getApiClient(currentServerId);
apiClient.getItems(apiClient.getCurrentUserId(), options).then(function (result) { apiClient.getItems(apiClient.getCurrentUserId(), options).then(result => {
let html = '';
var html = ''; html += `<option value="">${globalize.translate('OptionNew')}</option>`;
html += '<option value="">' + globalize.translate('OptionNew') + '</option>'; html += result.Items.map(i => {
return `<option value="${i.Id}">${i.Name}</option>`;
html += result.Items.map(function (i) {
return '<option value="' + i.Id + '">' + i.Name + '</option>';
}); });
select.innerHTML = html; select.innerHTML = html;
@ -119,8 +124,7 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
} }
function getEditorHtml() { function getEditorHtml() {
let html = '';
var html = '';
html += '<div class="formDialogContent smoothScrollY" style="padding-top:2em;">'; html += '<div class="formDialogContent smoothScrollY" style="padding-top:2em;">';
html += '<div class="dialogContentInner dialog-content-centered">'; html += '<div class="dialogContentInner dialog-content-centered">';
@ -134,27 +138,27 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
html += '<br/>'; html += '<br/>';
html += '<br/>'; html += '<br/>';
html += '<div class="selectContainer">'; html += '<div class="selectContainer">';
html += '<select is="emby-select" label="' + globalize.translate('LabelCollection') + '" id="selectCollectionToAddTo" autofocus></select>'; html += `<select is="emby-select" label="${globalize.translate('LabelCollection')}" id="selectCollectionToAddTo" autofocus></select>`;
html += '</div>'; html += '</div>';
html += '</div>'; html += '</div>';
html += '<div class="newCollectionInfo">'; html += '<div class="newCollectionInfo">';
html += '<div class="inputContainer">'; html += '<div class="inputContainer">';
html += '<input is="emby-input" type="text" id="txtNewCollectionName" required="required" label="' + globalize.translate('LabelName') + '" />'; html += `<input is="emby-input" type="text" id="txtNewCollectionName" required="required" label="${globalize.translate('LabelName')}" />`;
html += '<div class="fieldDescription">' + globalize.translate('NewCollectionNameExample') + '</div>'; html += `<div class="fieldDescription">${globalize.translate('NewCollectionNameExample')}</div>`;
html += '</div>'; html += '</div>';
html += '<label class="checkboxContainer">'; html += '<label class="checkboxContainer">';
html += '<input is="emby-checkbox" type="checkbox" id="chkEnableInternetMetadata" />'; html += '<input is="emby-checkbox" type="checkbox" id="chkEnableInternetMetadata" />';
html += '<span>' + globalize.translate('SearchForCollectionInternetMetadata') + '</span>'; html += `<span>${globalize.translate('SearchForCollectionInternetMetadata')}</span>`;
html += '</label>'; html += '</label>';
// newCollectionInfo // newCollectionInfo
html += '</div>'; html += '</div>';
html += '<div class="formDialogFooter">'; html += '<div class="formDialogFooter">';
html += '<button is="emby-button" type="submit" class="raised btnSubmit block formDialogFooterItem button-submit">' + globalize.translate('ButtonOk') + '</button>'; html += `<button is="emby-button" type="submit" class="raised btnSubmit block formDialogFooterItem button-submit">${globalize.translate('ButtonOk')}</button>`;
html += '</div>'; html += '</div>';
html += '<input type="hidden" class="fldSelectedItemIds" />'; html += '<input type="hidden" class="fldSelectedItemIds" />';
@ -167,7 +171,6 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
} }
function initEditor(content, items) { function initEditor(content, items) {
content.querySelector('#selectCollectionToAddTo').addEventListener('change', function () { content.querySelector('#selectCollectionToAddTo').addEventListener('change', function () {
if (this.value) { if (this.value) {
content.querySelector('.newCollectionInfo').classList.add('hide'); content.querySelector('.newCollectionInfo').classList.add('hide');
@ -188,7 +191,7 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
} else { } else {
content.querySelector('.fldSelectCollection').classList.add('hide'); content.querySelector('.fldSelectCollection').classList.add('hide');
var selectCollectionToAddTo = content.querySelector('#selectCollectionToAddTo'); const selectCollectionToAddTo = content.querySelector('#selectCollectionToAddTo');
selectCollectionToAddTo.innerHTML = ''; selectCollectionToAddTo.innerHTML = '';
selectCollectionToAddTo.value = ''; selectCollectionToAddTo.value = '';
triggerChange(selectCollectionToAddTo); triggerChange(selectCollectionToAddTo);
@ -196,22 +199,18 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
} }
function centerFocus(elem, horiz, on) { function centerFocus(elem, horiz, on) {
require(['scrollHelper'], function (scrollHelper) { import('scrollHelper').then((scrollHelper) => {
var fn = on ? 'on' : 'off'; const fn = on ? 'on' : 'off';
scrollHelper.centerFocus[fn](elem, horiz); scrollHelper.centerFocus[fn](elem, horiz);
}); });
} }
function CollectionEditor() { export class showEditor {
constructor(options) {
} const items = options.items || {};
CollectionEditor.prototype.show = function (options) {
var items = options.items || {};
currentServerId = options.serverId; currentServerId = options.serverId;
var dialogOptions = { const dialogOptions = {
removeOnClose: true, removeOnClose: true,
scrollY: false scrollY: false
}; };
@ -222,12 +221,12 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
dialogOptions.size = 'small'; dialogOptions.size = 'small';
} }
var dlg = dialogHelper.createDialog(dialogOptions); const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog'); dlg.classList.add('formDialog');
var html = ''; let html = '';
var title = items.length ? globalize.translate('HeaderAddToCollection') : globalize.translate('NewCollection'); const title = items.length ? globalize.translate('HeaderAddToCollection') : globalize.translate('NewCollection');
html += '<div class="formDialogHeader">'; html += '<div class="formDialogHeader">';
html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>'; html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
@ -235,10 +234,6 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
html += title; html += title;
html += '</h3>'; html += '</h3>';
if (appHost.supports('externallinks')) {
html += '<a is="emby-linkbutton" class="button-link btnHelp flex align-items-center" href="https://web.archive.org/web/20181216120305/https://github.com/MediaBrowser/Wiki/wiki/Collections" target="_blank" style="margin-left:auto;margin-right:.5em;padding:.25em;" title="' + globalize.translate('Help') + '"><span class="material-icons info"></span><span style="margin-left:.25em;">' + globalize.translate('Help') + '</span></a>';
}
html += '</div>'; html += '</div>';
html += getEditorHtml(); html += getEditorHtml();
@ -247,8 +242,7 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
initEditor(dlg, items); initEditor(dlg, items);
dlg.querySelector('.btnCancel').addEventListener('click', function () { dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg); dialogHelper.close(dlg);
}); });
@ -256,8 +250,7 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
centerFocus(dlg.querySelector('.formDialogContent'), false, true); centerFocus(dlg.querySelector('.formDialogContent'), false, true);
} }
return dialogHelper.open(dlg).then(function () { return dialogHelper.open(dlg).then(() => {
if (layoutManager.tv) { if (layoutManager.tv) {
centerFocus(dlg.querySelector('.formDialogContent'), false, false); centerFocus(dlg.querySelector('.formDialogContent'), false, false);
} }
@ -268,7 +261,8 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
return Promise.reject(); return Promise.reject();
}); });
}; }
}
return CollectionEditor; /* eslint-enable indent */
}); export default showEditor;

View file

@ -1,13 +1,16 @@
define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize) { import browser from 'browser';
'use strict'; import dialog from 'dialog';
import globalize from 'globalize';
/* eslint-disable indent */
export default (() => {
function replaceAll(str, find, replace) { function replaceAll(str, find, replace) {
return str.split(find).join(replace); return str.split(find).join(replace);
} }
if (browser.tv && window.confirm) { if (browser.tv && window.confirm) {
// Use the native confirm dialog // Use the native confirm dialog
return function (options) { return options => {
if (typeof options === 'string') { if (typeof options === 'string') {
options = { options = {
title: '', title: '',
@ -15,8 +18,8 @@ define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize)
}; };
} }
var text = replaceAll(options.text || '', '<br/>', '\n'); const text = replaceAll(options.text || '', '<br/>', '\n');
var result = confirm(text); const result = window.confirm(text);
if (result) { if (result) {
return Promise.resolve(); return Promise.resolve();
@ -26,8 +29,8 @@ define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize)
}; };
} else { } else {
// Use our own dialog // Use our own dialog
return function (text, title) { return (text, title) => {
var options; let options;
if (typeof text === 'string') { if (typeof text === 'string') {
options = { options = {
title: title, title: title,
@ -37,7 +40,7 @@ define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize)
options = text; options = text;
} }
var items = []; const items = [];
items.push({ items.push({
name: options.cancelText || globalize.translate('ButtonCancel'), name: options.cancelText || globalize.translate('ButtonCancel'),
@ -53,7 +56,7 @@ define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize)
options.buttons = items; options.buttons = items;
return dialog(options).then(function (result) { return dialog.show(options).then(result => {
if (result === 'ok') { if (result === 'ok') {
return Promise.resolve(); return Promise.resolve();
} }
@ -62,4 +65,5 @@ define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize)
}); });
}; };
} }
}); })();
/* eslint-enable indent */

View file

@ -1,20 +1,30 @@
define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 'require', 'material-icons', 'emby-button', 'paper-icon-button-light', 'emby-input', 'formDialogStyle', 'flexStyles'], function (dialogHelper, dom, layoutManager, scrollHelper, globalize, require) { import dialogHelper from 'dialogHelper';
'use strict'; import dom from 'dom';
import layoutManager from 'layoutManager';
import scrollHelper from 'scrollHelper';
import globalize from 'globalize';
import 'material-icons';
import 'emby-button';
import 'paper-icon-button-light';
import 'emby-input';
import 'formDialogStyle';
import 'flexStyles';
/* eslint-disable indent */
function showDialog(options, template) { function showDialog(options, template) {
const dialogOptions = {
var dialogOptions = {
removeOnClose: true, removeOnClose: true,
scrollY: false scrollY: false
}; };
var enableTvLayout = layoutManager.tv; const enableTvLayout = layoutManager.tv;
if (enableTvLayout) { if (enableTvLayout) {
dialogOptions.size = 'fullscreen'; dialogOptions.size = 'fullscreen';
} }
var dlg = dialogHelper.createDialog(dialogOptions); const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog'); dlg.classList.add('formDialog');
@ -22,7 +32,7 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
dlg.classList.add('align-items-center'); dlg.classList.add('align-items-center');
dlg.classList.add('justify-content-center'); dlg.classList.add('justify-content-center');
var formDialogContent = dlg.querySelector('.formDialogContent'); const formDialogContent = dlg.querySelector('.formDialogContent');
formDialogContent.classList.add('no-grow'); formDialogContent.classList.add('no-grow');
if (enableTvLayout) { if (enableTvLayout) {
@ -30,41 +40,36 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
formDialogContent.style['max-height'] = '60%'; formDialogContent.style['max-height'] = '60%';
scrollHelper.centerFocus.on(formDialogContent, false); scrollHelper.centerFocus.on(formDialogContent, false);
} else { } else {
formDialogContent.style.maxWidth = (Math.min((options.buttons.length * 150) + 200, dom.getWindowSize().innerWidth - 50)) + 'px'; formDialogContent.style.maxWidth = `${Math.min((options.buttons.length * 150) + 200, dom.getWindowSize().innerWidth - 50)}px`;
dlg.classList.add('dialog-fullscreen-lowres'); dlg.classList.add('dialog-fullscreen-lowres');
} }
//dlg.querySelector('.btnCancel').addEventListener('click', function (e) {
// dialogHelper.close(dlg);
//});
if (options.title) { if (options.title) {
dlg.querySelector('.formDialogHeaderTitle').innerHTML = options.title || ''; dlg.querySelector('.formDialogHeaderTitle').innerHTML = options.title || '';
} else { } else {
dlg.querySelector('.formDialogHeaderTitle').classList.add('hide'); dlg.querySelector('.formDialogHeaderTitle').classList.add('hide');
} }
var displayText = options.html || options.text || ''; const displayText = options.html || options.text || '';
dlg.querySelector('.text').innerHTML = displayText; dlg.querySelector('.text').innerHTML = displayText;
if (!displayText) { if (!displayText) {
dlg.querySelector('.dialogContentInner').classList.add('hide'); dlg.querySelector('.dialogContentInner').classList.add('hide');
} }
var i; let i;
var length; let length;
var html = ''; let html = '';
var hasDescriptions = false; let hasDescriptions = false;
for (i = 0, length = options.buttons.length; i < length; i++) { for (i = 0, length = options.buttons.length; i < length; i++) {
const item = options.buttons[i];
const autoFocus = i === 0 ? ' autofocus' : '';
var item = options.buttons[i]; let buttonClass = 'btnOption raised formDialogFooterItem formDialogFooterItem-autosize';
var autoFocus = i === 0 ? ' autofocus' : '';
var buttonClass = 'btnOption raised formDialogFooterItem formDialogFooterItem-autosize';
if (item.type) { if (item.type) {
buttonClass += ' button-' + item.type; buttonClass += ` button-${item.type}`;
} }
if (item.description) { if (item.description) {
@ -75,10 +80,10 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
buttonClass += ' formDialogFooterItem-vertical formDialogFooterItem-nomarginbottom'; buttonClass += ' formDialogFooterItem-vertical formDialogFooterItem-nomarginbottom';
} }
html += '<button is="emby-button" type="button" class="' + buttonClass + '" data-id="' + item.id + '"' + autoFocus + '>' + item.name + '</button>'; html += `<button is="emby-button" type="button" class="${buttonClass}" data-id="${item.id}"${autoFocus}>${item.name}</button>`;
if (item.description) { if (item.description) {
html += '<div class="formDialogFooterItem formDialogFooterItem-autosize fieldDescription" style="margin-top:.25em!important;margin-bottom:1.25em!important;">' + item.description + '</div>'; html += `<div class="formDialogFooterItem formDialogFooterItem-autosize fieldDescription" style="margin-top:.25em!important;margin-bottom:1.25em!important;">${item.description}</div>`;
} }
} }
@ -88,19 +93,18 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
dlg.querySelector('.formDialogFooter').classList.add('formDialogFooter-vertical'); dlg.querySelector('.formDialogFooter').classList.add('formDialogFooter-vertical');
} }
var dialogResult; let dialogResult;
function onButtonClick() { function onButtonClick() {
dialogResult = this.getAttribute('data-id'); dialogResult = this.getAttribute('data-id');
dialogHelper.close(dlg); dialogHelper.close(dlg);
} }
var buttons = dlg.querySelectorAll('.btnOption'); const buttons = dlg.querySelectorAll('.btnOption');
for (i = 0, length = buttons.length; i < length; i++) { for (i = 0, length = buttons.length; i < length; i++) {
buttons[i].addEventListener('click', onButtonClick); buttons[i].addEventListener('click', onButtonClick);
} }
return dialogHelper.open(dlg).then(function () { return dialogHelper.open(dlg).then(() => {
if (enableTvLayout) { if (enableTvLayout) {
scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false); scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false);
} }
@ -113,9 +117,8 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
}); });
} }
return function (text, title) { export async function show(text, title) {
let options;
var options;
if (typeof text === 'string') { if (typeof text === 'string') {
options = { options = {
title: title, title: title,
@ -125,10 +128,13 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
options = text; options = text;
} }
return new Promise(function (resolve, reject) { const { default: template } = await import('text!./dialog.template.html');
require(['text!./dialog.template.html'], function (template) { return new Promise((resolve, reject) => {
showDialog(options, template).then(resolve, reject); showDialog(options, template).then(resolve, reject);
}); });
}); }
};
}); /* eslint-enable indent */
export default {
show: show
};

View file

@ -1,10 +1,17 @@
define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', 'dom', 'css!./dialoghelper.css', 'scrollStyles'], function (appRouter, focusManager, browser, layoutManager, inputManager, dom) { import appRouter from 'appRouter';
'use strict'; import focusManager from 'focusManager';
import browser from 'browser';
import layoutManager from 'layoutManager';
import inputManager from 'inputManager';
import dom from 'dom';
import 'css!./dialoghelper.css';
import 'scrollStyles';
var globalOnOpenCallback; /* eslint-disable indent */
let globalOnOpenCallback;
function enableAnimation() { function enableAnimation() {
// too slow // too slow
if (browser.tv) { if (browser.tv) {
return false; return false;
@ -14,7 +21,6 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
} }
function removeCenterFocus(dlg) { function removeCenterFocus(dlg) {
if (layoutManager.tv) { if (layoutManager.tv) {
if (dlg.classList.contains('scrollX')) { if (dlg.classList.contains('scrollX')) {
centerFocus(dlg, true, false); centerFocus(dlg, true, false);
@ -25,9 +31,8 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
} }
function tryRemoveElement(elem) { function tryRemoveElement(elem) {
var parentNode = elem.parentNode; const parentNode = elem.parentNode;
if (parentNode) { if (parentNode) {
// Seeing crashes in edge webview // Seeing crashes in edge webview
try { try {
parentNode.removeChild(elem); parentNode.removeChild(elem);
@ -38,15 +43,13 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
} }
function DialogHashHandler(dlg, hash, resolve) { function DialogHashHandler(dlg, hash, resolve) {
const self = this;
var self = this;
self.originalUrl = window.location.href; self.originalUrl = window.location.href;
var activeElement = document.activeElement; const activeElement = document.activeElement;
var removeScrollLockOnClose = false; let removeScrollLockOnClose = false;
function onHashChange(e) { function onHashChange(e) {
const isBack = self.originalUrl === window.location.href;
var isBack = self.originalUrl === window.location.href;
if (isBack || !isOpened(dlg)) { if (isBack || !isOpened(dlg)) {
window.removeEventListener('popstate', onHashChange); window.removeEventListener('popstate', onHashChange);
@ -59,7 +62,6 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
} }
function onBackCommand(e) { function onBackCommand(e) {
if (e.detail.command === 'back') { if (e.detail.command === 'back') {
self.closedByBack = true; self.closedByBack = true;
e.preventDefault(); e.preventDefault();
@ -69,7 +71,6 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
} }
function onDialogClosed() { function onDialogClosed() {
if (!isHistoryEnabled(dlg)) { if (!isHistoryEnabled(dlg)) {
inputManager.off(dlg, onBackCommand); inputManager.off(dlg, onBackCommand);
} }
@ -84,9 +85,9 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
} }
if (!self.closedByBack && isHistoryEnabled(dlg)) { if (!self.closedByBack && isHistoryEnabled(dlg)) {
var state = history.state || {}; const state = window.history.state || {};
if (state.dialogId === hash) { if (state.dialogId === hash) {
history.back(); window.history.back();
} }
} }
@ -97,7 +98,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
if (dlg.getAttribute('data-removeonclose') !== 'false') { if (dlg.getAttribute('data-removeonclose') !== 'false') {
removeCenterFocus(dlg); removeCenterFocus(dlg);
var dialogContainer = dlg.dialogContainer; const dialogContainer = dlg.dialogContainer;
if (dialogContainer) { if (dialogContainer) {
tryRemoveElement(dialogContainer); tryRemoveElement(dialogContainer);
dlg.dialogContainer = null; dlg.dialogContainer = null;
@ -108,7 +109,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
//resolve(); //resolve();
// if we just called history.back(), then use a timeout to allow the history events to fire first // if we just called history.back(), then use a timeout to allow the history events to fire first
setTimeout(function () { setTimeout(() => {
resolve({ resolve({
element: dlg, element: dlg,
closedByBack: self.closedByBack closedByBack: self.closedByBack
@ -118,7 +119,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
dlg.addEventListener('close', onDialogClosed); dlg.addEventListener('close', onDialogClosed);
var center = !dlg.classList.contains('dialog-fixedSize'); const center = !dlg.classList.contains('dialog-fixedSize');
if (center) { if (center) {
dlg.classList.add('centeredDialog'); dlg.classList.add('centeredDialog');
} }
@ -141,7 +142,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
animateDialogOpen(dlg); animateDialogOpen(dlg);
if (isHistoryEnabled(dlg)) { if (isHistoryEnabled(dlg)) {
appRouter.pushState({ dialogId: hash }, 'Dialog', '#' + hash); appRouter.pushState({ dialogId: hash }, 'Dialog', `#${hash}`);
window.addEventListener('popstate', onHashChange); window.addEventListener('popstate', onHashChange);
} else { } else {
@ -150,11 +151,10 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
} }
function addBackdropOverlay(dlg) { function addBackdropOverlay(dlg) {
const backdrop = document.createElement('div');
var backdrop = document.createElement('div');
backdrop.classList.add('dialogBackdrop'); backdrop.classList.add('dialogBackdrop');
var backdropParent = dlg.dialogContainer || dlg; const backdropParent = dlg.dialogContainer || dlg;
backdropParent.parentNode.insertBefore(backdrop, backdropParent); backdropParent.parentNode.insertBefore(backdrop, backdropParent);
dlg.backdrop = backdrop; dlg.backdrop = backdrop;
@ -162,7 +162,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
void backdrop.offsetWidth; void backdrop.offsetWidth;
backdrop.classList.add('dialogBackdropOpened'); backdrop.classList.add('dialogBackdropOpened');
dom.addEventListener((dlg.dialogContainer || backdrop), 'click', function (e) { dom.addEventListener((dlg.dialogContainer || backdrop), 'click', e => {
if (e.target === dlg.dialogContainer) { if (e.target === dlg.dialogContainer) {
close(dlg); close(dlg);
} }
@ -170,7 +170,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
passive: true passive: true
}); });
dom.addEventListener((dlg.dialogContainer || backdrop), 'contextmenu', function (e) { dom.addEventListener((dlg.dialogContainer || backdrop), 'contextmenu', e => {
if (e.target === dlg.dialogContainer) { if (e.target === dlg.dialogContainer) {
// Close the application dialog menu // Close the application dialog menu
close(dlg); close(dlg);
@ -184,40 +184,36 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
return dlg.getAttribute('data-history') === 'true'; return dlg.getAttribute('data-history') === 'true';
} }
function open(dlg) { export function open(dlg) {
if (globalOnOpenCallback) { if (globalOnOpenCallback) {
globalOnOpenCallback(dlg); globalOnOpenCallback(dlg);
} }
var parent = dlg.parentNode; const parent = dlg.parentNode;
if (parent) { if (parent) {
parent.removeChild(dlg); parent.removeChild(dlg);
} }
var dialogContainer = document.createElement('div'); const dialogContainer = document.createElement('div');
dialogContainer.classList.add('dialogContainer'); dialogContainer.classList.add('dialogContainer');
dialogContainer.appendChild(dlg); dialogContainer.appendChild(dlg);
dlg.dialogContainer = dialogContainer; dlg.dialogContainer = dialogContainer;
document.body.appendChild(dialogContainer); document.body.appendChild(dialogContainer);
return new Promise(function (resolve, reject) { return new Promise((resolve, reject) => {
new DialogHashHandler(dlg, `dlg${new Date().getTime()}`, resolve);
new DialogHashHandler(dlg, 'dlg' + new Date().getTime(), resolve);
}); });
} }
function isOpened(dlg) { function isOpened(dlg) {
//return dlg.opened; //return dlg.opened;
return !dlg.classList.contains('hide'); return !dlg.classList.contains('hide');
} }
function close(dlg) { export function close(dlg) {
if (isOpened(dlg)) { if (isOpened(dlg)) {
if (isHistoryEnabled(dlg)) { if (isHistoryEnabled(dlg)) {
history.back(); window.history.back();
} else { } else {
closeDialog(dlg); closeDialog(dlg);
} }
@ -225,15 +221,13 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
} }
function closeDialog(dlg) { function closeDialog(dlg) {
if (!dlg.classList.contains('hide')) { if (!dlg.classList.contains('hide')) {
dlg.dispatchEvent(new CustomEvent('closing', { dlg.dispatchEvent(new CustomEvent('closing', {
bubbles: false, bubbles: false,
cancelable: false cancelable: false
})); }));
var onAnimationFinish = function () { const onAnimationFinish = () => {
focusManager.popScope(dlg); focusManager.popScope(dlg);
dlg.classList.add('hide'); dlg.classList.add('hide');
@ -248,8 +242,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
} }
function animateDialogOpen(dlg) { function animateDialogOpen(dlg) {
const onAnimationFinish = () => {
var onAnimationFinish = function () {
focusManager.pushScope(dlg); focusManager.pushScope(dlg);
if (dlg.getAttribute('data-autofocus') === 'true') { if (dlg.getAttribute('data-autofocus') === 'true') {
@ -263,8 +256,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
}; };
if (enableAnimation()) { if (enableAnimation()) {
const onFinish = () => {
var onFinish = function () {
dom.removeEventListener(dlg, dom.whichAnimationEvent(), onFinish, { dom.removeEventListener(dlg, dom.whichAnimationEvent(), onFinish, {
once: true once: true
}); });
@ -280,27 +272,24 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
} }
function animateDialogClose(dlg, onAnimationFinish) { function animateDialogClose(dlg, onAnimationFinish) {
if (enableAnimation()) { if (enableAnimation()) {
let animated = true;
var animated = true;
switch (dlg.animationConfig.exit.name) { switch (dlg.animationConfig.exit.name) {
case 'fadeout': case 'fadeout':
dlg.style.animation = 'fadeout ' + dlg.animationConfig.exit.timing.duration + 'ms ease-out normal both'; dlg.style.animation = `fadeout ${dlg.animationConfig.exit.timing.duration}ms ease-out normal both`;
break; break;
case 'scaledown': case 'scaledown':
dlg.style.animation = 'scaledown ' + dlg.animationConfig.exit.timing.duration + 'ms ease-out normal both'; dlg.style.animation = `scaledown ${dlg.animationConfig.exit.timing.duration}ms ease-out normal both`;
break; break;
case 'slidedown': case 'slidedown':
dlg.style.animation = 'slidedown ' + dlg.animationConfig.exit.timing.duration + 'ms ease-out normal both'; dlg.style.animation = `slidedown ${dlg.animationConfig.exit.timing.duration}ms ease-out normal both`;
break; break;
default: default:
animated = false; animated = false;
break; break;
} }
var onFinish = function () { const onFinish = () => {
dom.removeEventListener(dlg, dom.whichAnimationEvent(), onFinish, { dom.removeEventListener(dlg, dom.whichAnimationEvent(), onFinish, {
once: true once: true
}); });
@ -318,10 +307,9 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
onAnimationFinish(); onAnimationFinish();
} }
var supportsOverscrollBehavior = 'overscroll-behavior-y' in document.body.style; const supportsOverscrollBehavior = 'overscroll-behavior-y' in document.body.style;
function shouldLockDocumentScroll(options) { function shouldLockDocumentScroll(options) {
if (supportsOverscrollBehavior && (options.size || !browser.touch)) { if (supportsOverscrollBehavior && (options.size || !browser.touch)) {
return false; return false;
} }
@ -342,8 +330,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
} }
function removeBackdrop(dlg) { function removeBackdrop(dlg) {
const backdrop = dlg.backdrop;
var backdrop = dlg.backdrop;
if (!backdrop) { if (!backdrop) {
return; return;
@ -351,12 +338,11 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
dlg.backdrop = null; dlg.backdrop = null;
var onAnimationFinish = function () { const onAnimationFinish = () => {
tryRemoveElement(backdrop); tryRemoveElement(backdrop);
}; };
if (enableAnimation()) { if (enableAnimation()) {
backdrop.classList.remove('dialogBackdropOpened'); backdrop.classList.remove('dialogBackdropOpened');
// this is not firing animatonend // this is not firing animatonend
@ -368,20 +354,19 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
} }
function centerFocus(elem, horiz, on) { function centerFocus(elem, horiz, on) {
require(['scrollHelper'], function (scrollHelper) { import('scrollHelper').then((scrollHelper) => {
var fn = on ? 'on' : 'off'; const fn = on ? 'on' : 'off';
scrollHelper.centerFocus[fn](elem, horiz); scrollHelper.centerFocus[fn](elem, horiz);
}); });
} }
function createDialog(options) { export function createDialog(options) {
options = options || {}; options = options || {};
// If there's no native dialog support, use a plain div // If there's no native dialog support, use a plain div
// Also not working well in samsung tizen browser, content inside not clickable // Also not working well in samsung tizen browser, content inside not clickable
// Just go ahead and always use a plain div because we're seeing issues overlaying absoltutely positioned content over a modal dialog // Just go ahead and always use a plain div because we're seeing issues overlaying absoltutely positioned content over a modal dialog
var dlg = document.createElement('div'); const dlg = document.createElement('div');
dlg.classList.add('focuscontainer'); dlg.classList.add('focuscontainer');
dlg.classList.add('hide'); dlg.classList.add('hide');
@ -390,7 +375,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
dlg.setAttribute('data-lockscroll', 'true'); dlg.setAttribute('data-lockscroll', 'true');
} }
if (options.enableHistory !== false && appRouter.enableNativeHistory()) { if (options.enableHistory === true) {
dlg.setAttribute('data-history', 'true'); dlg.setAttribute('data-history', 'true');
} }
@ -406,17 +391,14 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
dlg.setAttribute('data-autofocus', 'true'); dlg.setAttribute('data-autofocus', 'true');
} }
var defaultEntryAnimation; const defaultEntryAnimation = 'scaleup';
var defaultExitAnimation; const defaultExitAnimation = 'scaledown';
const entryAnimation = options.entryAnimation || defaultEntryAnimation;
defaultEntryAnimation = 'scaleup'; const exitAnimation = options.exitAnimation || defaultExitAnimation;
defaultExitAnimation = 'scaledown';
var entryAnimation = options.entryAnimation || defaultEntryAnimation;
var exitAnimation = options.exitAnimation || defaultExitAnimation;
// If it's not fullscreen then lower the default animation speed to make it open really fast // If it's not fullscreen then lower the default animation speed to make it open really fast
var entryAnimationDuration = options.entryAnimationDuration || (options.size !== 'fullscreen' ? 180 : 280); const entryAnimationDuration = options.entryAnimationDuration || (options.size !== 'fullscreen' ? 180 : 280);
var exitAnimationDuration = options.exitAnimationDuration || (options.size !== 'fullscreen' ? 120 : 220); const exitAnimationDuration = options.exitAnimationDuration || (options.size !== 'fullscreen' ? 120 : 220);
dlg.animationConfig = { dlg.animationConfig = {
// scale up // scale up
@ -461,24 +443,22 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
if (options.size) { if (options.size) {
dlg.classList.add('dialog-fixedSize'); dlg.classList.add('dialog-fixedSize');
dlg.classList.add('dialog-' + options.size); dlg.classList.add(`dialog-${options.size}`);
} }
if (enableAnimation()) { if (enableAnimation()) {
switch (dlg.animationConfig.entry.name) { switch (dlg.animationConfig.entry.name) {
case 'fadein': case 'fadein':
dlg.style.animation = 'fadein ' + entryAnimationDuration + 'ms ease-out normal'; dlg.style.animation = `fadein ${entryAnimationDuration}ms ease-out normal`;
break; break;
case 'scaleup': case 'scaleup':
dlg.style.animation = 'scaleup ' + entryAnimationDuration + 'ms ease-out normal both'; dlg.style.animation = `scaleup ${entryAnimationDuration}ms ease-out normal both`;
break; break;
case 'slideup': case 'slideup':
dlg.style.animation = 'slideup ' + entryAnimationDuration + 'ms ease-out normal'; dlg.style.animation = `slideup ${entryAnimationDuration}ms ease-out normal`;
break; break;
case 'slidedown': case 'slidedown':
dlg.style.animation = 'slidedown ' + entryAnimationDuration + 'ms ease-out normal'; dlg.style.animation = `slidedown ${entryAnimationDuration}ms ease-out normal`;
break; break;
default: default:
break; break;
@ -488,12 +468,15 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
return dlg; return dlg;
} }
return { export function setOnOpen(val) {
globalOnOpenCallback = val;
}
/* eslint-enable indent */
export default {
open: open, open: open,
close: close, close: close,
createDialog: createDialog, createDialog: createDialog,
setOnOpen: function (val) { setOnOpen: setOnOpen
globalOnOpenCallback = val; };
}
};
});

View file

@ -1,9 +1,19 @@
define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-input', 'paper-icon-button-light', 'css!./directorybrowser', 'formDialogStyle', 'emby-button'], function(loading, dialogHelper, dom, globalize) { import loading from 'loading';
'use strict'; import dialogHelper from 'dialogHelper';
import dom from 'dom';
import globalize from 'globalize';
import 'listViewStyle';
import 'emby-input';
import 'paper-icon-button-light';
import 'css!./directorybrowser';
import 'formDialogStyle';
import 'emby-button';
/* eslint-disable indent */
function getSystemInfo() { function getSystemInfo() {
return systemInfo ? Promise.resolve(systemInfo) : ApiClient.getPublicSystemInfo().then( return systemInfo ? Promise.resolve(systemInfo) : ApiClient.getPublicSystemInfo().then(
function(info) { info => {
systemInfo = info; systemInfo = info;
return info; return info;
} }
@ -21,9 +31,9 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
loading.show(); loading.show();
var promises = []; const promises = [];
if ('Network' === path) { if (path === 'Network') {
promises.push(ApiClient.getNetworkDevices()); promises.push(ApiClient.getNetworkDevices());
} else { } else {
if (path) { if (path) {
@ -35,10 +45,10 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
} }
Promise.all(promises).then( Promise.all(promises).then(
function(responses) { responses => {
var folders = responses[0]; const folders = responses[0];
var parentPath = responses[1] || ''; const parentPath = responses[1] || '';
var html = ''; let html = '';
page.querySelector('.results').scrollTop = 0; page.querySelector('.results').scrollTop = 0;
page.querySelector('#txtDirectoryPickerPath').value = path || ''; page.querySelector('#txtDirectoryPickerPath').value = path || '';
@ -46,9 +56,9 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
if (path) { if (path) {
html += getItem('lnkPath lnkDirectory', '', parentPath, '...'); html += getItem('lnkPath lnkDirectory', '', parentPath, '...');
} }
for (var i = 0, length = folders.length; i < length; i++) { for (let i = 0, length = folders.length; i < length; i++) {
var folder = folders[i]; const folder = folders[i];
var cssClass = 'File' === folder.Type ? 'lnkPath lnkFile' : 'lnkPath lnkDirectory'; const cssClass = folder.Type === 'File' ? 'lnkPath lnkFile' : 'lnkPath lnkDirectory';
html += getItem(cssClass, folder.Type, folder.Path, folder.Name); html += getItem(cssClass, folder.Type, folder.Path, folder.Name);
} }
@ -58,7 +68,7 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
page.querySelector('.results').innerHTML = html; page.querySelector('.results').innerHTML = html;
loading.hide(); loading.hide();
}, function() { }, () => {
if (updatePathOnError) { if (updatePathOnError) {
page.querySelector('#txtDirectoryPickerPath').value = ''; page.querySelector('#txtDirectoryPickerPath').value = '';
page.querySelector('.results').innerHTML = ''; page.querySelector('.results').innerHTML = '';
@ -69,8 +79,8 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
} }
function getItem(cssClass, type, path, name) { function getItem(cssClass, type, path, name) {
var html = ''; let html = '';
html += '<div class="listItem listItem-border ' + cssClass + '" data-type="' + type + '" data-path="' + path + '">'; html += `<div class="listItem listItem-border ${cssClass}" data-type="${type}" data-path="${path}">`;
html += '<div class="listItemBody" style="padding-left:0;padding-top:.5em;padding-bottom:.5em;">'; html += '<div class="listItemBody" style="padding-left:0;padding-top:.5em;padding-bottom:.5em;">';
html += '<div class="listItemBodyText">'; html += '<div class="listItemBodyText">';
html += name; html += name;
@ -82,19 +92,19 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
} }
function getEditorHtml(options, systemInfo) { function getEditorHtml(options, systemInfo) {
var html = ''; let html = '';
html += '<div class="formDialogContent scrollY">'; html += '<div class="formDialogContent scrollY">';
html += '<div class="dialogContentInner dialog-content-centered" style="padding-top:2em;">'; html += '<div class="dialogContentInner dialog-content-centered" style="padding-top:2em;">';
if (!options.pathReadOnly) { if (!options.pathReadOnly) {
var instruction = options.instruction ? options.instruction + '<br/><br/>' : ''; const instruction = options.instruction ? `${options.instruction}<br/><br/>` : '';
html += '<div class="infoBanner" style="margin-bottom:1.5em;">'; html += '<div class="infoBanner" style="margin-bottom:1.5em;">';
html += instruction; html += instruction;
if ('bsd' === systemInfo.OperatingSystem.toLowerCase()) { if (systemInfo.OperatingSystem.toLowerCase() === 'bsd') {
html += '<br/>'; html += '<br/>';
html += '<br/>'; html += '<br/>';
html += globalize.translate('MessageDirectoryPickerBSDInstruction'); html += globalize.translate('MessageDirectoryPickerBSDInstruction');
html += '<br/>'; html += '<br/>';
} else if ('linux' === systemInfo.OperatingSystem.toLowerCase()) { } else if (systemInfo.OperatingSystem.toLowerCase() === 'linux') {
html += '<br/>'; html += '<br/>';
html += '<br/>'; html += '<br/>';
html += globalize.translate('MessageDirectoryPickerLinuxInstruction'); html += globalize.translate('MessageDirectoryPickerLinuxInstruction');
@ -105,17 +115,17 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
html += '<form style="margin:auto;">'; html += '<form style="margin:auto;">';
html += '<div class="inputContainer" style="display: flex; align-items: center;">'; html += '<div class="inputContainer" style="display: flex; align-items: center;">';
html += '<div style="flex-grow:1;">'; html += '<div style="flex-grow:1;">';
var labelKey; let labelKey;
if (options.includeFiles !== true) { if (options.includeFiles !== true) {
labelKey = 'LabelFolder'; labelKey = 'LabelFolder';
} else { } else {
labelKey = 'LabelPath'; labelKey = 'LabelPath';
} }
var readOnlyAttribute = options.pathReadOnly ? ' readonly' : ''; const readOnlyAttribute = options.pathReadOnly ? ' readonly' : '';
html += '<input is="emby-input" id="txtDirectoryPickerPath" type="text" required="required" ' + readOnlyAttribute + ' label="' + globalize.translate(labelKey) + '"/>'; html += `<input is="emby-input" id="txtDirectoryPickerPath" type="text" required="required" ${readOnlyAttribute} label="${globalize.translate(labelKey)}"/>`;
html += '</div>'; html += '</div>';
if (!readOnlyAttribute) { if (!readOnlyAttribute) {
html += '<button type="button" is="paper-icon-button-light" class="btnRefreshDirectories emby-input-iconbutton" title="' + globalize.translate('ButtonRefresh') + '"><span class="material-icons search"></span></button>'; html += `<button type="button" is="paper-icon-button-light" class="btnRefreshDirectories emby-input-iconbutton" title="${globalize.translate('Refresh')}"><span class="material-icons search"></span></button>`;
} }
html += '</div>'; html += '</div>';
if (!readOnlyAttribute) { if (!readOnlyAttribute) {
@ -123,14 +133,14 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
} }
if (options.enableNetworkSharePath) { if (options.enableNetworkSharePath) {
html += '<div class="inputContainer" style="margin-top:2em;">'; html += '<div class="inputContainer" style="margin-top:2em;">';
html += '<input is="emby-input" id="txtNetworkPath" type="text" label="' + globalize.translate('LabelOptionalNetworkPath') + '"/>'; html += `<input is="emby-input" id="txtNetworkPath" type="text" label="${globalize.translate('LabelOptionalNetworkPath')}"/>`;
html += '<div class="fieldDescription">'; html += '<div class="fieldDescription">';
html += globalize.translate('LabelOptionalNetworkPathHelp', '<b>\\\\server</b>', '<b>\\\\192.168.1.101</b>'); html += globalize.translate('LabelOptionalNetworkPathHelp', '<b>\\\\server</b>', '<b>\\\\192.168.1.101</b>');
html += '</div>'; html += '</div>';
html += '</div>'; html += '</div>';
} }
html += '<div class="formDialogFooter">'; html += '<div class="formDialogFooter">';
html += '<button is="emby-button" type="submit" class="raised button-submit block formDialogFooterItem">' + globalize.translate('ButtonOk') + '</button>'; html += `<button is="emby-button" type="submit" class="raised button-submit block formDialogFooterItem">${globalize.translate('ButtonOk')}</button>`;
html += '</div>'; html += '</div>';
html += '</form>'; html += '</form>';
html += '</div>'; html += '</div>';
@ -147,7 +157,7 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
} }
function alertTextWithOptions(options) { function alertTextWithOptions(options) {
require(['alert'], function(alert) { import('alert').then(({default: alert}) => {
alert(options); alert(options);
}); });
} }
@ -156,11 +166,12 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
return apiClient.ajax({ return apiClient.ajax({
type: 'POST', type: 'POST',
url: apiClient.getUrl('Environment/ValidatePath'), url: apiClient.getUrl('Environment/ValidatePath'),
data: { data: JSON.stringify({
ValidateWriteable: validateWriteable, ValidateWriteable: validateWriteable,
Path: path Path: path
} }),
}).catch(function(response) { contentType: 'application/json'
}).catch(response => {
if (response) { if (response) {
if (response.status === 404) { if (response.status === 404) {
alertText(globalize.translate('PathNotFound')); alertText(globalize.translate('PathNotFound'));
@ -180,10 +191,10 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
} }
function initEditor(content, options, fileOptions) { function initEditor(content, options, fileOptions) {
content.addEventListener('click', function(e) { content.addEventListener('click', e => {
var lnkPath = dom.parentWithClass(e.target, 'lnkPath'); const lnkPath = dom.parentWithClass(e.target, 'lnkPath');
if (lnkPath) { if (lnkPath) {
var path = lnkPath.getAttribute('data-path'); const path = lnkPath.getAttribute('data-path');
if (lnkPath.classList.contains('lnkFile')) { if (lnkPath.classList.contains('lnkFile')) {
content.querySelector('#txtDirectoryPickerPath').value = path; content.querySelector('#txtDirectoryPickerPath').value = path;
} else { } else {
@ -192,25 +203,25 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
} }
}); });
content.addEventListener('click', function(e) { content.addEventListener('click', e => {
if (dom.parentWithClass(e.target, 'btnRefreshDirectories')) { if (dom.parentWithClass(e.target, 'btnRefreshDirectories')) {
var path = content.querySelector('#txtDirectoryPickerPath').value; const path = content.querySelector('#txtDirectoryPickerPath').value;
refreshDirectoryBrowser(content, path, fileOptions); refreshDirectoryBrowser(content, path, fileOptions);
} }
}); });
content.addEventListener('change', function(e) { content.addEventListener('change', e => {
var txtDirectoryPickerPath = dom.parentWithTag(e.target, 'INPUT'); const txtDirectoryPickerPath = dom.parentWithTag(e.target, 'INPUT');
if (txtDirectoryPickerPath && 'txtDirectoryPickerPath' === txtDirectoryPickerPath.id) { if (txtDirectoryPickerPath && txtDirectoryPickerPath.id === 'txtDirectoryPickerPath') {
refreshDirectoryBrowser(content, txtDirectoryPickerPath.value, fileOptions); refreshDirectoryBrowser(content, txtDirectoryPickerPath.value, fileOptions);
} }
}); });
content.querySelector('form').addEventListener('submit', function(e) { content.querySelector('form').addEventListener('submit', function(e) {
if (options.callback) { if (options.callback) {
var networkSharePath = this.querySelector('#txtNetworkPath'); let networkSharePath = this.querySelector('#txtNetworkPath');
networkSharePath = networkSharePath ? networkSharePath.value : null; networkSharePath = networkSharePath ? networkSharePath.value : null;
var path = this.querySelector('#txtDirectoryPickerPath').value; const path = this.querySelector('#txtDirectoryPickerPath').value;
validatePath(path, options.validateWriteable, ApiClient).then(options.callback(path, networkSharePath)); validatePath(path, options.validateWriteable, ApiClient).then(options.callback(path, networkSharePath));
} }
e.preventDefault(); e.preventDefault();
@ -224,21 +235,21 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
return Promise.resolve(options.path); return Promise.resolve(options.path);
} else { } else {
return ApiClient.getJSON(ApiClient.getUrl('Environment/DefaultDirectoryBrowser')).then( return ApiClient.getJSON(ApiClient.getUrl('Environment/DefaultDirectoryBrowser')).then(
function(result) { result => {
return result.Path || ''; return result.Path || '';
}, function() { }, () => {
return ''; return '';
} }
); );
} }
} }
function directoryBrowser() { class directoryBrowser {
var currentDialog; constructor() {
var self = this; let currentDialog;
self.show = function(options) { this.show = options => {
options = options || {}; options = options || {};
var fileOptions = { const fileOptions = {
includeDirectories: true includeDirectories: true
}; };
if (options.includeDirectories != null) { if (options.includeDirectories != null) {
@ -248,10 +259,10 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
fileOptions.includeFiles = options.includeFiles; fileOptions.includeFiles = options.includeFiles;
} }
Promise.all([getSystemInfo(), getDefaultPath(options)]).then( Promise.all([getSystemInfo(), getDefaultPath(options)]).then(
function(responses) { responses => {
var systemInfo = responses[0]; const systemInfo = responses[0];
var initialPath = responses[1]; const initialPath = responses[1];
var dlg = dialogHelper.createDialog({ const dlg = dialogHelper.createDialog({
size: 'small', size: 'small',
removeOnClose: true, removeOnClose: true,
scrollY: false scrollY: false
@ -261,7 +272,7 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
dlg.classList.add('directoryPicker'); dlg.classList.add('directoryPicker');
dlg.classList.add('formDialog'); dlg.classList.add('formDialog');
var html = ''; let html = '';
html += '<div class="formDialogHeader">'; html += '<div class="formDialogHeader">';
html += '<button is="paper-icon-button-light" class="btnCloseDialog autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>'; html += '<button is="paper-icon-button-light" class="btnCloseDialog autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
html += '<h3 class="formDialogHeaderTitle">'; html += '<h3 class="formDialogHeaderTitle">';
@ -273,12 +284,12 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
initEditor(dlg, options, fileOptions); initEditor(dlg, options, fileOptions);
dlg.addEventListener('close', onDialogClosed); dlg.addEventListener('close', onDialogClosed);
dialogHelper.open(dlg); dialogHelper.open(dlg);
dlg.querySelector('.btnCloseDialog').addEventListener('click', function() { dlg.querySelector('.btnCloseDialog').addEventListener('click', () => {
dialogHelper.close(dlg); dialogHelper.close(dlg);
}); });
currentDialog = dlg; currentDialog = dlg;
dlg.querySelector('#txtDirectoryPickerPath').value = initialPath; dlg.querySelector('#txtDirectoryPickerPath').value = initialPath;
var txtNetworkPath = dlg.querySelector('#txtNetworkPath'); const txtNetworkPath = dlg.querySelector('#txtNetworkPath');
if (txtNetworkPath) { if (txtNetworkPath) {
txtNetworkPath.value = options.networkSharePath || ''; txtNetworkPath.value = options.networkSharePath || '';
} }
@ -288,13 +299,15 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
} }
); );
}; };
self.close = function() { this.close = () => {
if (currentDialog) { if (currentDialog) {
dialogHelper.close(currentDialog); dialogHelper.close(currentDialog);
} }
}; };
} }
}
var systemInfo; let systemInfo;
return directoryBrowser;
}); /* eslint-enable indent */
export default directoryBrowser;

View file

@ -1,22 +1,40 @@
define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', 'apphost', 'focusManager', 'datetime', 'globalize', 'loading', 'connectionManager', 'skinManager', 'dom', 'events', 'emby-select', 'emby-checkbox', 'emby-button'], function (require, browser, layoutManager, appSettings, pluginManager, appHost, focusManager, datetime, globalize, loading, connectionManager, skinManager, dom, events) { import browser from 'browser';
'use strict'; import layoutManager from 'layoutManager';
import pluginManager from 'pluginManager';
import appHost from 'apphost';
import focusManager from 'focusManager';
import datetime from 'datetime';
import globalize from 'globalize';
import loading from 'loading';
import skinManager from 'skinManager';
import events from 'events';
import 'emby-select';
import 'emby-checkbox';
import 'emby-button';
function fillThemes(select, isDashboard) { /* eslint-disable indent */
select.innerHTML = skinManager.getThemes().map(function (t) {
var value = t.id;
if (t.isDefault && !isDashboard) {
value = '';
} else if (t.isDefaultServerDashboard && isDashboard) {
value = '';
}
return '<option value="' + value + '">' + t.name + '</option>'; function fillThemes(context, userSettings) {
const select = context.querySelector('#selectTheme');
skinManager.getThemes().then(themes => {
select.innerHTML = themes.map(t => {
return `<option value="${t.id}">${t.name}</option>`;
}).join(''); }).join('');
// get default theme
var defaultTheme = themes.find(theme => {
return theme.default;
});
// set the current theme
select.value = userSettings.theme() || defaultTheme.id;
});
} }
function loadScreensavers(context, userSettings) { function loadScreensavers(context, userSettings) {
var selectScreensaver = context.querySelector('.selectScreensaver'); const selectScreensaver = context.querySelector('.selectScreensaver');
var options = pluginManager.ofType('screensaver').map(function (plugin) { const options = pluginManager.ofType('screensaver').map(plugin => {
return { return {
name: plugin.name, name: plugin.name,
value: plugin.id value: plugin.id
@ -28,9 +46,10 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
value: 'none' value: 'none'
}); });
selectScreensaver.innerHTML = options.map(function (o) { selectScreensaver.innerHTML = options.map(o => {
return '<option value="' + o.value + '">' + o.name + '</option>'; return `<option value="${o.value}">${o.name}</option>`;
}).join(''); }).join('');
selectScreensaver.value = userSettings.screensaver(); selectScreensaver.value = userSettings.screensaver();
if (!selectScreensaver.value) { if (!selectScreensaver.value) {
@ -39,61 +58,7 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
} }
} }
function loadSoundEffects(context, userSettings) { function showOrHideMissingEpisodesField(context) {
var selectSoundEffects = context.querySelector('.selectSoundEffects');
var options = pluginManager.ofType('soundeffects').map(function (plugin) {
return {
name: plugin.name,
value: plugin.id
};
});
options.unshift({
name: globalize.translate('None'),
value: 'none'
});
selectSoundEffects.innerHTML = options.map(function (o) {
return '<option value="' + o.value + '">' + o.name + '</option>';
}).join('');
selectSoundEffects.value = userSettings.soundEffects();
if (!selectSoundEffects.value) {
// TODO: set the default instead of none
selectSoundEffects.value = 'none';
}
}
function loadSkins(context, userSettings) {
var selectSkin = context.querySelector('.selectSkin');
var options = pluginManager.ofType('skin').map(function (plugin) {
return {
name: plugin.name,
value: plugin.id
};
});
selectSkin.innerHTML = options.map(function (o) {
return '<option value="' + o.value + '">' + o.name + '</option>';
}).join('');
selectSkin.value = userSettings.skin();
if (!selectSkin.value && options.length) {
selectSkin.value = options[0].value;
}
if (options.length > 1 && appHost.supports('skins')) {
context.querySelector('.selectSkinContainer').classList.remove('hide');
} else {
context.querySelector('.selectSkinContainer').classList.add('hide');
}
}
function showOrHideMissingEpisodesField(context, user, apiClient) {
if (browser.tizen || browser.web0s) { if (browser.tizen || browser.web0s) {
context.querySelector('.fldDisplayMissingEpisodes').classList.add('hide'); context.querySelector('.fldDisplayMissingEpisodes').classList.add('hide');
return; return;
@ -102,17 +67,7 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
context.querySelector('.fldDisplayMissingEpisodes').classList.remove('hide'); context.querySelector('.fldDisplayMissingEpisodes').classList.remove('hide');
} }
function loadForm(context, user, userSettings, apiClient) { function loadForm(context, user, userSettings) {
var loggedInUserId = apiClient.getCurrentUserId();
var userId = user.Id;
if (user.Policy.IsAdministrator) {
context.querySelector('.selectDashboardThemeContainer').classList.remove('hide');
} else {
context.querySelector('.selectDashboardThemeContainer').classList.add('hide');
}
if (appHost.supports('displaylanguage')) { if (appHost.supports('displaylanguage')) {
context.querySelector('.languageSection').classList.remove('hide'); context.querySelector('.languageSection').classList.remove('hide');
} else { } else {
@ -131,18 +86,6 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
context.querySelector('.learnHowToContributeContainer').classList.add('hide'); context.querySelector('.learnHowToContributeContainer').classList.add('hide');
} }
if (appHost.supports('runatstartup')) {
context.querySelector('.fldAutorun').classList.remove('hide');
} else {
context.querySelector('.fldAutorun').classList.add('hide');
}
if (appHost.supports('soundeffects')) {
context.querySelector('.fldSoundEffects').classList.remove('hide');
} else {
context.querySelector('.fldSoundEffects').classList.add('hide');
}
if (appHost.supports('screensaver')) { if (appHost.supports('screensaver')) {
context.querySelector('.selectScreensaverContainer').classList.remove('hide'); context.querySelector('.selectScreensaverContainer').classList.remove('hide');
} else { } else {
@ -165,16 +108,8 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
context.querySelector('.fldThemeVideo').classList.add('hide'); context.querySelector('.fldThemeVideo').classList.add('hide');
} }
context.querySelector('.chkRunAtStartup').checked = appSettings.runAtStartup(); fillThemes(context, userSettings);
var selectTheme = context.querySelector('#selectTheme');
var selectDashboardTheme = context.querySelector('#selectDashboardTheme');
fillThemes(selectTheme);
fillThemes(selectDashboardTheme, true);
loadScreensavers(context, userSettings); loadScreensavers(context, userSettings);
loadSoundEffects(context, userSettings);
loadSkins(context, userSettings);
context.querySelector('.chkDisplayMissingEpisodes').checked = user.Configuration.DisplayMissingEpisodes || false; context.querySelector('.chkDisplayMissingEpisodes').checked = user.Configuration.DisplayMissingEpisodes || false;
@ -190,20 +125,14 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
context.querySelector('#txtLibraryPageSize').value = userSettings.libraryPageSize(); context.querySelector('#txtLibraryPageSize').value = userSettings.libraryPageSize();
selectDashboardTheme.value = userSettings.dashboardTheme() || '';
selectTheme.value = userSettings.theme() || '';
context.querySelector('.selectLayout').value = layoutManager.getSavedLayout() || ''; context.querySelector('.selectLayout').value = layoutManager.getSavedLayout() || '';
showOrHideMissingEpisodesField(context, user, apiClient); showOrHideMissingEpisodesField(context);
loading.hide(); loading.hide();
} }
function saveUser(context, user, userSettingsInstance, apiClient) { function saveUser(context, user, userSettingsInstance, apiClient) {
appSettings.runAtStartup(context.querySelector('.chkRunAtStartup').checked);
user.Configuration.DisplayMissingEpisodes = context.querySelector('.chkDisplayMissingEpisodes').checked; user.Configuration.DisplayMissingEpisodes = context.querySelector('.chkDisplayMissingEpisodes').checked;
if (appHost.supports('displaylanguage')) { if (appHost.supports('displaylanguage')) {
@ -214,15 +143,11 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
userSettingsInstance.enableThemeSongs(context.querySelector('#chkThemeSong').checked); userSettingsInstance.enableThemeSongs(context.querySelector('#chkThemeSong').checked);
userSettingsInstance.enableThemeVideos(context.querySelector('#chkThemeVideo').checked); userSettingsInstance.enableThemeVideos(context.querySelector('#chkThemeVideo').checked);
userSettingsInstance.dashboardTheme(context.querySelector('#selectDashboardTheme').value);
userSettingsInstance.theme(context.querySelector('#selectTheme').value); userSettingsInstance.theme(context.querySelector('#selectTheme').value);
userSettingsInstance.soundEffects(context.querySelector('.selectSoundEffects').value);
userSettingsInstance.screensaver(context.querySelector('.selectScreensaver').value); userSettingsInstance.screensaver(context.querySelector('.selectScreensaver').value);
userSettingsInstance.libraryPageSize(context.querySelector('#txtLibraryPageSize').value); userSettingsInstance.libraryPageSize(context.querySelector('#txtLibraryPageSize').value);
userSettingsInstance.skin(context.querySelector('.selectSkin').value);
userSettingsInstance.enableFastFadein(context.querySelector('#chkFadein').checked); userSettingsInstance.enableFastFadein(context.querySelector('#chkFadein').checked);
userSettingsInstance.enableBlurhash(context.querySelector('#chkBlurhash').checked); userSettingsInstance.enableBlurhash(context.querySelector('#chkBlurhash').checked);
userSettingsInstance.enableBackdrops(context.querySelector('#chkBackdrops').checked); userSettingsInstance.enableBackdrops(context.querySelector('#chkBackdrops').checked);
@ -239,29 +164,29 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
function save(instance, context, userId, userSettings, apiClient, enableSaveConfirmation) { function save(instance, context, userId, userSettings, apiClient, enableSaveConfirmation) {
loading.show(); loading.show();
apiClient.getUser(userId).then(function (user) { apiClient.getUser(userId).then(user => {
saveUser(context, user, userSettings, apiClient).then(function () { saveUser(context, user, userSettings, apiClient).then(() => {
loading.hide(); loading.hide();
if (enableSaveConfirmation) { if (enableSaveConfirmation) {
require(['toast'], function (toast) { import('toast').then(({default: toast}) => {
toast(globalize.translate('SettingsSaved')); toast(globalize.translate('SettingsSaved'));
}); });
} }
events.trigger(instance, 'saved'); events.trigger(instance, 'saved');
}, function () { }, () => {
loading.hide(); loading.hide();
}); });
}); });
} }
function onSubmit(e) { function onSubmit(e) {
var self = this; const self = this;
var apiClient = connectionManager.getApiClient(self.options.serverId); const apiClient = window.connectionManager.getApiClient(self.options.serverId);
var userId = self.options.userId; const userId = self.options.userId;
var userSettings = self.options.userSettings; const userSettings = self.options.userSettings;
userSettings.setUserInfo(userId, apiClient).then(function () { userSettings.setUserInfo(userId, apiClient).then(() => {
var enableSaveConfirmation = self.options.enableSaveConfirmation; const enableSaveConfirmation = self.options.enableSaveConfirmation;
save(self, self.options.element, userId, userSettings, apiClient, enableSaveConfirmation); save(self, self.options.element, userId, userSettings, apiClient, enableSaveConfirmation);
}); });
@ -272,50 +197,51 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
return false; return false;
} }
function embed(options, self) { async function embed(options, self) {
require(['text!./displaySettings.template.html'], function (template) { const { default: template } = await import('text!./displaySettings.template.html');
options.element.innerHTML = globalize.translateDocument(template, 'core'); options.element.innerHTML = globalize.translateHtml(template, 'core');
options.element.querySelector('form').addEventListener('submit', onSubmit.bind(self)); options.element.querySelector('form').addEventListener('submit', onSubmit.bind(self));
if (options.enableSaveButton) { if (options.enableSaveButton) {
options.element.querySelector('.btnSave').classList.remove('hide'); options.element.querySelector('.btnSave').classList.remove('hide');
} }
self.loadData(options.autoFocus); self.loadData(options.autoFocus);
});
} }
function DisplaySettings(options) { class DisplaySettings {
constructor(options) {
this.options = options; this.options = options;
embed(options, this); embed(options, this);
} }
DisplaySettings.prototype.loadData = function (autoFocus) { loadData(autoFocus) {
var self = this; const self = this;
var context = self.options.element; const context = self.options.element;
loading.show(); loading.show();
var userId = self.options.userId; const userId = self.options.userId;
var apiClient = connectionManager.getApiClient(self.options.serverId); const apiClient = window.connectionManager.getApiClient(self.options.serverId);
var userSettings = self.options.userSettings; const userSettings = self.options.userSettings;
return apiClient.getUser(userId).then(function (user) { return apiClient.getUser(userId).then(user => {
return userSettings.setUserInfo(userId, apiClient).then(function () { return userSettings.setUserInfo(userId, apiClient).then(() => {
self.dataLoaded = true; self.dataLoaded = true;
loadForm(context, user, userSettings, apiClient); loadForm(context, user, userSettings);
if (autoFocus) { if (autoFocus) {
focusManager.autoFocus(context); focusManager.autoFocus(context);
} }
}); });
}); });
}; }
DisplaySettings.prototype.submit = function () { submit() {
onSubmit.call(this); onSubmit.call(this);
}; }
DisplaySettings.prototype.destroy = function () { destroy() {
this.options = null; this.options = null;
}; }
}
return DisplaySettings; /* eslint-enable indent */
}); export default DisplaySettings;

View file

@ -1,5 +1,4 @@
<form style="margin: 0 auto;"> <form style="margin: 0 auto;">
<h2 class="sectionTitle"> <h2 class="sectionTitle">
${Display} ${Display}
</h2> </h2>
@ -123,26 +122,14 @@
<div class="fieldDescription">${LabelPleaseRestart}</div> <div class="fieldDescription">${LabelPleaseRestart}</div>
</div> </div>
<div class="selectContainer hide selectSkinContainer">
<select is="emby-select" class="selectSkin" label="${LabelSkin}"></select>
</div>
<div class="selectContainer"> <div class="selectContainer">
<select id="selectTheme" is="emby-select" label="${LabelTheme}"></select> <select id="selectTheme" is="emby-select" label="${LabelTheme}"></select>
</div> </div>
<div class="selectContainer selectDashboardThemeContainer hide">
<select id="selectDashboardTheme" is="emby-select" label="${LabelDashboardTheme}"></select>
</div>
<div class="selectContainer hide selectScreensaverContainer"> <div class="selectContainer hide selectScreensaverContainer">
<select is="emby-select" class="selectScreensaver" label="${LabelScreensaver}"></select> <select is="emby-select" class="selectScreensaver" label="${LabelScreensaver}"></select>
</div> </div>
<div class="selectContainer fldSoundEffects hide">
<select is="emby-select" class="selectSoundEffects" label="${LabelSoundEffects}"></select>
</div>
<div class="inputContainer inputContainer-withDescription"> <div class="inputContainer inputContainer-withDescription">
<input is="emby-input" type="number" id="txtLibraryPageSize" pattern="[0-9]*" required="required" min="0" max="1000" step="1" label="${LabelLibraryPageSize}" /> <input is="emby-input" type="number" id="txtLibraryPageSize" pattern="[0-9]*" required="required" min="0" max="1000" step="1" label="${LabelLibraryPageSize}" />
<div class="fieldDescription">${LabelLibraryPageSizeHelp}</div> <div class="fieldDescription">${LabelLibraryPageSizeHelp}</div>
@ -159,9 +146,9 @@
<div class="checkboxContainer checkboxContainer-withDescription"> <div class="checkboxContainer checkboxContainer-withDescription">
<label> <label>
<input type="checkbox" is="emby-checkbox" id="chkBlurhash" /> <input type="checkbox" is="emby-checkbox" id="chkBlurhash" />
<span>${EnableBlurhash}</span> <span>${EnableBlurHash}</span>
</label> </label>
<div class="fieldDescription checkboxFieldDescription">${EnableBlurhashHelp}</div> <div class="fieldDescription checkboxFieldDescription">${EnableBlurHashHelp}</div>
</div> </div>
<div class="checkboxContainer checkboxContainer-withDescription"> <div class="checkboxContainer checkboxContainer-withDescription">
@ -175,7 +162,7 @@
<div class="checkboxContainer checkboxContainer-withDescription fldBackdrops hide"> <div class="checkboxContainer checkboxContainer-withDescription fldBackdrops hide">
<label> <label>
<input type="checkbox" is="emby-checkbox" id="chkBackdrops" /> <input type="checkbox" is="emby-checkbox" id="chkBackdrops" />
<span>${EnableBackdrops}</span> <span>${Backdrops}</span>
</label> </label>
<div class="fieldDescription checkboxFieldDescription">${EnableBackdropsHelp}</div> <div class="fieldDescription checkboxFieldDescription">${EnableBackdropsHelp}</div>
</div> </div>
@ -183,7 +170,7 @@
<div class="checkboxContainer checkboxContainer-withDescription fldThemeSong hide"> <div class="checkboxContainer checkboxContainer-withDescription fldThemeSong hide">
<label> <label>
<input type="checkbox" is="emby-checkbox" id="chkThemeSong" /> <input type="checkbox" is="emby-checkbox" id="chkThemeSong" />
<span>${EnableThemeSongs}</span> <span>${ThemeSongs}</span>
</label> </label>
<div class="fieldDescription checkboxFieldDescription">${EnableThemeSongsHelp}</div> <div class="fieldDescription checkboxFieldDescription">${EnableThemeSongsHelp}</div>
</div> </div>
@ -191,18 +178,11 @@
<div class="checkboxContainer checkboxContainer-withDescription fldThemeVideo hide"> <div class="checkboxContainer checkboxContainer-withDescription fldThemeVideo hide">
<label> <label>
<input type="checkbox" is="emby-checkbox" id="chkThemeVideo" /> <input type="checkbox" is="emby-checkbox" id="chkThemeVideo" />
<span>${EnableThemeVideos}</span> <span>${ThemeVideos}</span>
</label> </label>
<div class="fieldDescription checkboxFieldDescription">${EnableThemeVideosHelp}</div> <div class="fieldDescription checkboxFieldDescription">${EnableThemeVideosHelp}</div>
</div> </div>
<div class="checkboxContainer hide fldAutorun">
<label>
<input type="checkbox" is="emby-checkbox" class="chkRunAtStartup" />
<span>${RunAtStartup}</span>
</label>
</div>
<div class="checkboxContainer checkboxContainer-withDescription fldDisplayMissingEpisodes hide"> <div class="checkboxContainer checkboxContainer-withDescription fldDisplayMissingEpisodes hide">
<label> <label>
<input type="checkbox" is="emby-checkbox" class="chkDisplayMissingEpisodes" /> <input type="checkbox" is="emby-checkbox" class="chkDisplayMissingEpisodes" />

View file

@ -1,5 +1,14 @@
define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoader', 'globalize', 'layoutManager', 'scrollStyles', 'emby-itemscontainer'], function (loading, libraryBrowser, cardBuilder, dom, appHost, imageLoader, globalize, layoutManager) { import loading from 'loading';
'use strict'; import cardBuilder from 'cardBuilder';
import dom from 'dom';
import appHost from 'apphost';
import imageLoader from 'imageLoader';
import globalize from 'globalize';
import layoutManager from 'layoutManager';
import 'scrollStyles';
import 'emby-itemscontainer';
/* eslint-disable indent */
function enableScrollX() { function enableScrollX() {
return !layoutManager.desktop; return !layoutManager.desktop;
@ -19,21 +28,21 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
function getSections() { function getSections() {
return [{ return [{
name: 'HeaderFavoriteMovies', name: 'Movies',
types: 'Movie', types: 'Movie',
id: 'favoriteMovies', id: 'favoriteMovies',
shape: getPosterShape(), shape: getPosterShape(),
showTitle: false, showTitle: false,
overlayPlayButton: true overlayPlayButton: true
}, { }, {
name: 'HeaderFavoriteShows', name: 'Shows',
types: 'Series', types: 'Series',
id: 'favoriteShows', id: 'favoriteShows',
shape: getPosterShape(), shape: getPosterShape(),
showTitle: false, showTitle: false,
overlayPlayButton: true overlayPlayButton: true
}, { }, {
name: 'HeaderFavoriteEpisodes', name: 'Episodes',
types: 'Episode', types: 'Episode',
id: 'favoriteEpisode', id: 'favoriteEpisode',
shape: getThumbShape(), shape: getThumbShape(),
@ -44,7 +53,7 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
overlayText: false, overlayText: false,
centerText: true centerText: true
}, { }, {
name: 'HeaderFavoriteVideos', name: 'Videos',
types: 'Video,MusicVideo', types: 'Video,MusicVideo',
id: 'favoriteVideos', id: 'favoriteVideos',
shape: getThumbShape(), shape: getThumbShape(),
@ -54,7 +63,7 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
overlayText: false, overlayText: false,
centerText: true centerText: true
}, { }, {
name: 'HeaderFavoriteArtists', name: 'Artists',
types: 'MusicArtist', types: 'MusicArtist',
id: 'favoriteArtists', id: 'favoriteArtists',
shape: getSquareShape(), shape: getSquareShape(),
@ -66,7 +75,7 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
overlayPlayButton: true, overlayPlayButton: true,
coverImage: true coverImage: true
}, { }, {
name: 'HeaderFavoriteAlbums', name: 'Albums',
types: 'MusicAlbum', types: 'MusicAlbum',
id: 'favoriteAlbums', id: 'favoriteAlbums',
shape: getSquareShape(), shape: getSquareShape(),
@ -78,7 +87,7 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
overlayPlayButton: true, overlayPlayButton: true,
coverImage: true coverImage: true
}, { }, {
name: 'HeaderFavoriteSongs', name: 'Songs',
types: 'Audio', types: 'Audio',
id: 'favoriteSongs', id: 'favoriteSongs',
shape: getSquareShape(), shape: getSquareShape(),
@ -94,8 +103,8 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
} }
function loadSection(elem, userId, topParentId, section, isSingleSection) { function loadSection(elem, userId, topParentId, section, isSingleSection) {
var screenWidth = dom.getWindowSize().innerWidth; const screenWidth = dom.getWindowSize().innerWidth;
var options = { const options = {
SortBy: 'SortName', SortBy: 'SortName',
SortOrder: 'Ascending', SortOrder: 'Ascending',
Filters: 'IsFavorite', Filters: 'IsFavorite',
@ -118,9 +127,9 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
} }
} }
var promise; let promise;
if ('MusicArtist' === section.types) { if (section.types === 'MusicArtist') {
promise = ApiClient.getArtists(userId, options); promise = ApiClient.getArtists(userId, options);
} else { } else {
options.IncludeItemTypes = section.types; options.IncludeItemTypes = section.types;
@ -128,7 +137,7 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
} }
return promise.then(function (result) { return promise.then(function (result) {
var html = ''; let html = '';
if (result.Items.length) { if (result.Items.length) {
if (html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">', !layoutManager.tv && options.Limit && result.Items.length >= options.Limit) { if (html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">', !layoutManager.tv && options.Limit && result.Items.length >= options.Limit) {
@ -144,7 +153,7 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
html += '</div>'; html += '</div>';
if (enableScrollX()) { if (enableScrollX()) {
var scrollXClass = 'scrollX hiddenScrollX'; let scrollXClass = 'scrollX hiddenScrollX';
if (layoutManager.tv) { if (layoutManager.tv) {
scrollXClass += ' smoothScrollX'; scrollXClass += ' smoothScrollX';
} }
@ -154,14 +163,13 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
html += '<div is="emby-itemscontainer" class="itemsContainer vertical-wrap padded-left padded-right">'; html += '<div is="emby-itemscontainer" class="itemsContainer vertical-wrap padded-left padded-right">';
} }
var supportsImageAnalysis = appHost.supports('imageanalysis'); let cardLayout = appHost.preferVisualCards && section.autoCardLayout && section.showTitle;
var cardLayout = (appHost.preferVisualCards || supportsImageAnalysis) && section.autoCardLayout && section.showTitle;
cardLayout = false; cardLayout = false;
html += cardBuilder.getCardsHtml(result.Items, { html += cardBuilder.getCardsHtml(result.Items, {
preferThumb: section.preferThumb, preferThumb: section.preferThumb,
shape: section.shape, shape: section.shape,
centerText: section.centerText && !cardLayout, centerText: section.centerText && !cardLayout,
overlayText: false !== section.overlayText, overlayText: section.overlayText !== false,
showTitle: section.showTitle, showTitle: section.showTitle,
showParentTitle: section.showParentTitle, showParentTitle: section.showParentTitle,
scalable: true, scalable: true,
@ -180,10 +188,10 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
}); });
} }
function loadSections(page, userId, topParentId, types) { export function loadSections(page, userId, topParentId, types) {
loading.show(); loading.show();
var sections = getSections(); let sections = getSections();
var sectionid = getParameterByName('sectionid'); const sectionid = getParameterByName('sectionid');
if (sectionid) { if (sectionid) {
sections = sections.filter(function (s) { sections = sections.filter(function (s) {
@ -193,30 +201,28 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
if (types) { if (types) {
sections = sections.filter(function (s) { sections = sections.filter(function (s) {
return -1 !== types.indexOf(s.id); return types.indexOf(s.id) !== -1;
}); });
} }
var i; let elem = page.querySelector('.favoriteSections');
var length;
var elem = page.querySelector('.favoriteSections');
if (!elem.innerHTML) { if (!elem.innerHTML) {
var html = ''; let html = '';
for (i = 0, length = sections.length; i < length; i++) { for (let i = 0, length = sections.length; i < length; i++) {
html += '<div class="verticalSection section' + sections[i].id + '"></div>'; html += '<div class="verticalSection section' + sections[i].id + '"></div>';
} }
elem.innerHTML = html; elem.innerHTML = html;
} }
var promises = []; const promises = [];
for (i = 0, length = sections.length; i < length; i++) { for (let i = 0, length = sections.length; i < length; i++) {
var section = sections[i]; const section = sections[i];
elem = page.querySelector('.section' + section.id); elem = page.querySelector('.section' + section.id);
promises.push(loadSection(elem, userId, topParentId, section, 1 === sections.length)); promises.push(loadSection(elem, userId, topParentId, section, sections.length === 1));
} }
Promise.all(promises).then(function () { Promise.all(promises).then(function () {
@ -224,7 +230,8 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
}); });
} }
return { export default {
render: loadSections render: loadSections
}; };
});
/* eslint-enable indent */

View file

@ -1,6 +1,5 @@
/* eslint-disable indent */ /* eslint-disable indent */
export function getFetchPromise(request) { export function getFetchPromise(request) {
const headers = request.headers || {}; const headers = request.headers || {};
if (request.dataType === 'json') { if (request.dataType === 'json') {
@ -16,7 +15,6 @@
let contentType = request.contentType; let contentType = request.contentType;
if (request.data) { if (request.data) {
if (typeof request.data === 'string') { if (typeof request.data === 'string') {
fetchRequest.body = request.data; fetchRequest.body = request.data;
} else { } else {
@ -27,7 +25,6 @@
} }
if (contentType) { if (contentType) {
headers['Content-Type'] = contentType; headers['Content-Type'] = contentType;
} }
@ -48,11 +45,9 @@
} }
function fetchWithTimeout(url, options, timeoutMs) { function fetchWithTimeout(url, options, timeoutMs) {
console.debug(`fetchWithTimeout: timeoutMs: ${timeoutMs}, url: ${url}`); console.debug(`fetchWithTimeout: timeoutMs: ${timeoutMs}, url: ${url}`);
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
const timeout = setTimeout(reject, timeoutMs); const timeout = setTimeout(reject, timeoutMs);
options = options || {}; options = options || {};
@ -65,7 +60,6 @@
resolve(response); resolve(response);
}, function (error) { }, function (error) {
clearTimeout(timeout); clearTimeout(timeout);
console.debug(`fetchWithTimeout: timed out connecting to url: ${url}`); console.debug(`fetchWithTimeout: timed out connecting to url: ${url}`);

View file

@ -1,7 +1,6 @@
import dom from 'dom'; import dom from 'dom';
import dialogHelper from 'dialogHelper'; import dialogHelper from 'dialogHelper';
import globalize from 'globalize'; import globalize from 'globalize';
import connectionManager from 'connectionManager';
import events from 'events'; import events from 'events';
import 'emby-checkbox'; import 'emby-checkbox';
import 'emby-collapse'; import 'emby-collapse';
@ -412,7 +411,7 @@ import 'css!./style.css';
dlg.classList.add('background-theme-a'); dlg.classList.add('background-theme-a');
dlg.classList.add('formDialog'); dlg.classList.add('formDialog');
dlg.classList.add('filterDialog'); dlg.classList.add('filterDialog');
dlg.innerHTML = globalize.translateDocument(template); dlg.innerHTML = globalize.translateHtml(template);
setVisibility(dlg, this.options); setVisibility(dlg, this.options);
dialogHelper.open(dlg); dialogHelper.open(dlg);
dlg.addEventListener('close', resolve); dlg.addEventListener('close', resolve);
@ -420,7 +419,7 @@ import 'css!./style.css';
this.bindEvents(dlg); this.bindEvents(dlg);
if (enableDynamicFilters(this.options.mode)) { if (enableDynamicFilters(this.options.mode)) {
dlg.classList.add('dynamicFilterDialog'); dlg.classList.add('dynamicFilterDialog');
const apiClient = connectionManager.getApiClient(this.options.serverId); const apiClient = window.connectionManager.getApiClient(this.options.serverId);
loadDynamicFilters(dlg, apiClient, apiClient.getCurrentUserId(), this.options.query); loadDynamicFilters(dlg, apiClient, apiClient.getCurrentUserId(), this.options.query);
} }
}); });

View file

@ -1,17 +1,17 @@
<div style="margin: 0;padding:1.5em 2em;" class="filterDialogContent"> <div style="margin: 0;padding:1.5em 2em;" class="filterDialogContent">
<div is="emby-collapse" title="${HeaderFilters}"> <div is="emby-collapse" title="${Filters}">
<div class="collapseContent"> <div class="collapseContent">
<div class="checkboxList"> <div class="checkboxList">
<label> <label>
<input type="checkbox" is="emby-checkbox" class="chkStandardFilter videoStandard" <input type="checkbox" is="emby-checkbox" class="chkStandardFilter videoStandard"
data-filter="IsPlayed" /> data-filter="IsPlayed" />
<span>${OptionPlayed}</span> <span>${Played}</span>
</label> </label>
<label> <label>
<input type="checkbox" is="emby-checkbox" class="chkStandardFilter videoStandard" <input type="checkbox" is="emby-checkbox" class="chkStandardFilter videoStandard"
data-filter="IsUnPlayed" /> data-filter="IsUnPlayed" />
<span>${OptionUnplayed}</span> <span>${Unplayed}</span>
</label> </label>
<label> <label>
<input type="checkbox" is="emby-checkbox" class="chkStandardFilter videoStandard" <input type="checkbox" is="emby-checkbox" class="chkStandardFilter videoStandard"
@ -21,7 +21,7 @@
<label> <label>
<input type="checkbox" is="emby-checkbox" class="chkStandardFilter chkFavorite" <input type="checkbox" is="emby-checkbox" class="chkStandardFilter chkFavorite"
data-filter="IsFavorite" /> data-filter="IsFavorite" />
<span>${OptionFavorite}</span> <span>${Favorites}</span>
</label> </label>
<label> <label>
<input type="checkbox" is="emby-checkbox" class="chkStandardFilter chkLikes" data-filter="Likes" /> <input type="checkbox" is="emby-checkbox" class="chkStandardFilter chkLikes" data-filter="Likes" />
@ -53,30 +53,30 @@
<div class="checkboxList"> <div class="checkboxList">
<label> <label>
<input type="checkbox" is="emby-checkbox" class="chkStatus" data-filter="Continuing" /> <input type="checkbox" is="emby-checkbox" class="chkStatus" data-filter="Continuing" />
<span>${OptionContinuing}</span> <span>${Continuing}</span>
</label> </label>
<label> <label>
<input type="checkbox" is="emby-checkbox" class="chkStatus" data-filter="Ended" /> <input type="checkbox" is="emby-checkbox" class="chkStatus" data-filter="Ended" />
<span>${OptionEnded}</span> <span>${Ended}</span>
</label> </label>
</div> </div>
</div> </div>
</div> </div>
<div is="emby-collapse" title="${HeaderFeatures}" class="features hide"> <div is="emby-collapse" title="${Features}" class="features hide">
<div class="collapseContent"> <div class="collapseContent">
<div class="checkboxList"> <div class="checkboxList">
<label> <label>
<input type="checkbox" is="emby-checkbox" class="chkFeatureFilter" id="chkSubtitle" /> <input type="checkbox" is="emby-checkbox" class="chkFeatureFilter" id="chkSubtitle" />
<span>${OptionHasSubtitles}</span> <span>${Subtitles}</span>
</label> </label>
<label> <label>
<input type="checkbox" is="emby-checkbox" class="chkFeatureFilter" id="chkTrailer" /> <input type="checkbox" is="emby-checkbox" class="chkFeatureFilter" id="chkTrailer" />
<span>${OptionHasTrailer}</span> <span>${ButtonTrailer}</span>
</label> </label>
<label> <label>
<input type="checkbox" is="emby-checkbox" class="chkFeatureFilter" id="chkSpecialFeature" /> <input type="checkbox" is="emby-checkbox" class="chkFeatureFilter" id="chkSpecialFeature" />
<span>${OptionHasSpecialFeatures}</span> <span>${SpecialFeatures}</span>
</label> </label>
<label> <label>
<input type="checkbox" is="emby-checkbox" class="chkFeatureFilter" id="chkThemeSong" /> <input type="checkbox" is="emby-checkbox" class="chkFeatureFilter" id="chkThemeSong" />
@ -90,7 +90,7 @@
</div> </div>
</div> </div>
<div is="emby-collapse" title="${HeaderGenres}" class="genreFilters hide"> <div is="emby-collapse" title="${Genres}" class="genreFilters hide">
<div class="collapseContent filterOptions"> <div class="collapseContent filterOptions">
</div> </div>
</div> </div>
@ -100,7 +100,7 @@
</div> </div>
</div> </div>
<div is="emby-collapse" title="${HeaderTags}" class="tagFilters hide"> <div is="emby-collapse" title="${Tags}" class="tagFilters hide">
<div class="collapseContent filterOptions"> <div class="collapseContent filterOptions">
</div> </div>
</div> </div>

View file

@ -1,20 +1,28 @@
define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', 'inputManager', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'userSettings', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'flexStyles'], function (require, dom, focusManager, dialogHelper, loading, appHost, inputManager, layoutManager, connectionManager, appRouter, globalize, userSettings) { import dom from 'dom';
'use strict'; import focusManager from 'focusManager';
import dialogHelper from 'dialogHelper';
function onSubmit(e) { import inputManager from 'inputManager';
import layoutManager from 'layoutManager';
import globalize from 'globalize';
import * as userSettings from 'userSettings';
import 'emby-checkbox';
import 'emby-input';
import 'paper-icon-button-light';
import 'emby-select';
import 'material-icons';
import 'css!./../formdialog';
import 'emby-button';
import 'flexStyles';
function onSubmit(e) {
e.preventDefault(); e.preventDefault();
return false; return false;
} }
function renderOptions(context, selector, cssClass, items, isCheckedFn) {
function renderOptions(context, selector, cssClass, items, isCheckedFn) {
var elem = context.querySelector(selector); var elem = context.querySelector(selector);
if (items.length) { if (items.length) {
elem.classList.remove('hide'); elem.classList.remove('hide');
} else { } else {
elem.classList.add('hide'); elem.classList.add('hide');
} }
@ -22,7 +30,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
var html = ''; var html = '';
html += items.map(function (filter) { html += items.map(function (filter) {
var itemHtml = ''; var itemHtml = '';
var checkedHtml = isCheckedFn(filter) ? ' checked' : ''; var checkedHtml = isCheckedFn(filter) ? ' checked' : '';
@ -32,180 +39,30 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
itemHtml += '</label>'; itemHtml += '</label>';
return itemHtml; return itemHtml;
}).join(''); }).join('');
elem.querySelector('.filterOptions').innerHTML = html; elem.querySelector('.filterOptions').innerHTML = html;
} }
function renderDynamicFilters(context, result, options) {
// If there's a huge number of these they will be really show to render
//if (result.Tags) {
// result.Tags.length = Math.min(result.Tags.length, 50);
//}
function renderDynamicFilters(context, result, options) {
renderOptions(context, '.genreFilters', 'chkGenreFilter', result.Genres, function (i) { renderOptions(context, '.genreFilters', 'chkGenreFilter', result.Genres, function (i) {
// Switching from | to , // Switching from | to ,
var delimeter = (options.settings.GenreIds || '').indexOf('|') === -1 ? ',' : '|'; var delimeter = (options.settings.GenreIds || '').indexOf('|') === -1 ? ',' : '|';
return (delimeter + (options.settings.GenreIds || '') + delimeter).indexOf(delimeter + i.Id + delimeter) !== -1; return (delimeter + (options.settings.GenreIds || '') + delimeter).indexOf(delimeter + i.Id + delimeter) !== -1;
}); });
}
//renderOptions(context, '.officialRatingFilters', 'chkOfficialRatingFilter', result.OfficialRatings, function (i) { function setBasicFilter(context, key, elem) {
// var delimeter = '|';
// return (delimeter + (query.OfficialRatings || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
//});
//renderOptions(context, '.tagFilters', 'chkTagFilter', result.Tags, function (i) {
// var delimeter = '|';
// return (delimeter + (query.Tags || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
//});
//renderOptions(context, '.yearFilters', 'chkYearFilter', result.Years, function (i) {
// var delimeter = ',';
// return (delimeter + (query.Years || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
//});
}
function loadDynamicFilters(context, options) {
var apiClient = connectionManager.getApiClient(options.serverId);
var filterMenuOptions = Object.assign(options.filterMenuOptions, {
UserId: apiClient.getCurrentUserId(),
ParentId: options.parentId,
IncludeItemTypes: options.itemTypes.join(',')
});
apiClient.getFilters(filterMenuOptions).then(function (result) {
renderDynamicFilters(context, result, options);
}, function () {
// older server
});
}
function initEditor(context, settings) {
context.querySelector('form').addEventListener('submit', onSubmit);
var elems = context.querySelectorAll('.simpleFilter');
var i;
var length;
for (i = 0, length = elems.length; i < length; i++) {
if (elems[i].tagName === 'INPUT') {
elems[i].checked = settings[elems[i].getAttribute('data-settingname')] || false;
} else {
elems[i].querySelector('input').checked = settings[elems[i].getAttribute('data-settingname')] || false;
}
}
var videoTypes = settings.VideoTypes ? settings.VideoTypes.split(',') : [];
elems = context.querySelectorAll('.chkVideoTypeFilter');
for (i = 0, length = elems.length; i < length; i++) {
elems[i].checked = videoTypes.indexOf(elems[i].getAttribute('data-filter')) !== -1;
}
var seriesStatuses = settings.SeriesStatus ? settings.SeriesStatus.split(',') : [];
elems = context.querySelectorAll('.chkSeriesStatus');
for (i = 0, length = elems.length; i < length; i++) {
elems[i].checked = seriesStatuses.indexOf(elems[i].getAttribute('data-filter')) !== -1;
}
if (context.querySelector('.basicFilterSection .viewSetting:not(.hide)')) {
context.querySelector('.basicFilterSection').classList.remove('hide');
} else {
context.querySelector('.basicFilterSection').classList.add('hide');
}
if (context.querySelector('.featureSection .viewSetting:not(.hide)')) {
context.querySelector('.featureSection').classList.remove('hide');
} else {
context.querySelector('.featureSection').classList.add('hide');
}
}
function saveValues(context, settings, settingsKey) {
var elems = context.querySelectorAll('.simpleFilter');
var i;
var length;
for (i = 0, length = elems.length; i < length; i++) {
if (elems[i].tagName === 'INPUT') {
setBasicFilter(context, settingsKey + '-filter-' + elems[i].getAttribute('data-settingname'), elems[i]);
} else {
setBasicFilter(context, settingsKey + '-filter-' + elems[i].getAttribute('data-settingname'), elems[i].querySelector('input'));
}
}
// Video type
var videoTypes = [];
elems = context.querySelectorAll('.chkVideoTypeFilter');
for (i = 0, length = elems.length; i < length; i++) {
if (elems[i].checked) {
videoTypes.push(elems[i].getAttribute('data-filter'));
}
}
userSettings.setFilter(settingsKey + '-filter-VideoTypes', videoTypes.join(','));
// Series status
var seriesStatuses = [];
elems = context.querySelectorAll('.chkSeriesStatus');
for (i = 0, length = elems.length; i < length; i++) {
if (elems[i].checked) {
seriesStatuses.push(elems[i].getAttribute('data-filter'));
}
}
// Genres
var genres = [];
elems = context.querySelectorAll('.chkGenreFilter');
for (i = 0, length = elems.length; i < length; i++) {
if (elems[i].checked) {
genres.push(elems[i].getAttribute('data-filter'));
}
}
userSettings.setFilter(settingsKey + '-filter-GenreIds', genres.join(','));
}
function setBasicFilter(context, key, elem) {
var value = elem.checked; var value = elem.checked;
value = value ? value : null; value = value ? value : null;
userSettings.setFilter(key, value); userSettings.setFilter(key, value);
} }
function moveCheckboxFocus(elem, offset) {
function centerFocus(elem, horiz, on) {
require(['scrollHelper'], function (scrollHelper) {
var fn = on ? 'on' : 'off';
scrollHelper.centerFocus[fn](elem, horiz);
});
}
function moveCheckboxFocus(elem, offset) {
var parent = dom.parentWithClass(elem, 'checkboxList-verticalwrap'); var parent = dom.parentWithClass(elem, 'checkboxList-verticalwrap');
var elems = focusManager.getFocusableElements(parent); var elems = focusManager.getFocusableElements(parent);
var index = -1; var index = -1;
for (var i = 0, length = elems.length; i < length; i++) { for (let i = 0, length = elems.length; i < length; i++) {
if (elems[i] === elem) { if (elems[i] === elem) {
index = i; index = i;
break; break;
@ -221,11 +78,15 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
if (newElem) { if (newElem) {
focusManager.focus(newElem); focusManager.focus(newElem);
} }
} }
function centerFocus(elem, horiz, on) {
function onInputCommand(e) { import('scrollHelper').then(({ default: scrollHelper }) => {
var fn = on ? 'on' : 'off';
scrollHelper.centerFocus[fn](elem, horiz);
});
}
function onInputCommand(e) {
switch (e.detail.command) { switch (e.detail.command) {
case 'left': case 'left':
moveCheckboxFocus(e.target, -1); moveCheckboxFocus(e.target, -1);
e.preventDefault(); e.preventDefault();
@ -237,35 +98,122 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
default: default:
break; break;
} }
}
function saveValues(context, settings, settingsKey) {
var elems = context.querySelectorAll('.simpleFilter');
for (let i = 0, length = elems.length; i < length; i++) {
if (elems[i].tagName === 'INPUT') {
setBasicFilter(context, settingsKey + '-filter-' + elems[i].getAttribute('data-settingname'), elems[i]);
} else {
setBasicFilter(context, settingsKey + '-filter-' + elems[i].getAttribute('data-settingname'), elems[i].querySelector('input'));
}
} }
function FilterMenu() { // Video type
var videoTypes = [];
elems = context.querySelectorAll('.chkVideoTypeFilter');
for (let i = 0, length = elems.length; i < length; i++) {
if (elems[i].checked) {
videoTypes.push(elems[i].getAttribute('data-filter'));
}
}
userSettings.setFilter(settingsKey + '-filter-VideoTypes', videoTypes.join(','));
// Series status
var seriesStatuses = [];
elems = context.querySelectorAll('.chkSeriesStatus');
for (let i = 0, length = elems.length; i < length; i++) {
if (elems[i].checked) {
seriesStatuses.push(elems[i].getAttribute('data-filter'));
}
} }
function bindCheckboxInput(context, on) { // Genres
var genres = [];
elems = context.querySelectorAll('.chkGenreFilter');
for (let i = 0, length = elems.length; i < length; i++) {
if (elems[i].checked) {
genres.push(elems[i].getAttribute('data-filter'));
}
}
userSettings.setFilter(settingsKey + '-filter-GenreIds', genres.join(','));
}
function bindCheckboxInput(context, on) {
var elems = context.querySelectorAll('.checkboxList-verticalwrap'); var elems = context.querySelectorAll('.checkboxList-verticalwrap');
for (var i = 0, length = elems.length; i < length; i++) { for (let i = 0, length = elems.length; i < length; i++) {
if (on) { if (on) {
inputManager.on(elems[i], onInputCommand); inputManager.on(elems[i], onInputCommand);
} else { } else {
inputManager.off(elems[i], onInputCommand); inputManager.off(elems[i], onInputCommand);
} }
} }
}
function initEditor(context, settings) {
context.querySelector('form').addEventListener('submit', onSubmit);
var elems = context.querySelectorAll('.simpleFilter');
var i;
var length;
for (i = 0, length = elems.length; i < length; i++) {
if (elems[i].tagName === 'INPUT') {
elems[i].checked = settings[elems[i].getAttribute('data-settingname')] || false;
} else {
elems[i].querySelector('input').checked = settings[elems[i].getAttribute('data-settingname')] || false;
}
} }
FilterMenu.prototype.show = function (options) { var videoTypes = settings.VideoTypes ? settings.VideoTypes.split(',') : [];
elems = context.querySelectorAll('.chkVideoTypeFilter');
return new Promise(function (resolve, reject) { for (i = 0, length = elems.length; i < length; i++) {
elems[i].checked = videoTypes.indexOf(elems[i].getAttribute('data-filter')) !== -1;
}
require(['text!./filtermenu.template.html'], function (template) { var seriesStatuses = settings.SeriesStatus ? settings.SeriesStatus.split(',') : [];
elems = context.querySelectorAll('.chkSeriesStatus');
for (i = 0, length = elems.length; i < length; i++) {
elems[i].checked = seriesStatuses.indexOf(elems[i].getAttribute('data-filter')) !== -1;
}
if (context.querySelector('.basicFilterSection .viewSetting:not(.hide)')) {
context.querySelector('.basicFilterSection').classList.remove('hide');
} else {
context.querySelector('.basicFilterSection').classList.add('hide');
}
if (context.querySelector('.featureSection .viewSetting:not(.hide)')) {
context.querySelector('.featureSection').classList.remove('hide');
} else {
context.querySelector('.featureSection').classList.add('hide');
}
}
function loadDynamicFilters(context, options) {
var apiClient = window.connectionManager.getApiClient(options.serverId);
var filterMenuOptions = Object.assign(options.filterMenuOptions, {
UserId: apiClient.getCurrentUserId(),
ParentId: options.parentId,
IncludeItemTypes: options.itemTypes.join(',')
});
apiClient.getFilters(filterMenuOptions).then((result) => {
renderDynamicFilters(context, result, options);
});
}
class FilterMenu {
show(options) {
return new Promise( (resolve, reject) => {
import('text!./filtermenu.template.html').then(({ default: template }) => {
var dialogOptions = { var dialogOptions = {
removeOnClose: true, removeOnClose: true,
scrollY: false scrollY: false
}; };
if (layoutManager.tv) { if (layoutManager.tv) {
dialogOptions.size = 'fullscreen'; dialogOptions.size = 'fullscreen';
} else { } else {
@ -286,10 +234,10 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
html += template; html += template;
dlg.innerHTML = globalize.translateDocument(html, 'core'); dlg.innerHTML = globalize.translateHtml(html, 'core');
var settingElements = dlg.querySelectorAll('.viewSetting'); var settingElements = dlg.querySelectorAll('.viewSetting');
for (var i = 0, length = settingElements.length; i < length; i++) { for (let i = 0, length = settingElements.length; i < length; i++) {
if (options.visibleSettings.indexOf(settingElements[i].getAttribute('data-settingname')) === -1) { if (options.visibleSettings.indexOf(settingElements[i].getAttribute('data-settingname')) === -1) {
settingElements[i].classList.add('hide'); settingElements[i].classList.add('hide');
} else { } else {
@ -301,9 +249,7 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
loadDynamicFilters(dlg, options); loadDynamicFilters(dlg, options);
bindCheckboxInput(dlg, true); bindCheckboxInput(dlg, true);
dlg.querySelector('.btnCancel').addEventListener('click', function () { dlg.querySelector('.btnCancel').addEventListener('click', function () {
dialogHelper.close(dlg); dialogHelper.close(dlg);
}); });
@ -314,17 +260,10 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
var submitted; var submitted;
dlg.querySelector('form').addEventListener('change', function () { dlg.querySelector('form').addEventListener('change', function () {
submitted = true; submitted = true;
//if (options.onChange) {
// saveValues(dlg, options.settings, options.settingsKey);
// options.onChange();
//}
}, true); }, true);
dialogHelper.open(dlg).then(function () { dialogHelper.open(dlg).then( function() {
bindCheckboxInput(dlg, false); bindCheckboxInput(dlg, false);
if (layoutManager.tv) { if (layoutManager.tv) {
@ -332,19 +271,16 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
} }
if (submitted) { if (submitted) {
//if (!options.onChange) { //if (!options.onChange) {
saveValues(dlg, options.settings, options.settingsKey); saveValues(dlg, options.settings, options.settingsKey);
resolve(); return resolve();
//} //}
return;
} }
return resolve();
});
});
});
}
}
reject(); export default FilterMenu;
});
});
});
};
return FilterMenu;
});

View file

@ -1,5 +1,7 @@
define(['dom', 'scrollManager'], function (dom, scrollManager) { /* eslint-disable indent */
'use strict';
import dom from 'dom';
import scrollManager from 'scrollManager';
var scopes = []; var scopes = [];
function pushScope(elem) { function pushScope(elem) {
@ -7,14 +9,12 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
} }
function popScope(elem) { function popScope(elem) {
if (scopes.length) { if (scopes.length) {
scopes.length -= 1; scopes.length -= 1;
} }
} }
function autoFocus(view, defaultToFirst, findAutoFocusElement) { function autoFocus(view, defaultToFirst, findAutoFocusElement) {
var element; var element;
if (findAutoFocusElement !== false) { if (findAutoFocusElement !== false) {
element = view.querySelector('*[autofocus]'); element = view.querySelector('*[autofocus]');
@ -37,7 +37,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
} }
function focus(element) { function focus(element) {
try { try {
element.focus({ element.focus({
preventScroll: scrollManager.isEnabled() preventScroll: scrollManager.isEnabled()
@ -50,16 +49,13 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
var focusableTagNames = ['INPUT', 'TEXTAREA', 'SELECT', 'BUTTON', 'A']; var focusableTagNames = ['INPUT', 'TEXTAREA', 'SELECT', 'BUTTON', 'A'];
var focusableContainerTagNames = ['BODY', 'DIALOG']; var focusableContainerTagNames = ['BODY', 'DIALOG'];
var focusableQuery = focusableTagNames.map(function (t) { var focusableQuery = focusableTagNames.map(function (t) {
if (t === 'INPUT') { if (t === 'INPUT') {
t += ':not([type="range"]):not([type="file"])'; t += ':not([type="range"]):not([type="file"])';
} }
return t + ':not([tabindex="-1"]):not(:disabled)'; return t + ':not([tabindex="-1"]):not(:disabled)';
}).join(',') + ',.focusable'; }).join(',') + ',.focusable';
function isFocusable(elem) { function isFocusable(elem) {
if (focusableTagNames.indexOf(elem.tagName) !== -1) { if (focusableTagNames.indexOf(elem.tagName) !== -1) {
return true; return true;
} }
@ -83,7 +79,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
} }
function focusableParent(elem) { function focusableParent(elem) {
var originalElement = elem; var originalElement = elem;
while (!isFocusable(elem)) { while (!isFocusable(elem)) {
@ -101,7 +96,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
// Determines if a focusable element can be focused at a given point in time // Determines if a focusable element can be focused at a given point in time
function isCurrentlyFocusableInternal(elem) { function isCurrentlyFocusableInternal(elem) {
// http://stackoverflow.com/questions/19669786/check-if-element-is-visible-in-dom // http://stackoverflow.com/questions/19669786/check-if-element-is-visible-in-dom
if (elem.offsetParent === null) { if (elem.offsetParent === null) {
return false; return false;
@ -112,7 +106,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
// Determines if a focusable element can be focused at a given point in time // Determines if a focusable element can be focused at a given point in time
function isCurrentlyFocusable(elem) { function isCurrentlyFocusable(elem) {
if (elem.disabled) { if (elem.disabled) {
return false; return false;
} }
@ -143,7 +136,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
var focusableElements = []; var focusableElements = [];
for (var i = 0, length = elems.length; i < length; i++) { for (var i = 0, length = elems.length; i < length; i++) {
var elem = elems[i]; var elem = elems[i];
if (excludeClass && elem.classList.contains(excludeClass)) { if (excludeClass && elem.classList.contains(excludeClass)) {
@ -163,7 +155,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
} }
function isFocusContainer(elem, direction) { function isFocusContainer(elem, direction) {
if (focusableContainerTagNames.indexOf(elem.tagName) !== -1) { if (focusableContainerTagNames.indexOf(elem.tagName) !== -1) {
return true; return true;
} }
@ -217,7 +208,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
} }
function getOffset(elem) { function getOffset(elem) {
var box; var box;
// Support: BlackBerry 5, iOS 3 (original iPhone) // Support: BlackBerry 5, iOS 3 (original iPhone)
@ -234,7 +224,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
} }
if (box.right === null) { if (box.right === null) {
// Create a new object because some browsers will throw an error when trying to set data onto the Rect object // Create a new object because some browsers will throw an error when trying to set data onto the Rect object
var newBox = { var newBox = {
top: box.top, top: box.top,
@ -253,7 +242,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
} }
function nav(activeElement, direction, container, focusableElements) { function nav(activeElement, direction, container, focusableElements) {
activeElement = activeElement || document.activeElement; activeElement = activeElement || document.activeElement;
if (activeElement) { if (activeElement) {
@ -272,14 +260,10 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
var rect = getOffset(activeElement); var rect = getOffset(activeElement);
// Get elements and work out x/y points // Get elements and work out x/y points
var cache = [];
var point1x = parseFloat(rect.left) || 0; var point1x = parseFloat(rect.left) || 0;
var point1y = parseFloat(rect.top) || 0; var point1y = parseFloat(rect.top) || 0;
var point2x = parseFloat(point1x + rect.width - 1) || point1x; var point2x = parseFloat(point1x + rect.width - 1) || point1x;
var point2y = parseFloat(point1y + rect.height - 1) || point1y; var point2y = parseFloat(point1y + rect.height - 1) || point1y;
// Shortcuts to help with compression
var min = Math.min;
var max = Math.max;
var sourceMidX = rect.left + (rect.width / 2); var sourceMidX = rect.left + (rect.width / 2);
var sourceMidY = rect.top + (rect.height / 2); var sourceMidY = rect.top + (rect.height / 2);
@ -301,10 +285,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
continue; continue;
} }
//if (!isCurrentlyFocusableInternal(curr)) {
// continue;
//}
var elementRect = getOffset(curr); var elementRect = getOffset(curr);
// not currently visible // not currently visible
@ -313,7 +293,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
} }
switch (direction) { switch (direction) {
case 0: case 0:
// left // left
if (elementRect.left >= rect.left) { if (elementRect.left >= rect.left) {
@ -369,7 +348,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
var distY; var distY;
switch (direction) { switch (direction) {
case 0: case 0:
// left // left
distX = Math.abs(point1x - Math.min(point1x, x2)); distX = Math.abs(point1x - Math.min(point1x, x2));
@ -403,7 +381,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
} }
if (nearestElement) { if (nearestElement) {
// See if there's a focusable container, and if so, send the focus command to that // See if there's a focusable container, and if so, send the focus command to that
if (activeElement) { if (activeElement) {
var nearestElementFocusableParent = dom.parentWithClass(nearestElement, 'focusable'); var nearestElementFocusableParent = dom.parentWithClass(nearestElement, 'focusable');
@ -418,12 +395,10 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
} }
function intersectsInternal(a1, a2, b1, b2) { function intersectsInternal(a1, a2, b1, b2) {
return (b1 >= a1 && b1 <= a2) || (b2 >= a1 && b2 <= a2); return (b1 >= a1 && b1 <= a2) || (b2 >= a1 && b2 <= a2);
} }
function intersects(a1, a2, b1, b2) { function intersects(a1, a2, b1, b2) {
return intersectsInternal(a1, a2, b1, b2) || intersectsInternal(b1, b2, a1, a2); return intersectsInternal(a1, a2, b1, b2) || intersectsInternal(b1, b2, a1, a2);
} }
@ -434,11 +409,9 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
} }
function focusFirst(container, focusableSelector) { function focusFirst(container, focusableSelector) {
var elems = container.querySelectorAll(focusableSelector); var elems = container.querySelectorAll(focusableSelector);
for (var i = 0, length = elems.length; i < length; i++) { for (var i = 0, length = elems.length; i < length; i++) {
var elem = elems[i]; var elem = elems[i];
if (isCurrentlyFocusableInternal(elem)) { if (isCurrentlyFocusableInternal(elem)) {
@ -449,11 +422,9 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
} }
function focusLast(container, focusableSelector) { function focusLast(container, focusableSelector) {
var elems = [].slice.call(container.querySelectorAll(focusableSelector), 0).reverse(); var elems = [].slice.call(container.querySelectorAll(focusableSelector), 0).reverse();
for (var i = 0, length = elems.length; i < length; i++) { for (var i = 0, length = elems.length; i < length; i++) {
var elem = elems[i]; var elem = elems[i];
if (isCurrentlyFocusableInternal(elem)) { if (isCurrentlyFocusableInternal(elem)) {
@ -464,7 +435,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
} }
function moveFocus(sourceElement, container, focusableSelector, offset) { function moveFocus(sourceElement, container, focusableSelector, offset) {
var elems = container.querySelectorAll(focusableSelector); var elems = container.querySelectorAll(focusableSelector);
var list = []; var list = [];
var i; var i;
@ -472,7 +442,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
var elem; var elem;
for (i = 0, length = elems.length; i < length; i++) { for (i = 0, length = elems.length; i < length; i++) {
elem = elems[i]; elem = elems[i];
if (isCurrentlyFocusableInternal(elem)) { if (isCurrentlyFocusableInternal(elem)) {
@ -483,7 +452,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
var currentIndex = -1; var currentIndex = -1;
for (i = 0, length = list.length; i < length; i++) { for (i = 0, length = list.length; i < length; i++) {
elem = list[i]; elem = list[i];
if (sourceElement === elem || elem.contains(sourceElement)) { if (sourceElement === elem || elem.contains(sourceElement)) {
@ -506,7 +474,9 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
} }
} }
return { /* eslint-enable indent */
export default {
autoFocus: autoFocus, autoFocus: autoFocus,
focus: focus, focus: focus,
focusableParent: focusableParent, focusableParent: focusableParent,
@ -538,5 +508,4 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
focusFirst: focusFirst, focusFirst: focusFirst,
focusLast: focusLast, focusLast: focusLast,
moveFocus: moveFocus moveFocus: moveFocus
}; };
});

View file

@ -1,10 +1,12 @@
define(['dom', 'appRouter', 'connectionManager'], function (dom, appRouter, connectionManager) { /* eslint-disable indent */
'use strict';
import dom from 'dom';
import appRouter from 'appRouter';
function onGroupedCardClick(e, card) { function onGroupedCardClick(e, card) {
var itemId = card.getAttribute('data-id'); var itemId = card.getAttribute('data-id');
var serverId = card.getAttribute('data-serverid'); var serverId = card.getAttribute('data-serverid');
var apiClient = connectionManager.getApiClient(serverId); var apiClient = window.connectionManager.getApiClient(serverId);
var userId = apiClient.getCurrentUserId(); var userId = apiClient.getCurrentUserId();
var playedIndicator = card.querySelector('.playedIndicator'); var playedIndicator = card.querySelector('.playedIndicator');
var playedIndicatorHtml = playedIndicator ? playedIndicator.innerHTML : null; var playedIndicatorHtml = playedIndicator ? playedIndicator.innerHTML : null;
@ -18,7 +20,7 @@ define(['dom', 'appRouter', 'connectionManager'], function (dom, appRouter, conn
if (!actionableParent || actionableParent.classList.contains('cardContent')) { if (!actionableParent || actionableParent.classList.contains('cardContent')) {
apiClient.getJSON(apiClient.getUrl('Users/' + userId + '/Items/Latest', options)).then(function (items) { apiClient.getJSON(apiClient.getUrl('Users/' + userId + '/Items/Latest', options)).then(function (items) {
if (1 === items.length) { if (items.length === 1) {
return void appRouter.showItem(items[0]); return void appRouter.showItem(items[0]);
} }
@ -31,7 +33,7 @@ define(['dom', 'appRouter', 'connectionManager'], function (dom, appRouter, conn
} }
} }
function onItemsContainerClick(e) { export default function onItemsContainerClick(e) {
var groupedCard = dom.parentWithClass(e.target, 'groupedCard'); var groupedCard = dom.parentWithClass(e.target, 'groupedCard');
if (groupedCard) { if (groupedCard) {
@ -39,7 +41,4 @@ define(['dom', 'appRouter', 'connectionManager'], function (dom, appRouter, conn
} }
} }
return { /* eslint-enable indent */
onItemsContainerClick: onItemsContainerClick
};
});

View file

@ -1,16 +1,21 @@
define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectionManager', 'require', 'loading', 'scrollHelper', 'emby-checkbox', 'emby-radio', 'css!./../formdialog', 'material-icons'], function (dialogHelper, globalize, userSettings, layoutManager, connectionManager, require, loading, scrollHelper) { import dialogHelper from 'dialogHelper';
'use strict'; import globalize from 'globalize';
import * as userSettings from 'userSettings';
import layoutManager from 'layoutManager';
import scrollHelper from 'scrollHelper';
import 'emby-checkbox';
import 'emby-radio';
import 'css!./../formdialog';
import 'material-icons';
function saveCategories(context, options) { function saveCategories(context, options) {
const categories = [];
var categories = []; const chkCategorys = context.querySelectorAll('.chkCategory');
for (const chkCategory of chkCategorys) {
const type = chkCategory.getAttribute('data-type');
var chkCategorys = context.querySelectorAll('.chkCategory'); if (chkCategory.checked) {
for (var i = 0, length = chkCategorys.length; i < length; i++) {
var type = chkCategorys[i].getAttribute('data-type');
if (chkCategorys[i].checked) {
categories.push(type); categories.push(type);
} }
} }
@ -22,82 +27,69 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio
// differentiate between none and all // differentiate between none and all
categories.push('all'); categories.push('all');
options.categories = categories; options.categories = categories;
}
function loadCategories(context, options) {
const selectedCategories = options.categories || [];
const chkCategorys = context.querySelectorAll('.chkCategory');
for (const chkCategory of chkCategorys) {
const type = chkCategory.getAttribute('data-type');
chkCategory.checked = !selectedCategories.length || selectedCategories.indexOf(type) !== -1;
} }
}
function loadCategories(context, options) { function save(context) {
const chkIndicators = context.querySelectorAll('.chkIndicator');
var selectedCategories = options.categories || []; for (const chkIndicator of chkIndicators) {
const type = chkIndicator.getAttribute('data-type');
var chkCategorys = context.querySelectorAll('.chkCategory'); userSettings.set('guide-indicator-' + type, chkIndicator.checked);
for (var i = 0, length = chkCategorys.length; i < length; i++) {
var type = chkCategorys[i].getAttribute('data-type');
chkCategorys[i].checked = !selectedCategories.length || selectedCategories.indexOf(type) !== -1;
}
}
function save(context) {
var i;
var length;
var chkIndicators = context.querySelectorAll('.chkIndicator');
for (i = 0, length = chkIndicators.length; i < length; i++) {
var type = chkIndicators[i].getAttribute('data-type');
userSettings.set('guide-indicator-' + type, chkIndicators[i].checked);
} }
userSettings.set('guide-colorcodedbackgrounds', context.querySelector('.chkColorCodedBackgrounds').checked); userSettings.set('guide-colorcodedbackgrounds', context.querySelector('.chkColorCodedBackgrounds').checked);
userSettings.set('livetv-favoritechannelsattop', context.querySelector('.chkFavoriteChannelsAtTop').checked); userSettings.set('livetv-favoritechannelsattop', context.querySelector('.chkFavoriteChannelsAtTop').checked);
var sortBys = context.querySelectorAll('.chkSortOrder'); const sortBys = context.querySelectorAll('.chkSortOrder');
for (i = 0, length = sortBys.length; i < length; i++) { for (const sortBy of sortBys) {
if (sortBys[i].checked) { if (sortBy.checked) {
userSettings.set('livetv-channelorder', sortBys[i].value); userSettings.set('livetv-channelorder', sortBy.value);
break; break;
} }
} }
} }
function load(context) { function load(context) {
const chkIndicators = context.querySelectorAll('.chkIndicator');
var i; for (const chkIndicator of chkIndicators) {
var length; const type = chkIndicator.getAttribute('data-type');
var chkIndicators = context.querySelectorAll('.chkIndicator'); if (chkIndicator.getAttribute('data-default') === 'true') {
for (i = 0, length = chkIndicators.length; i < length; i++) { chkIndicator.checked = userSettings.get('guide-indicator-' + type) !== 'false';
var type = chkIndicators[i].getAttribute('data-type');
if (chkIndicators[i].getAttribute('data-default') === 'true') {
chkIndicators[i].checked = userSettings.get('guide-indicator-' + type) !== 'false';
} else { } else {
chkIndicators[i].checked = userSettings.get('guide-indicator-' + type) === 'true'; chkIndicator.checked = userSettings.get('guide-indicator-' + type) === 'true';
} }
} }
context.querySelector('.chkColorCodedBackgrounds').checked = userSettings.get('guide-colorcodedbackgrounds') === 'true'; context.querySelector('.chkColorCodedBackgrounds').checked = userSettings.get('guide-colorcodedbackgrounds') === 'true';
context.querySelector('.chkFavoriteChannelsAtTop').checked = userSettings.get('livetv-favoritechannelsattop') !== 'false'; context.querySelector('.chkFavoriteChannelsAtTop').checked = userSettings.get('livetv-favoritechannelsattop') !== 'false';
var sortByValue = userSettings.get('livetv-channelorder') || 'Number'; const sortByValue = userSettings.get('livetv-channelorder') || 'Number';
var sortBys = context.querySelectorAll('.chkSortOrder'); const sortBys = context.querySelectorAll('.chkSortOrder');
for (i = 0, length = sortBys.length; i < length; i++) { for (const sortBy of sortBys) {
sortBys[i].checked = sortBys[i].value === sortByValue; sortBy.checked = sortBy.value === sortByValue;
}
} }
}
function showEditor(options) { function showEditor(options) {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
let settingsChanged = false;
var settingsChanged = false; import('text!./guide-settings.template.html').then(({ default: template }) => {
const dialogOptions = {
require(['text!./guide-settings.template.html'], function (template) {
var dialogOptions = {
removeOnClose: true, removeOnClose: true,
scrollY: false scrollY: false
}; };
@ -108,23 +100,21 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio
dialogOptions.size = 'small'; dialogOptions.size = 'small';
} }
var dlg = dialogHelper.createDialog(dialogOptions); const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog'); dlg.classList.add('formDialog');
var html = ''; let html = '';
html += globalize.translateDocument(template, 'core'); html += globalize.translateHtml(template, 'core');
dlg.innerHTML = html; dlg.innerHTML = html;
dlg.addEventListener('change', function () { dlg.addEventListener('change', function () {
settingsChanged = true; settingsChanged = true;
}); });
dlg.addEventListener('close', function () { dlg.addEventListener('close', function () {
if (layoutManager.tv) { if (layoutManager.tv) {
scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false); scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false);
} }
@ -152,9 +142,8 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio
dialogHelper.open(dlg); dialogHelper.open(dlg);
}); });
}); });
} }
return { export default {
show: showEditor show: showEditor
}; };
});

View file

@ -1,5 +1,5 @@
<div class="formDialogHeader"> <div class="formDialogHeader">
<button is="paper-icon-button-light" class="btnCancel autoSize" title="${LabelPrevious}" tabindex="-1"> <button is="paper-icon-button-light" class="btnCancel autoSize" title="${Previous}" tabindex="-1">
<span class="material-icons arrow_back" aria-hidden="true"></span> <span class="material-icons arrow_back" aria-hidden="true"></span>
</button> </button>
<h3 class="formDialogHeaderTitle"> <h3 class="formDialogHeaderTitle">

View file

@ -70,6 +70,10 @@
contain: strict; contain: strict;
} }
.programContainer.emby-scroller {
margin: 0;
}
.channelPrograms { .channelPrograms {
height: 4.42em; height: 4.42em;
contain: strict; contain: strict;

File diff suppressed because it is too large Load diff

View file

@ -29,10 +29,10 @@
</div> </div>
<div class="guideOptions hide"> <div class="guideOptions hide">
<button is="paper-icon-button-light" type="button" class="btnPreviousPage" title="${LabelPrevious}"> <button is="paper-icon-button-light" type="button" class="btnPreviousPage" title="${Previous}">
<span class="material-icons arrow_back" aria-hidden="true"></span> <span class="material-icons arrow_back" aria-hidden="true"></span>
</button> </button>
<button is="paper-icon-button-light" type="button" class="btnNextPage" title="${LabelNext}"> <button is="paper-icon-button-light" type="button" class="btnNextPage" title="${Next}">
<span class="material-icons arrow_forward" aria-hidden="true"></span> <span class="material-icons arrow_forward" aria-hidden="true"></span>
</button> </button>
</div> </div>

View file

@ -1,30 +1,37 @@
define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loading', 'connectionManager', 'homeSections', 'dom', 'events', 'listViewStyle', 'emby-select', 'emby-checkbox'], function (require, appHost, layoutManager, focusManager, globalize, loading, connectionManager, homeSections, dom, events) { import layoutManager from 'layoutManager';
'use strict'; import focusManager from 'focusManager';
import globalize from 'globalize';
import loading from 'loading';
import homeSections from 'homeSections';
import dom from 'dom';
import events from 'events';
import 'listViewStyle';
import 'emby-select';
import 'emby-checkbox';
var numConfigurableSections = 7; /* eslint-disable indent */
const numConfigurableSections = 7;
function renderViews(page, user, result) { function renderViews(page, user, result) {
let folderHtml = '';
var folderHtml = '';
folderHtml += '<div class="checkboxList">'; folderHtml += '<div class="checkboxList">';
folderHtml += result.map(function (i) { folderHtml += result.map(i => {
let currentHtml = '';
var currentHtml = ''; const id = `chkGroupFolder${i.Id}`;
var id = 'chkGroupFolder' + i.Id; const isChecked = user.Configuration.GroupedFolders.includes(i.Id);
var isChecked = user.Configuration.GroupedFolders.indexOf(i.Id) !== -1; const checkedHtml = isChecked ? ' checked="checked"' : '';
var checkedHtml = isChecked ? ' checked="checked"' : '';
currentHtml += '<label>'; currentHtml += '<label>';
currentHtml += '<input type="checkbox" is="emby-checkbox" class="chkGroupFolder" data-folderid="' + i.Id + '" id="' + id + '"' + checkedHtml + '/>'; currentHtml += `<input type="checkbox" is="emby-checkbox" class="chkGroupFolder" data-folderid="${i.Id}" id="${id}"${checkedHtml}/>`;
currentHtml += '<span>' + i.Name + '</span>'; currentHtml += `<span>${i.Name}</span>`;
currentHtml += '</label>'; currentHtml += '</label>';
return currentHtml; return currentHtml;
}).join(''); }).join('');
folderHtml += '</div>'; folderHtml += '</div>';
@ -33,8 +40,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
} }
function getLandingScreenOptions(type) { function getLandingScreenOptions(type) {
const list = [];
var list = [];
if (type === 'movies') { if (type === 'movies') {
list.push({ list.push({
@ -122,28 +128,22 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
} }
function getLandingScreenOptionsHtml(type, userValue) { function getLandingScreenOptionsHtml(type, userValue) {
return getLandingScreenOptions(type).map(o => {
const selected = userValue === o.value || (o.isDefault && !userValue);
const selectedHtml = selected ? ' selected' : '';
const optionValue = o.isDefault ? '' : o.value;
return getLandingScreenOptions(type).map(function (o) { return `<option value="${optionValue}"${selectedHtml}>${o.name}</option>`;
var selected = userValue === o.value || (o.isDefault && !userValue);
var selectedHtml = selected ? ' selected' : '';
var optionValue = o.isDefault ? '' : o.value;
return '<option value="' + optionValue + '"' + selectedHtml + '>' + o.name + '</option>';
}).join(''); }).join('');
} }
function renderViewOrder(context, user, result) { function renderViewOrder(context, user, result) {
let html = '';
var html = ''; html += result.Items.map((view) => {
let currentHtml = '';
var index = 0; currentHtml += `<div class="listItem viewItem" data-viewid="${view.Id}">`;
html += result.Items.map(function (view) {
var currentHtml = '';
currentHtml += '<div class="listItem viewItem" data-viewid="' + view.Id + '">';
currentHtml += '<span class="material-icons listItemIcon folder_open"></span>'; currentHtml += '<span class="material-icons listItemIcon folder_open"></span>';
@ -155,29 +155,25 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
currentHtml += '</div>'; currentHtml += '</div>';
currentHtml += '<button type="button" is="paper-icon-button-light" class="btnViewItemUp btnViewItemMove autoSize" title="' + globalize.translate('Up') + '"><span class="material-icons keyboard_arrow_up"></span></button>'; currentHtml += `<button type="button" is="paper-icon-button-light" class="btnViewItemUp btnViewItemMove autoSize" title="${globalize.translate('Up')}"><span class="material-icons keyboard_arrow_up"></span></button>`;
currentHtml += '<button type="button" is="paper-icon-button-light" class="btnViewItemDown btnViewItemMove autoSize" title="' + globalize.translate('Down') + '"><span class="material-icons keyboard_arrow_down"></span></button>'; currentHtml += `<button type="button" is="paper-icon-button-light" class="btnViewItemDown btnViewItemMove autoSize" title="${globalize.translate('Down')}"><span class="material-icons keyboard_arrow_down"></span></button>`;
currentHtml += '</div>'; currentHtml += '</div>';
index++;
return currentHtml; return currentHtml;
}).join(''); }).join('');
context.querySelector('.viewOrderList').innerHTML = html; context.querySelector('.viewOrderList').innerHTML = html;
} }
function updateHomeSectionValues(context, userSettings) { function updateHomeSectionValues(context, userSettings) {
for (let i = 1; i <= 7; i++) {
const select = context.querySelector(`#selectHomeSection${i}`);
const defaultValue = homeSections.getDefaultSection(i - 1);
for (var i = 1; i <= 7; i++) { const option = select.querySelector(`option[value=${defaultValue}]`) || select.querySelector('option[value=""]');
var select = context.querySelector('#selectHomeSection' + i); const userValue = userSettings.get(`homesection${i - 1}`);
var defaultValue = homeSections.getDefaultSection(i - 1);
var option = select.querySelector('option[value=' + defaultValue + ']') || select.querySelector('option[value=""]');
var userValue = userSettings.get('homesection' + (i - 1));
option.value = ''; option.value = '';
@ -192,43 +188,39 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
} }
function getPerLibrarySettingsHtml(item, user, userSettings, apiClient) { function getPerLibrarySettingsHtml(item, user, userSettings, apiClient) {
let html = '';
var html = ''; let isChecked;
var isChecked;
if (item.Type === 'Channel' || item.CollectionType === 'boxsets' || item.CollectionType === 'playlists') { if (item.Type === 'Channel' || item.CollectionType === 'boxsets' || item.CollectionType === 'playlists') {
isChecked = (user.Configuration.MyMediaExcludes || []).indexOf(item.Id) === -1; isChecked = !(user.Configuration.MyMediaExcludes || []).includes(item.Id);
html += '<div>'; html += '<div>';
html += '<label>'; html += '<label>';
html += '<input type="checkbox" is="emby-checkbox" class="chkIncludeInMyMedia" data-folderid="' + item.Id + '"' + (isChecked ? ' checked="checked"' : '') + '/>'; html += `<input type="checkbox" is="emby-checkbox" class="chkIncludeInMyMedia" data-folderid="${item.Id}"${isChecked ? ' checked="checked"' : ''}/>`;
html += '<span>' + globalize.translate('DisplayInMyMedia') + '</span>'; html += `<span>${globalize.translate('DisplayInMyMedia')}</span>`;
html += '</label>'; html += '</label>';
html += '</div>'; html += '</div>';
} }
var excludeFromLatest = ['playlists', 'livetv', 'boxsets', 'channels']; const excludeFromLatest = ['playlists', 'livetv', 'boxsets', 'channels'];
if (excludeFromLatest.indexOf(item.CollectionType || '') === -1) { if (!excludeFromLatest.includes(item.CollectionType || '')) {
isChecked = !user.Configuration.LatestItemsExcludes.includes(item.Id);
isChecked = user.Configuration.LatestItemsExcludes.indexOf(item.Id) === -1;
html += '<label class="fldIncludeInLatest">'; html += '<label class="fldIncludeInLatest">';
html += '<input type="checkbox" is="emby-checkbox" class="chkIncludeInLatest" data-folderid="' + item.Id + '"' + (isChecked ? ' checked="checked"' : '') + '/>'; html += `<input type="checkbox" is="emby-checkbox" class="chkIncludeInLatest" data-folderid="${item.Id}"${isChecked ? ' checked="checked"' : ''}/>`;
html += '<span>' + globalize.translate('DisplayInOtherHomeScreenSections') + '</span>'; html += `<span>${globalize.translate('DisplayInOtherHomeScreenSections')}</span>`;
html += '</label>'; html += '</label>';
} }
if (html) { if (html) {
html = `<div class="checkboxListContainer">${html}</div>`;
html = '<div class="checkboxListContainer">' + html + '</div>';
} }
if (item.CollectionType === 'movies' || item.CollectionType === 'tvshows' || item.CollectionType === 'music' || item.CollectionType === 'livetv') { if (item.CollectionType === 'movies' || item.CollectionType === 'tvshows' || item.CollectionType === 'music' || item.CollectionType === 'livetv') {
const idForLanding = item.CollectionType === 'livetv' ? item.CollectionType : item.Id;
var idForLanding = item.CollectionType === 'livetv' ? item.CollectionType : item.Id;
html += '<div class="selectContainer">'; html += '<div class="selectContainer">';
html += '<select is="emby-select" class="selectLanding" data-folderid="' + idForLanding + '" label="' + globalize.translate('LabelDefaultScreen') + '">'; html += `<select is="emby-select" class="selectLanding" data-folderid="${idForLanding}" label="${globalize.translate('LabelDefaultScreen')}">`;
var userValue = userSettings.get('landing-' + idForLanding); const userValue = userSettings.get(`landing-${idForLanding}`);
html += getLandingScreenOptionsHtml(item.CollectionType, userValue); html += getLandingScreenOptionsHtml(item.CollectionType, userValue);
@ -237,8 +229,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
} }
if (html) { if (html) {
let prefix = '';
var prefix = '';
prefix += '<div class="verticalSection">'; prefix += '<div class="verticalSection">';
prefix += '<h2 class="sectionTitle">'; prefix += '<h2 class="sectionTitle">';
@ -253,12 +244,10 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
} }
function renderPerLibrarySettings(context, user, userViews, userSettings, apiClient) { function renderPerLibrarySettings(context, user, userViews, userSettings, apiClient) {
const elem = context.querySelector('.perLibrarySettings');
let html = '';
var elem = context.querySelector('.perLibrarySettings'); for (let i = 0, length = userViews.length; i < length; i++) {
var html = '';
for (var i = 0, length = userViews.length; i < length; i++) {
html += getPerLibrarySettingsHtml(userViews[i], user, userSettings, apiClient); html += getPerLibrarySettingsHtml(userViews[i], user, userSettings, apiClient);
} }
@ -266,16 +255,14 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
} }
function loadForm(context, user, userSettings, apiClient) { function loadForm(context, user, userSettings, apiClient) {
context.querySelector('.chkHidePlayedFromLatest').checked = user.Configuration.HidePlayedInLatest || false; context.querySelector('.chkHidePlayedFromLatest').checked = user.Configuration.HidePlayedInLatest || false;
updateHomeSectionValues(context, userSettings); updateHomeSectionValues(context, userSettings);
var promise1 = apiClient.getUserViews({ IncludeHidden: true }, user.Id); const promise1 = apiClient.getUserViews({ IncludeHidden: true }, user.Id);
var promise2 = apiClient.getJSON(apiClient.getUrl('Users/' + user.Id + '/GroupingOptions')); const promise2 = apiClient.getJSON(apiClient.getUrl(`Users/${user.Id}/GroupingOptions`));
Promise.all([promise1, promise2]).then(function (responses) {
Promise.all([promise1, promise2]).then(responses => {
renderViewOrder(context, user, responses[0]); renderViewOrder(context, user, responses[0]);
renderPerLibrarySettings(context, user, responses[0].Items, userSettings, apiClient); renderPerLibrarySettings(context, user, responses[0].Items, userSettings, apiClient);
@ -286,48 +273,23 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
}); });
} }
function getSibling(elem, type, className) {
var sibling = elem[type];
while (sibling != null) {
if (sibling.classList.contains(className)) {
break;
}
}
if (sibling != null) {
if (!sibling.classList.contains(className)) {
sibling = null;
}
}
return sibling;
}
function onSectionOrderListClick(e) { function onSectionOrderListClick(e) {
const target = dom.parentWithClass(e.target, 'btnViewItemMove');
var target = dom.parentWithClass(e.target, 'btnViewItemMove');
if (target) { if (target) {
var viewItem = dom.parentWithClass(target, 'viewItem'); const viewItem = dom.parentWithClass(target, 'viewItem');
if (viewItem) { if (viewItem) {
var ul = dom.parentWithClass(viewItem, 'paperList');
if (target.classList.contains('btnViewItemDown')) { if (target.classList.contains('btnViewItemDown')) {
const next = viewItem.nextSibling;
var next = viewItem.nextSibling;
if (next) { if (next) {
viewItem.parentNode.removeChild(viewItem); viewItem.parentNode.removeChild(viewItem);
next.parentNode.insertBefore(viewItem, next.nextSibling); next.parentNode.insertBefore(viewItem, next.nextSibling);
focusManager.focus(e.target); focusManager.focus(e.target);
} }
} else { } else {
const prev = viewItem.previousSibling;
var prev = viewItem.previousSibling;
if (prev) { if (prev) {
viewItem.parentNode.removeChild(viewItem); viewItem.parentNode.removeChild(viewItem);
@ -340,44 +302,37 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
} }
function getCheckboxItems(selector, context, isChecked) { function getCheckboxItems(selector, context, isChecked) {
const inputs = context.querySelectorAll(selector);
const list = [];
var inputs = context.querySelectorAll(selector); for (let i = 0, length = inputs.length; i < length; i++) {
var list = [];
for (var i = 0, length = inputs.length; i < length; i++) {
if (inputs[i].checked === isChecked) { if (inputs[i].checked === isChecked) {
list.push(inputs[i]); list.push(inputs[i]);
} }
} }
return list; return list;
} }
function saveUser(context, user, userSettingsInstance, apiClient) { function saveUser(context, user, userSettingsInstance, apiClient) {
user.Configuration.HidePlayedInLatest = context.querySelector('.chkHidePlayedFromLatest').checked; user.Configuration.HidePlayedInLatest = context.querySelector('.chkHidePlayedFromLatest').checked;
user.Configuration.LatestItemsExcludes = getCheckboxItems('.chkIncludeInLatest', context, false).map(function (i) { user.Configuration.LatestItemsExcludes = getCheckboxItems('.chkIncludeInLatest', context, false).map(i => {
return i.getAttribute('data-folderid'); return i.getAttribute('data-folderid');
}); });
user.Configuration.MyMediaExcludes = getCheckboxItems('.chkIncludeInMyMedia', context, false).map(function (i) { user.Configuration.MyMediaExcludes = getCheckboxItems('.chkIncludeInMyMedia', context, false).map(i => {
return i.getAttribute('data-folderid'); return i.getAttribute('data-folderid');
}); });
user.Configuration.GroupedFolders = getCheckboxItems('.chkGroupFolder', context, true).map(function (i) { user.Configuration.GroupedFolders = getCheckboxItems('.chkGroupFolder', context, true).map(i => {
return i.getAttribute('data-folderid'); return i.getAttribute('data-folderid');
}); });
var viewItems = context.querySelectorAll('.viewItem'); const viewItems = context.querySelectorAll('.viewItem');
var orderedViews = []; const orderedViews = [];
var i; let i;
var length; let length;
for (i = 0, length = viewItems.length; i < length; i++) { for (i = 0, length = viewItems.length; i < length; i++) {
orderedViews.push(viewItems[i].getAttribute('data-viewid')); orderedViews.push(viewItems[i].getAttribute('data-viewid'));
} }
@ -394,48 +349,42 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
userSettingsInstance.set('homesection5', context.querySelector('#selectHomeSection6').value); userSettingsInstance.set('homesection5', context.querySelector('#selectHomeSection6').value);
userSettingsInstance.set('homesection6', context.querySelector('#selectHomeSection7').value); userSettingsInstance.set('homesection6', context.querySelector('#selectHomeSection7').value);
var selectLandings = context.querySelectorAll('.selectLanding'); const selectLandings = context.querySelectorAll('.selectLanding');
for (i = 0, length = selectLandings.length; i < length; i++) { for (i = 0, length = selectLandings.length; i < length; i++) {
var selectLanding = selectLandings[i]; const selectLanding = selectLandings[i];
userSettingsInstance.set('landing-' + selectLanding.getAttribute('data-folderid'), selectLanding.value); userSettingsInstance.set(`landing-${selectLanding.getAttribute('data-folderid')}`, selectLanding.value);
} }
return apiClient.updateUserConfiguration(user.Id, user.Configuration); return apiClient.updateUserConfiguration(user.Id, user.Configuration);
} }
function save(instance, context, userId, userSettings, apiClient, enableSaveConfirmation) { function save(instance, context, userId, userSettings, apiClient, enableSaveConfirmation) {
loading.show(); loading.show();
apiClient.getUser(userId).then(function (user) { apiClient.getUser(userId).then(user => {
saveUser(context, user, userSettings, apiClient).then(() => {
saveUser(context, user, userSettings, apiClient).then(function () {
loading.hide(); loading.hide();
if (enableSaveConfirmation) { if (enableSaveConfirmation) {
require(['toast'], function (toast) { import('toast').then(({default: toast}) => {
toast(globalize.translate('SettingsSaved')); toast(globalize.translate('SettingsSaved'));
}); });
} }
events.trigger(instance, 'saved'); events.trigger(instance, 'saved');
}, () => {
}, function () {
loading.hide(); loading.hide();
}); });
}); });
} }
function onSubmit(e) { function onSubmit(e) {
const self = this;
const apiClient = window.connectionManager.getApiClient(self.options.serverId);
const userId = self.options.userId;
const userSettings = self.options.userSettings;
var self = this; userSettings.setUserInfo(userId, apiClient).then(() => {
var apiClient = connectionManager.getApiClient(self.options.serverId); const enableSaveConfirmation = self.options.enableSaveConfirmation;
var userId = self.options.userId;
var userSettings = self.options.userSettings;
userSettings.setUserInfo(userId, apiClient).then(function () {
var enableSaveConfirmation = self.options.enableSaveConfirmation;
save(self, self.options.element, userId, userSettings, apiClient, enableSaveConfirmation); save(self, self.options.element, userId, userSettings, apiClient, enableSaveConfirmation);
}); });
@ -447,14 +396,13 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
} }
function onChange(e) { function onChange(e) {
const chkIncludeInMyMedia = dom.parentWithClass(e.target, 'chkIncludeInMyMedia');
var chkIncludeInMyMedia = dom.parentWithClass(e.target, 'chkIncludeInMyMedia');
if (!chkIncludeInMyMedia) { if (!chkIncludeInMyMedia) {
return; return;
} }
var section = dom.parentWithClass(chkIncludeInMyMedia, 'verticalSection'); const section = dom.parentWithClass(chkIncludeInMyMedia, 'verticalSection');
var fldIncludeInLatest = section.querySelector('.fldIncludeInLatest'); const fldIncludeInLatest = section.querySelector('.fldIncludeInLatest');
if (fldIncludeInLatest) { if (fldIncludeInLatest) {
if (chkIncludeInMyMedia.checked) { if (chkIncludeInMyMedia.checked) {
fldIncludeInLatest.classList.remove('hide'); fldIncludeInLatest.classList.remove('hide');
@ -465,14 +413,12 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
} }
function embed(options, self) { function embed(options, self) {
return import('text!./homeScreenSettings.template.html').then(({default: template}) => {
require(['text!./homeScreenSettings.template.html'], function (template) { for (let i = 1; i <= numConfigurableSections; i++) {
template = template.replace(`{section${i}label}`, globalize.translate('LabelHomeScreenSectionValue', i));
for (var i = 1; i <= numConfigurableSections; i++) {
template = template.replace('{section' + i + 'label}', globalize.translate('LabelHomeScreenSectionValue', i));
} }
options.element.innerHTML = globalize.translateDocument(template, 'core'); options.element.innerHTML = globalize.translateHtml(template, 'core');
options.element.querySelector('.viewOrderList').addEventListener('click', onSectionOrderListClick); options.element.querySelector('.viewOrderList').addEventListener('click', onSectionOrderListClick);
options.element.querySelector('form').addEventListener('submit', onSubmit.bind(self)); options.element.querySelector('form').addEventListener('submit', onSubmit.bind(self));
@ -492,28 +438,24 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
}); });
} }
function HomeScreenSettings(options) { class HomeScreenSettings {
constructor(options) {
this.options = options; this.options = options;
embed(options, this); embed(options, this);
} }
HomeScreenSettings.prototype.loadData = function (autoFocus) { loadData(autoFocus) {
const self = this;
var self = this; const context = self.options.element;
var context = self.options.element;
loading.show(); loading.show();
var userId = self.options.userId; const userId = self.options.userId;
var apiClient = connectionManager.getApiClient(self.options.serverId); const apiClient = window.connectionManager.getApiClient(self.options.serverId);
var userSettings = self.options.userSettings; const userSettings = self.options.userSettings;
apiClient.getUser(userId).then(function (user) {
userSettings.setUserInfo(userId, apiClient).then(function () {
apiClient.getUser(userId).then(user => {
userSettings.setUserInfo(userId, apiClient).then(() => {
self.dataLoaded = true; self.dataLoaded = true;
loadForm(context, user, userSettings, apiClient); loadForm(context, user, userSettings, apiClient);
@ -523,16 +465,17 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
} }
}); });
}); });
}; }
HomeScreenSettings.prototype.submit = function () { submit() {
onSubmit.call(this); onSubmit.call(this);
}; }
HomeScreenSettings.prototype.destroy = function () {
destroy() {
this.options = null; this.options = null;
}; }
}
return HomeScreenSettings; /* eslint-enable indent */
});
export default HomeScreenSettings;

View file

@ -1,6 +1,6 @@
<form style="margin:0 auto;"> <form style="margin:0 auto;">
<div class="verticalSection verticalSection-extrabottompadding"> <div class="verticalSection verticalSection-extrabottompadding">
<h2 class="sectionTitle">${HeaderHome}</h2> <h2 class="sectionTitle">${Home}</h2>
<div class="selectContainer hide selectTVHomeScreenContainer"> <div class="selectContainer hide selectTVHomeScreenContainer">
<select is="emby-select" class="selectTVHomeScreen" label="${LabelTVHomeScreen}"> <select is="emby-select" class="selectTVHomeScreen" label="${LabelTVHomeScreen}">
@ -25,7 +25,7 @@
<option value="resume">${HeaderContinueWatching}</option> <option value="resume">${HeaderContinueWatching}</option>
<option value="resumeaudio">${HeaderContinueListening}</option> <option value="resumeaudio">${HeaderContinueListening}</option>
<option value="latestmedia">${HeaderLatestMedia}</option> <option value="latestmedia">${HeaderLatestMedia}</option>
<option value="nextup">${HeaderNextUp}</option> <option value="nextup">${NextUp}</option>
<option value="livetv">${LiveTV}</option> <option value="livetv">${LiveTV}</option>
<option value="none">${None}</option> <option value="none">${None}</option>
</select> </select>
@ -38,7 +38,7 @@
<option value="resume">${HeaderContinueWatching}</option> <option value="resume">${HeaderContinueWatching}</option>
<option value="resumeaudio">${HeaderContinueListening}</option> <option value="resumeaudio">${HeaderContinueListening}</option>
<option value="latestmedia">${HeaderLatestMedia}</option> <option value="latestmedia">${HeaderLatestMedia}</option>
<option value="nextup">${HeaderNextUp}</option> <option value="nextup">${NextUp}</option>
<option value="livetv">${LiveTV}</option> <option value="livetv">${LiveTV}</option>
<option value="none">${None}</option> <option value="none">${None}</option>
</select> </select>
@ -51,7 +51,7 @@
<option value="resume">${HeaderContinueWatching}</option> <option value="resume">${HeaderContinueWatching}</option>
<option value="resumeaudio">${HeaderContinueListening}</option> <option value="resumeaudio">${HeaderContinueListening}</option>
<option value="latestmedia">${HeaderLatestMedia}</option> <option value="latestmedia">${HeaderLatestMedia}</option>
<option value="nextup">${HeaderNextUp}</option> <option value="nextup">${NextUp}</option>
<option value="livetv">${LiveTV}</option> <option value="livetv">${LiveTV}</option>
<option value="none">${None}</option> <option value="none">${None}</option>
</select> </select>
@ -64,7 +64,7 @@
<option value="resume">${HeaderContinueWatching}</option> <option value="resume">${HeaderContinueWatching}</option>
<option value="resumeaudio">${HeaderContinueListening}</option> <option value="resumeaudio">${HeaderContinueListening}</option>
<option value="latestmedia">${HeaderLatestMedia}</option> <option value="latestmedia">${HeaderLatestMedia}</option>
<option value="nextup">${HeaderNextUp}</option> <option value="nextup">${NextUp}</option>
<option value="livetv">${LiveTV}</option> <option value="livetv">${LiveTV}</option>
<option value="none">${None}</option> <option value="none">${None}</option>
</select> </select>
@ -77,7 +77,7 @@
<option value="resume">${HeaderContinueWatching}</option> <option value="resume">${HeaderContinueWatching}</option>
<option value="resumeaudio">${HeaderContinueListening}</option> <option value="resumeaudio">${HeaderContinueListening}</option>
<option value="latestmedia">${HeaderLatestMedia}</option> <option value="latestmedia">${HeaderLatestMedia}</option>
<option value="nextup">${HeaderNextUp}</option> <option value="nextup">${NextUp}</option>
<option value="livetv">${LiveTV}</option> <option value="livetv">${LiveTV}</option>
<option value="none">${None}</option> <option value="none">${None}</option>
</select> </select>
@ -90,7 +90,7 @@
<option value="resume">${HeaderContinueWatching}</option> <option value="resume">${HeaderContinueWatching}</option>
<option value="resumeaudio">${HeaderContinueListening}</option> <option value="resumeaudio">${HeaderContinueListening}</option>
<option value="latestmedia">${HeaderLatestMedia}</option> <option value="latestmedia">${HeaderLatestMedia}</option>
<option value="nextup">${HeaderNextUp}</option> <option value="nextup">${NextUp}</option>
<option value="livetv">${LiveTV}</option> <option value="livetv">${LiveTV}</option>
<option value="none">${None}</option> <option value="none">${None}</option>
</select> </select>
@ -103,7 +103,7 @@
<option value="resume">${HeaderContinueWatching}</option> <option value="resume">${HeaderContinueWatching}</option>
<option value="resumeaudio">${HeaderContinueListening}</option> <option value="resumeaudio">${HeaderContinueListening}</option>
<option value="latestmedia">${HeaderLatestMedia}</option> <option value="latestmedia">${HeaderLatestMedia}</option>
<option value="nextup">${HeaderNextUp}</option> <option value="nextup">${NextUp}</option>
<option value="livetv">${LiveTV}</option> <option value="livetv">${LiveTV}</option>
<option value="none">${None}</option> <option value="none">${None}</option>
</select> </select>

View file

@ -1,7 +1,19 @@
define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'layoutManager', 'imageLoader', 'globalize', 'itemShortcuts', 'itemHelper', 'appRouter', 'scripts/imagehelper', 'paper-icon-button-light', 'emby-itemscontainer', 'emby-scroller', 'emby-button', 'css!./homesections'], function (connectionManager, cardBuilder, appSettings, dom, appHost, layoutManager, imageLoader, globalize, itemShortcuts, itemHelper, appRouter, imageHelper) { import cardBuilder from 'cardBuilder';
'use strict'; import dom from 'dom';
import layoutManager from 'layoutManager';
import imageLoader from 'imageLoader';
import globalize from 'globalize';
import appRouter from 'appRouter';
import imageHelper from 'scripts/imagehelper';
import 'paper-icon-button-light';
import 'emby-itemscontainer';
import 'emby-scroller';
import 'emby-button';
import 'css!./homesections';
function getDefaultSection(index) { /* eslint-disable indent */
export function getDefaultSection(index) {
switch (index) { switch (index) {
case 0: case 0:
return 'smalllibrarytiles'; return 'smalllibrarytiles';
@ -23,9 +35,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
} }
function getAllSectionsToShow(userSettings, sectionCount) { function getAllSectionsToShow(userSettings, sectionCount) {
var sections = []; const sections = [];
for (var i = 0, length = sectionCount; i < length; i++) { for (let i = 0, length = sectionCount; i < length; i++) {
var section = userSettings.get('homesection' + i) || getDefaultSection(i); let section = userSettings.get('homesection' + i) || getDefaultSection(i);
if (section === 'folders') { if (section === 'folders') {
section = getDefaultSection(0); section = getDefaultSection(0);
} }
@ -36,22 +48,22 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
return sections; return sections;
} }
function loadSections(elem, apiClient, user, userSettings) { export function loadSections(elem, apiClient, user, userSettings) {
return getUserViews(apiClient, user.Id).then(function (userViews) { return getUserViews(apiClient, user.Id).then(function (userViews) {
var html = ''; let html = '';
if (userViews.length) { if (userViews.length) {
var sectionCount = 7; const sectionCount = 7;
for (var i = 0; i < sectionCount; i++) { for (let i = 0; i < sectionCount; i++) {
html += '<div class="verticalSection section' + i + '"></div>'; html += '<div class="verticalSection section' + i + '"></div>';
} }
elem.innerHTML = html; elem.innerHTML = html;
elem.classList.add('homeSectionsContainer'); elem.classList.add('homeSectionsContainer');
var promises = []; const promises = [];
var sections = getAllSectionsToShow(userSettings, sectionCount); const sections = getAllSectionsToShow(userSettings, sectionCount);
for (var i = 0; i < sections.length; i++) { for (let i = 0; i < sections.length; i++) {
promises.push(loadSection(elem, apiClient, user, userSettings, userViews, sections, i)); promises.push(loadSection(elem, apiClient, user, userSettings, userViews, sections, i));
} }
@ -62,7 +74,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}); });
}); });
} else { } else {
var noLibDescription; let noLibDescription;
if (user['Policy'] && user['Policy']['IsAdministrator']) { if (user['Policy'] && user['Policy']['IsAdministrator']) {
noLibDescription = globalize.translate('NoCreatedLibraries', '<br><a id="button-createLibrary" class="button-link">', '</a>'); noLibDescription = globalize.translate('NoCreatedLibraries', '<br><a id="button-createLibrary" class="button-link">', '</a>');
} else { } else {
@ -75,7 +87,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
html += '</div>'; html += '</div>';
elem.innerHTML = html; elem.innerHTML = html;
var createNowLink = elem.querySelector('#button-createLibrary'); const createNowLink = elem.querySelector('#button-createLibrary');
if (createNowLink) { if (createNowLink) {
createNowLink.addEventListener('click', function () { createNowLink.addEventListener('click', function () {
Dashboard.navigate('library.html'); Dashboard.navigate('library.html');
@ -85,9 +97,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}); });
} }
function destroySections(elem) { export function destroySections(elem) {
var elems = elem.querySelectorAll('.itemsContainer'); const elems = elem.querySelectorAll('.itemsContainer');
for (var i = 0; i < elems.length; i++) { for (let i = 0; i < elems.length; i++) {
elems[i].fetchData = null; elems[i].fetchData = null;
elems[i].parentContainer = null; elems[i].parentContainer = null;
elems[i].getItemsHtml = null; elems[i].getItemsHtml = null;
@ -96,35 +108,32 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
elem.innerHTML = ''; elem.innerHTML = '';
} }
function pause(elem) { export function pause(elem) {
var elems = elem.querySelectorAll('.itemsContainer'); const elems = elem.querySelectorAll('.itemsContainer');
for (var i = 0; i < elems.length; i++) { for (let i = 0; i < elems.length; i++) {
elems[i].pause(); elems[i].pause();
} }
} }
function resume(elem, options) { export function resume(elem, options) {
var elems = elem.querySelectorAll('.itemsContainer'); const elems = elem.querySelectorAll('.itemsContainer');
var i; const promises = [];
var length;
var promises = [];
for (i = 0, length = elems.length; i < length; i++) { for (let i = 0, length = elems.length; i < length; i++) {
promises.push(elems[i].resume(options)); promises.push(elems[i].resume(options));
} }
var promise = Promise.all(promises); const promise = Promise.all(promises);
if (!options || options.returnPromise !== false) { if (!options || options.returnPromise !== false) {
return promise; return promise;
} }
} }
function loadSection(page, apiClient, user, userSettings, userViews, allSections, index) { function loadSection(page, apiClient, user, userSettings, userViews, allSections, index) {
const section = allSections[index];
const userId = user.Id;
var section = allSections[index]; const elem = page.querySelector('.section' + index);
var userId = user.Id;
var elem = page.querySelector('.section' + index);
if (section === 'latestmedia') { if (section === 'latestmedia') {
loadRecentlyAdded(elem, apiClient, user, userViews); loadRecentlyAdded(elem, apiClient, user, userViews);
@ -172,7 +181,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
} }
function getLibraryButtonsHtml(items) { function getLibraryButtonsHtml(items) {
var html = ''; let html = '';
html += '<div class="verticalSection verticalSection-extrabottompadding">'; html += '<div class="verticalSection verticalSection-extrabottompadding">';
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderMyMedia') + '</h2>'; html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderMyMedia') + '</h2>';
@ -180,9 +189,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right vertical-wrap focuscontainer-x" data-multiselect="false">'; html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right vertical-wrap focuscontainer-x" data-multiselect="false">';
// library card background images // library card background images
for (var i = 0, length = items.length; i < length; i++) { for (let i = 0, length = items.length; i < length; i++) {
var item = items[i]; const item = items[i];
var icon = imageHelper.getLibraryIcon(item.CollectionType); const icon = imageHelper.getLibraryIcon(item.CollectionType);
html += '<a is="emby-linkbutton" href="' + appRouter.getRouteUrl(item) + '" class="raised homeLibraryButton"><span class="material-icons homeLibraryIcon ' + icon + '"></span><span class="homeLibraryText">' + item.Name + '</span></a>'; html += '<a is="emby-linkbutton" href="' + appRouter.getRouteUrl(item) + '" class="raised homeLibraryButton"><span class="material-icons homeLibraryIcon ' + icon + '"></span><span class="homeLibraryText">' + item.Name + '</span></a>';
} }
@ -194,24 +203,16 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function loadlibraryButtons(elem, apiClient, user, userSettings, userViews) { function loadlibraryButtons(elem, apiClient, user, userSettings, userViews) {
elem.classList.remove('verticalSection'); elem.classList.remove('verticalSection');
var html = getLibraryButtonsHtml(userViews); const html = getLibraryButtonsHtml(userViews);
elem.innerHTML = html; elem.innerHTML = html;
imageLoader.lazyChildren(elem); imageLoader.lazyChildren(elem);
} }
/**
* Returns a random integer between min (inclusive) and max (inclusive)
* Using Math.round() will give you a non-uniform distribution!
*/
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function getFetchLatestItemsFn(serverId, parentId, collectionType) { function getFetchLatestItemsFn(serverId, parentId, collectionType) {
return function () { return function () {
var apiClient = connectionManager.getApiClient(serverId); const apiClient = window.connectionManager.getApiClient(serverId);
var limit = 16; let limit = 16;
if (enableScrollX()) { if (enableScrollX()) {
if (collectionType === 'music') { if (collectionType === 'music') {
@ -227,7 +228,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
} }
} }
var options = { const options = {
Limit: limit, Limit: limit,
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo,Path', Fields: 'PrimaryImageAspectRatio,BasicSyncInfo,Path',
ImageTypeLimit: 1, ImageTypeLimit: 1,
@ -241,8 +242,8 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function getLatestItemsHtmlFn(itemType, viewType) { function getLatestItemsHtmlFn(itemType, viewType) {
return function (items) { return function (items) {
var cardLayout = false; const cardLayout = false;
var shape; let shape;
if (itemType === 'Channel' || viewType === 'movies' || viewType === 'books' || viewType === 'tvshows') { if (itemType === 'Channel' || viewType === 'movies' || viewType === 'books' || viewType === 'tvshows') {
shape = getPortraitShape(); shape = getPortraitShape();
} else if (viewType === 'music' || viewType === 'homevideos') { } else if (viewType === 'music' || viewType === 'homevideos') {
@ -272,7 +273,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
} }
function renderLatestSection(elem, apiClient, user, parent) { function renderLatestSection(elem, apiClient, user, parent) {
var html = ''; let html = '';
html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">'; html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">';
if (!layoutManager.tv) { if (!layoutManager.tv) {
@ -303,7 +304,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
elem.innerHTML = html; elem.innerHTML = html;
var itemsContainer = elem.querySelector('.itemsContainer'); const itemsContainer = elem.querySelector('.itemsContainer');
itemsContainer.fetchData = getFetchLatestItemsFn(apiClient.serverId(), parent.Id, parent.CollectionType); itemsContainer.fetchData = getFetchLatestItemsFn(apiClient.serverId(), parent.Id, parent.CollectionType);
itemsContainer.getItemsHtml = getLatestItemsHtmlFn(parent.Type, parent.CollectionType); itemsContainer.getItemsHtml = getLatestItemsHtmlFn(parent.Type, parent.CollectionType);
itemsContainer.parentContainer = elem; itemsContainer.parentContainer = elem;
@ -311,10 +312,10 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function loadRecentlyAdded(elem, apiClient, user, userViews) { function loadRecentlyAdded(elem, apiClient, user, userViews) {
elem.classList.remove('verticalSection'); elem.classList.remove('verticalSection');
var excludeViewTypes = ['playlists', 'livetv', 'boxsets', 'channels']; const excludeViewTypes = ['playlists', 'livetv', 'boxsets', 'channels'];
for (var i = 0, length = userViews.length; i < length; i++) { for (let i = 0, length = userViews.length; i < length; i++) {
var item = userViews[i]; const item = userViews[i];
if (user.Configuration.LatestItemsExcludes.indexOf(item.Id) !== -1) { if (user.Configuration.LatestItemsExcludes.indexOf(item.Id) !== -1) {
continue; continue;
} }
@ -323,7 +324,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
continue; continue;
} }
var frag = document.createElement('div'); const frag = document.createElement('div');
frag.classList.add('verticalSection'); frag.classList.add('verticalSection');
frag.classList.add('hide'); frag.classList.add('hide');
elem.appendChild(frag); elem.appendChild(frag);
@ -332,14 +333,8 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
} }
} }
function getRequirePromise(deps) { export function loadLibraryTiles(elem, apiClient, user, userSettings, shape, userViews, allSections) {
return new Promise(function (resolve, reject) { let html = '';
require(deps, resolve);
});
}
function loadLibraryTiles(elem, apiClient, user, userSettings, shape, userViews, allSections) {
var html = '';
if (userViews.length) { if (userViews.length) {
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderMyMedia') + '</h2>'; html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderMyMedia') + '</h2>';
if (enableScrollX()) { if (enableScrollX()) {
@ -372,10 +367,10 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function getContinueWatchingFetchFn(serverId) { function getContinueWatchingFetchFn(serverId) {
return function () { return function () {
var apiClient = connectionManager.getApiClient(serverId); const apiClient = window.connectionManager.getApiClient(serverId);
var screenWidth = dom.getWindowSize().innerWidth; const screenWidth = dom.getWindowSize().innerWidth;
var limit; let limit;
if (enableScrollX()) { if (enableScrollX()) {
limit = 12; limit = 12;
} else { } else {
@ -383,7 +378,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
limit = Math.min(limit, 5); limit = Math.min(limit, 5);
} }
var options = { const options = {
Limit: limit, Limit: limit,
Recursive: true, Recursive: true,
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo', Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
@ -398,7 +393,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
} }
function getContinueWatchingItemsHtml(items) { function getContinueWatchingItemsHtml(items) {
var cardLayout = false; const cardLayout = false;
return cardBuilder.getCardsHtml({ return cardBuilder.getCardsHtml({
items: items, items: items,
preferThumb: true, preferThumb: true,
@ -419,7 +414,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
} }
function loadResumeVideo(elem, apiClient, userId) { function loadResumeVideo(elem, apiClient, userId) {
var html = ''; let html = '';
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderContinueWatching') + '</h2>'; html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderContinueWatching') + '</h2>';
if (enableScrollX()) { if (enableScrollX()) {
@ -437,7 +432,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
elem.classList.add('hide'); elem.classList.add('hide');
elem.innerHTML = html; elem.innerHTML = html;
var itemsContainer = elem.querySelector('.itemsContainer'); const itemsContainer = elem.querySelector('.itemsContainer');
itemsContainer.fetchData = getContinueWatchingFetchFn(apiClient.serverId()); itemsContainer.fetchData = getContinueWatchingFetchFn(apiClient.serverId());
itemsContainer.getItemsHtml = getContinueWatchingItemsHtml; itemsContainer.getItemsHtml = getContinueWatchingItemsHtml;
itemsContainer.parentContainer = elem; itemsContainer.parentContainer = elem;
@ -445,10 +440,10 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function getContinueListeningFetchFn(serverId) { function getContinueListeningFetchFn(serverId) {
return function () { return function () {
var apiClient = connectionManager.getApiClient(serverId); const apiClient = window.connectionManager.getApiClient(serverId);
var screenWidth = dom.getWindowSize().innerWidth; const screenWidth = dom.getWindowSize().innerWidth;
var limit; let limit;
if (enableScrollX()) { if (enableScrollX()) {
limit = 12; limit = 12;
} else { } else {
@ -456,7 +451,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
limit = Math.min(limit, 5); limit = Math.min(limit, 5);
} }
var options = { const options = {
Limit: limit, Limit: limit,
Recursive: true, Recursive: true,
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo', Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
@ -471,7 +466,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
} }
function getContinueListeningItemsHtml(items) { function getContinueListeningItemsHtml(items) {
var cardLayout = false; const cardLayout = false;
return cardBuilder.getCardsHtml({ return cardBuilder.getCardsHtml({
items: items, items: items,
preferThumb: true, preferThumb: true,
@ -492,7 +487,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
} }
function loadResumeAudio(elem, apiClient, userId) { function loadResumeAudio(elem, apiClient, userId) {
var html = ''; let html = '';
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderContinueWatching') + '</h2>'; html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderContinueWatching') + '</h2>';
if (enableScrollX()) { if (enableScrollX()) {
@ -510,7 +505,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
elem.classList.add('hide'); elem.classList.add('hide');
elem.innerHTML = html; elem.innerHTML = html;
var itemsContainer = elem.querySelector('.itemsContainer'); const itemsContainer = elem.querySelector('.itemsContainer');
itemsContainer.fetchData = getContinueListeningFetchFn(apiClient.serverId()); itemsContainer.fetchData = getContinueListeningFetchFn(apiClient.serverId());
itemsContainer.getItemsHtml = getContinueListeningItemsHtml; itemsContainer.getItemsHtml = getContinueListeningItemsHtml;
itemsContainer.parentContainer = elem; itemsContainer.parentContainer = elem;
@ -518,7 +513,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function getOnNowFetchFn(serverId) { function getOnNowFetchFn(serverId) {
return function () { return function () {
var apiClient = connectionManager.getApiClient(serverId); const apiClient = window.connectionManager.getApiClient(serverId);
return apiClient.getLiveTvRecommendedPrograms({ return apiClient.getLiveTvRecommendedPrograms({
userId: apiClient.getCurrentUserId(), userId: apiClient.getCurrentUserId(),
IsAiring: true, IsAiring: true,
@ -532,7 +527,6 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
} }
function getOnNowItemsHtml(items) { function getOnNowItemsHtml(items) {
var cardLayout = false;
return cardBuilder.getCardsHtml({ return cardBuilder.getCardsHtml({
items: items, items: items,
preferThumb: 'auto', preferThumb: 'auto',
@ -559,7 +553,6 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
return Promise.resolve(); return Promise.resolve();
} }
var userId = user.Id;
return apiClient.getLiveTvRecommendedPrograms({ return apiClient.getLiveTvRecommendedPrograms({
userId: apiClient.getCurrentUserId(), userId: apiClient.getCurrentUserId(),
IsAiring: true, IsAiring: true,
@ -569,7 +562,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
EnableTotalRecordCount: false, EnableTotalRecordCount: false,
Fields: 'ChannelInfo,PrimaryImageAspectRatio' Fields: 'ChannelInfo,PrimaryImageAspectRatio'
}).then(function (result) { }).then(function (result) {
var html = ''; let html = '';
if (result.Items.length) { if (result.Items.length) {
elem.classList.remove('padded-left'); elem.classList.remove('padded-left');
elem.classList.remove('padded-right'); elem.classList.remove('padded-right');
@ -632,7 +625,6 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
html += '</h2>'; html += '</h2>';
html += '<span class="material-icons chevron_right"></span>'; html += '<span class="material-icons chevron_right"></span>';
html += '</a>'; html += '</a>';
} else { } else {
html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate('HeaderOnNow') + '</h2>'; html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate('HeaderOnNow') + '</h2>';
} }
@ -654,7 +646,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
elem.innerHTML = html; elem.innerHTML = html;
var itemsContainer = elem.querySelector('.itemsContainer'); const itemsContainer = elem.querySelector('.itemsContainer');
itemsContainer.parentContainer = elem; itemsContainer.parentContainer = elem;
itemsContainer.fetchData = getOnNowFetchFn(apiClient.serverId()); itemsContainer.fetchData = getOnNowFetchFn(apiClient.serverId());
itemsContainer.getItemsHtml = getOnNowItemsHtml; itemsContainer.getItemsHtml = getOnNowItemsHtml;
@ -664,7 +656,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function getNextUpFetchFn(serverId) { function getNextUpFetchFn(serverId) {
return function () { return function () {
var apiClient = connectionManager.getApiClient(serverId); const apiClient = window.connectionManager.getApiClient(serverId);
return apiClient.getNextUpEpisodes({ return apiClient.getNextUpEpisodes({
Limit: enableScrollX() ? 24 : 15, Limit: enableScrollX() ? 24 : 15,
Fields: 'PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo,Path', Fields: 'PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo,Path',
@ -677,7 +669,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
} }
function getNextUpItemsHtml(items) { function getNextUpItemsHtml(items) {
var cardLayout = false; const cardLayout = false;
return cardBuilder.getCardsHtml({ return cardBuilder.getCardsHtml({
items: items, items: items,
preferThumb: true, preferThumb: true,
@ -695,7 +687,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
} }
function loadNextUp(elem, apiClient, userId) { function loadNextUp(elem, apiClient, userId) {
var html = ''; let html = '';
html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">'; html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">';
if (!layoutManager.tv) { if (!layoutManager.tv) {
@ -703,12 +695,12 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
serverId: apiClient.serverId() serverId: apiClient.serverId()
}) + '" class="button-flat button-flat-mini sectionTitleTextButton">'; }) + '" class="button-flat button-flat-mini sectionTitleTextButton">';
html += '<h2 class="sectionTitle sectionTitle-cards">'; html += '<h2 class="sectionTitle sectionTitle-cards">';
html += globalize.translate('HeaderNextUp'); html += globalize.translate('NextUp');
html += '</h2>'; html += '</h2>';
html += '<span class="material-icons chevron_right"></span>'; html += '<span class="material-icons chevron_right"></span>';
html += '</a>'; html += '</a>';
} else { } else {
html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate('HeaderNextUp') + '</h2>'; html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate('NextUp') + '</h2>';
} }
html += '</div>'; html += '</div>';
@ -727,7 +719,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
elem.classList.add('hide'); elem.classList.add('hide');
elem.innerHTML = html; elem.innerHTML = html;
var itemsContainer = elem.querySelector('.itemsContainer'); const itemsContainer = elem.querySelector('.itemsContainer');
itemsContainer.fetchData = getNextUpFetchFn(apiClient.serverId()); itemsContainer.fetchData = getNextUpFetchFn(apiClient.serverId());
itemsContainer.getItemsHtml = getNextUpItemsHtml; itemsContainer.getItemsHtml = getNextUpItemsHtml;
itemsContainer.parentContainer = elem; itemsContainer.parentContainer = elem;
@ -735,7 +727,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function getLatestRecordingsFetchFn(serverId, activeRecordingsOnly) { function getLatestRecordingsFetchFn(serverId, activeRecordingsOnly) {
return function () { return function () {
var apiClient = connectionManager.getApiClient(serverId); const apiClient = window.connectionManager.getApiClient(serverId);
return apiClient.getLiveTvRecordings({ return apiClient.getLiveTvRecordings({
userId: apiClient.getCurrentUserId(), userId: apiClient.getCurrentUserId(),
Limit: enableScrollX() ? 12 : 5, Limit: enableScrollX() ? 12 : 5,
@ -749,7 +741,6 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function getLatestRecordingItemsHtml(activeRecordingsOnly) { function getLatestRecordingItemsHtml(activeRecordingsOnly) {
return function (items) { return function (items) {
var cardLayout = false;
return cardBuilder.getCardsHtml({ return cardBuilder.getCardsHtml({
items: items, items: items,
shape: enableScrollX() ? 'autooverflow' : 'auto', shape: enableScrollX() ? 'autooverflow' : 'auto',
@ -774,11 +765,11 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
} }
function loadLatestLiveTvRecordings(elem, activeRecordingsOnly, apiClient, userId) { function loadLatestLiveTvRecordings(elem, activeRecordingsOnly, apiClient, userId) {
var title = activeRecordingsOnly ? const title = activeRecordingsOnly ?
globalize.translate('HeaderActiveRecordings') : globalize.translate('HeaderActiveRecordings') :
globalize.translate('HeaderLatestRecordings'); globalize.translate('HeaderLatestRecordings');
var html = ''; let html = '';
html += '<div class="sectionTitleContainer sectionTitleContainer-cards">'; html += '<div class="sectionTitleContainer sectionTitleContainer-cards">';
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + title + '</h2>'; html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + title + '</h2>';
@ -799,18 +790,19 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
elem.classList.add('hide'); elem.classList.add('hide');
elem.innerHTML = html; elem.innerHTML = html;
var itemsContainer = elem.querySelector('.itemsContainer'); const itemsContainer = elem.querySelector('.itemsContainer');
itemsContainer.fetchData = getLatestRecordingsFetchFn(apiClient.serverId(), activeRecordingsOnly); itemsContainer.fetchData = getLatestRecordingsFetchFn(apiClient.serverId(), activeRecordingsOnly);
itemsContainer.getItemsHtml = getLatestRecordingItemsHtml(activeRecordingsOnly); itemsContainer.getItemsHtml = getLatestRecordingItemsHtml(activeRecordingsOnly);
itemsContainer.parentContainer = elem; itemsContainer.parentContainer = elem;
} }
return { export default {
loadLibraryTiles: loadLibraryTiles, loadLibraryTiles: loadLibraryTiles,
getDefaultSection: getDefaultSection, getDefaultSection: getDefaultSection,
loadSections: loadSections, loadSections: loadSections,
destroySections: destroySections, destroySections: destroySections,
pause: pause, pause: pause,
resume: resume resume: resume
}; };
});
/* eslint-enable indent */

View file

@ -1,17 +1,20 @@
define(['appSettings', 'browser', 'events'], function (appSettings, browser, events) { /* eslint-disable indent */
'use strict';
function getSavedVolume() { import appSettings from 'appSettings' ;
import browser from 'browser';
import events from 'events';
export function getSavedVolume() {
return appSettings.get('volume') || 1; return appSettings.get('volume') || 1;
} }
function saveVolume(value) { export function saveVolume(value) {
if (value) { if (value) {
appSettings.set('volume', value); appSettings.set('volume', value);
} }
} }
function getCrossOriginValue(mediaSource) { export function getCrossOriginValue(mediaSource) {
if (mediaSource.IsRemote) { if (mediaSource.IsRemote) {
return null; return null;
} }
@ -30,34 +33,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
return false; return false;
} }
function enableHlsShakaPlayer(item, mediaSource, mediaType) { export function enableHlsJsPlayer(runTimeTicks, mediaType) {
/* eslint-disable-next-line compat/compat */
if (!!window.MediaSource && !!MediaSource.isTypeSupported) {
if (canPlayNativeHls()) {
if (browser.edge && mediaType === 'Video') {
return true;
}
// simple playback should use the native support
if (mediaSource.RunTimeTicks) {
//if (!browser.edge) {
//return false;
//}
}
//return false;
}
return true;
}
return false;
}
function enableHlsJsPlayer(runTimeTicks, mediaType) {
if (window.MediaSource == null) { if (window.MediaSource == null) {
return false; return false;
} }
@ -73,7 +49,6 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
} }
if (canPlayNativeHls()) { if (canPlayNativeHls()) {
// Having trouble with chrome's native support and transcoded music // Having trouble with chrome's native support and transcoded music
if (browser.android && mediaType === 'Audio') { if (browser.android && mediaType === 'Audio') {
return true; return true;
@ -98,8 +73,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
var recoverDecodingErrorDate; var recoverDecodingErrorDate;
var recoverSwapAudioCodecDate; var recoverSwapAudioCodecDate;
function handleHlsJsMediaError(instance, reject) { export function handleHlsJsMediaError(instance, reject) {
var hlsPlayer = instance._hlsPlayer; var hlsPlayer = instance._hlsPlayer;
if (!hlsPlayer) { if (!hlsPlayer) {
@ -134,8 +108,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
} }
} }
function onErrorInternal(instance, type) { export function onErrorInternal(instance, type) {
// Needed for video // Needed for video
if (instance.destroyCustomTrack) { if (instance.destroyCustomTrack) {
instance.destroyCustomTrack(instance._mediaElement); instance.destroyCustomTrack(instance._mediaElement);
@ -148,7 +121,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
]); ]);
} }
function isValidDuration(duration) { export function isValidDuration(duration) {
if (duration && !isNaN(duration) && duration !== Number.POSITIVE_INFINITY && duration !== Number.NEGATIVE_INFINITY) { if (duration && !isNaN(duration) && duration !== Number.POSITIVE_INFINITY && duration !== Number.NEGATIVE_INFINITY) {
return true; return true;
} }
@ -162,13 +135,10 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
} }
} }
function seekOnPlaybackStart(instance, element, ticks, onMediaReady) { export function seekOnPlaybackStart(instance, element, ticks, onMediaReady) {
var seconds = (ticks || 0) / 10000000; var seconds = (ticks || 0) / 10000000;
if (seconds) { if (seconds) {
var src = (instance.currentSrc() || '').toLowerCase();
// Appending #t=xxx to the query string doesn't seem to work with HLS // Appending #t=xxx to the query string doesn't seem to work with HLS
// For plain video files, not all browsers support it either // For plain video files, not all browsers support it either
@ -200,12 +170,9 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
} }
} }
function applySrc(elem, src, options) { export function applySrc(elem, src, options) {
if (window.Windows && options.mediaSource && options.mediaSource.IsLocal) { if (window.Windows && options.mediaSource && options.mediaSource.IsLocal) {
return Windows.Storage.StorageFile.getFileFromPathAsync(options.url).then(function (file) { return Windows.Storage.StorageFile.getFileFromPathAsync(options.url).then(function (file) {
var playlist = new Windows.Media.Playback.MediaPlaybackList(); var playlist = new Windows.Media.Playback.MediaPlaybackList();
var source1 = Windows.Media.Core.MediaSource.createFromStorageFile(file); var source1 = Windows.Media.Core.MediaSource.createFromStorageFile(file);
@ -214,9 +181,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
elem.src = URL.createObjectURL(playlist, { oneTimeOnly: true }); elem.src = URL.createObjectURL(playlist, { oneTimeOnly: true });
return Promise.resolve(); return Promise.resolve();
}); });
} else { } else {
elem.src = src; elem.src = src;
} }
@ -224,18 +189,15 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
} }
function onSuccessfulPlay(elem, onErrorFn) { function onSuccessfulPlay(elem, onErrorFn) {
elem.addEventListener('error', onErrorFn); elem.addEventListener('error', onErrorFn);
} }
function playWithPromise(elem, onErrorFn) { export function playWithPromise(elem, onErrorFn) {
try { try {
var promise = elem.play(); var promise = elem.play();
if (promise && promise.then) { if (promise && promise.then) {
// Chrome now returns a promise // Chrome now returns a promise
return promise.catch(function (e) { return promise.catch(function (e) {
var errorName = (e.name || '').toLowerCase(); var errorName = (e.name || '').toLowerCase();
// safari uses aborterror // safari uses aborterror
if (errorName === 'notallowederror' || if (errorName === 'notallowederror' ||
@ -256,8 +218,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
} }
} }
function destroyCastPlayer(instance) { export function destroyCastPlayer(instance) {
var player = instance._castPlayer; var player = instance._castPlayer;
if (player) { if (player) {
try { try {
@ -270,20 +231,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
} }
} }
function destroyShakaPlayer(instance) { export function destroyHlsPlayer(instance) {
var player = instance._shakaPlayer;
if (player) {
try {
player.destroy();
} catch (err) {
console.error(err);
}
instance._shakaPlayer = null;
}
}
function destroyHlsPlayer(instance) {
var player = instance._hlsPlayer; var player = instance._hlsPlayer;
if (player) { if (player) {
try { try {
@ -296,7 +244,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
} }
} }
function destroyFlvPlayer(instance) { export function destroyFlvPlayer(instance) {
var player = instance._flvPlayer; var player = instance._flvPlayer;
if (player) { if (player) {
try { try {
@ -311,11 +259,9 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
} }
} }
function bindEventsToHlsPlayer(instance, hls, elem, onErrorFn, resolve, reject) { export function bindEventsToHlsPlayer(instance, hls, elem, onErrorFn, resolve, reject) {
hls.on(Hls.Events.MANIFEST_PARSED, function () { hls.on(Hls.Events.MANIFEST_PARSED, function () {
playWithPromise(elem, onErrorFn).then(resolve, function () { playWithPromise(elem, onErrorFn).then(resolve, function () {
if (reject) { if (reject) {
reject(); reject();
reject = null; reject = null;
@ -324,14 +270,12 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
}); });
hls.on(Hls.Events.ERROR, function (event, data) { hls.on(Hls.Events.ERROR, function (event, data) {
console.error('HLS Error: Type: ' + data.type + ' Details: ' + (data.details || '') + ' Fatal: ' + (data.fatal || false)); console.error('HLS Error: Type: ' + data.type + ' Details: ' + (data.details || '') + ' Fatal: ' + (data.fatal || false));
switch (data.type) { switch (data.type) {
case Hls.ErrorTypes.NETWORK_ERROR: case Hls.ErrorTypes.NETWORK_ERROR:
// try to recover network error // try to recover network error
if (data.response && data.response.code && data.response.code >= 400) { if (data.response && data.response.code && data.response.code >= 400) {
console.debug('hls.js response error code: ' + data.response.code); console.debug('hls.js response error code: ' + data.response.code);
// Trigger failure differently depending on whether this is prior to start of playback, or after // Trigger failure differently depending on whether this is prior to start of playback, or after
@ -345,7 +289,6 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
} }
return; return;
} }
break; break;
@ -358,7 +301,6 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
case Hls.ErrorTypes.NETWORK_ERROR: case Hls.ErrorTypes.NETWORK_ERROR:
if (data.response && data.response.code === 0) { if (data.response && data.response.code === 0) {
// This could be a CORS error related to access control response headers // This could be a CORS error related to access control response headers
console.debug('hls.js response error code: ' + data.response.code); console.debug('hls.js response error code: ' + data.response.code);
@ -403,8 +345,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
}); });
} }
function onEndedInternal(instance, elem, onErrorFn) { export function onEndedInternal(instance, elem, onErrorFn) {
elem.removeEventListener('error', onErrorFn); elem.removeEventListener('error', onErrorFn);
elem.src = ''; elem.src = '';
@ -413,7 +354,6 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
destroyHlsPlayer(instance); destroyHlsPlayer(instance);
destroyFlvPlayer(instance); destroyFlvPlayer(instance);
destroyShakaPlayer(instance);
destroyCastPlayer(instance); destroyCastPlayer(instance);
var stopInfo = { var stopInfo = {
@ -427,8 +367,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
instance._currentPlayOptions = null; instance._currentPlayOptions = null;
} }
function getBufferedRanges(instance, elem) { export function getBufferedRanges(instance, elem) {
var ranges = []; var ranges = [];
var seekable = elem.buffered || []; var seekable = elem.buffered || [];
@ -441,7 +380,6 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
offset = offset || 0; offset = offset || 0;
for (var i = 0, length = seekable.length; i < length; i++) { for (var i = 0, length = seekable.length; i < length; i++) {
var start = seekable.start(i); var start = seekable.start(i);
var end = seekable.end(i); var end = seekable.end(i);
@ -462,23 +400,4 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
return ranges; return ranges;
} }
return { /* eslint-enable indent */
getSavedVolume: getSavedVolume,
saveVolume: saveVolume,
enableHlsJsPlayer: enableHlsJsPlayer,
enableHlsShakaPlayer: enableHlsShakaPlayer,
handleHlsJsMediaError: handleHlsJsMediaError,
isValidDuration: isValidDuration,
onErrorInternal: onErrorInternal,
seekOnPlaybackStart: seekOnPlaybackStart,
applySrc: applySrc,
playWithPromise: playWithPromise,
destroyHlsPlayer: destroyHlsPlayer,
destroyFlvPlayer: destroyFlvPlayer,
destroyCastPlayer: destroyCastPlayer,
bindEventsToHlsPlayer: bindEventsToHlsPlayer,
onEndedInternal: onEndedInternal,
getCrossOriginValue: getCrossOriginValue,
getBufferedRanges: getBufferedRanges
};
});

View file

@ -1,24 +1,37 @@
define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader', 'browser', 'layoutManager', 'scrollHelper', 'globalize', 'require', 'emby-checkbox', 'paper-icon-button-light', 'emby-button', 'formDialogStyle', 'cardStyle'], function (dom, loading, appHost, dialogHelper, connectionManager, imageLoader, browser, layoutManager, scrollHelper, globalize, require) { import dom from 'dom';
'use strict'; import loading from 'loading';
import appHost from 'apphost';
import dialogHelper from 'dialogHelper';
import imageLoader from 'imageLoader';
import browser from 'browser';
import layoutManager from 'layoutManager';
import scrollHelper from 'scrollHelper';
import globalize from 'globalize';
import 'emby-checkbox';
import 'paper-icon-button-light';
import 'emby-button';
import 'formDialogStyle';
import 'cardStyle';
var enableFocusTransform = !browser.slow && !browser.edge; /* eslint-disable indent */
var currentItemId; const enableFocusTransform = !browser.slow && !browser.edge;
var currentItemType;
var currentResolve; let currentItemId;
var currentReject; let currentItemType;
var hasChanges = false; let currentResolve;
let currentReject;
let hasChanges = false;
// These images can be large and we're seeing memory problems in safari // These images can be large and we're seeing memory problems in safari
var browsableImagePageSize = browser.slow ? 6 : 30; const browsableImagePageSize = browser.slow ? 6 : 30;
var browsableImageStartIndex = 0; let browsableImageStartIndex = 0;
var browsableImageType = 'Primary'; let browsableImageType = 'Primary';
var selectedProvider; let selectedProvider;
function getBaseRemoteOptions() { function getBaseRemoteOptions() {
const options = {};
var options = {};
options.itemId = currentItemId; options.itemId = currentItemId;
@ -26,58 +39,53 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
} }
function reloadBrowsableImages(page, apiClient) { function reloadBrowsableImages(page, apiClient) {
loading.show(); loading.show();
var options = getBaseRemoteOptions(); const options = getBaseRemoteOptions();
options.type = browsableImageType; options.type = browsableImageType;
options.startIndex = browsableImageStartIndex; options.startIndex = browsableImageStartIndex;
options.limit = browsableImagePageSize; options.limit = browsableImagePageSize;
options.IncludeAllLanguages = page.querySelector('#chkAllLanguages').checked; options.IncludeAllLanguages = page.querySelector('#chkAllLanguages').checked;
var provider = selectedProvider || ''; const provider = selectedProvider || '';
if (provider) { if (provider) {
options.ProviderName = provider; options.ProviderName = provider;
} }
apiClient.getAvailableRemoteImages(options).then(function (result) { apiClient.getAvailableRemoteImages(options).then(function (result) {
renderRemoteImages(page, apiClient, result, browsableImageType, options.startIndex, options.limit); renderRemoteImages(page, apiClient, result, browsableImageType, options.startIndex, options.limit);
page.querySelector('#selectBrowsableImageType').value = browsableImageType; page.querySelector('#selectBrowsableImageType').value = browsableImageType;
var providersHtml = result.Providers.map(function (p) { const providersHtml = result.Providers.map(function (p) {
return '<option value="' + p + '">' + p + '</option>'; return '<option value="' + p + '">' + p + '</option>';
}); });
var selectImageProvider = page.querySelector('#selectImageProvider'); const selectImageProvider = page.querySelector('#selectImageProvider');
selectImageProvider.innerHTML = '<option value="">' + globalize.translate('All') + '</option>' + providersHtml; selectImageProvider.innerHTML = '<option value="">' + globalize.translate('All') + '</option>' + providersHtml;
selectImageProvider.value = provider; selectImageProvider.value = provider;
loading.hide(); loading.hide();
}); });
} }
function renderRemoteImages(page, apiClient, imagesResult, imageType, startIndex, limit) { function renderRemoteImages(page, apiClient, imagesResult, imageType, startIndex, limit) {
page.querySelector('.availableImagesPaging').innerHTML = getPagingHtml(startIndex, limit, imagesResult.TotalRecordCount); page.querySelector('.availableImagesPaging').innerHTML = getPagingHtml(startIndex, limit, imagesResult.TotalRecordCount);
var html = ''; let html = '';
for (var i = 0, length = imagesResult.Images.length; i < length; i++) {
for (let i = 0, length = imagesResult.Images.length; i < length; i++) {
html += getRemoteImageHtml(imagesResult.Images[i], imageType, apiClient); html += getRemoteImageHtml(imagesResult.Images[i], imageType, apiClient);
} }
var availableImagesList = page.querySelector('.availableImagesList'); const availableImagesList = page.querySelector('.availableImagesList');
availableImagesList.innerHTML = html; availableImagesList.innerHTML = html;
imageLoader.lazyChildren(availableImagesList); imageLoader.lazyChildren(availableImagesList);
var btnNextPage = page.querySelector('.btnNextPage'); const btnNextPage = page.querySelector('.btnNextPage');
var btnPreviousPage = page.querySelector('.btnPreviousPage'); const btnPreviousPage = page.querySelector('.btnPreviousPage');
if (btnNextPage) { if (btnNextPage) {
btnNextPage.addEventListener('click', function () { btnNextPage.addEventListener('click', function () {
@ -92,23 +100,21 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
reloadBrowsableImages(page, apiClient); reloadBrowsableImages(page, apiClient);
}); });
} }
} }
function getPagingHtml(startIndex, limit, totalRecordCount) { function getPagingHtml(startIndex, limit, totalRecordCount) {
let html = '';
var html = ''; const recordsEnd = Math.min(startIndex + limit, totalRecordCount);
var recordsEnd = Math.min(startIndex + limit, totalRecordCount);
// 20 is the minimum page size // 20 is the minimum page size
var showControls = totalRecordCount > limit; const showControls = totalRecordCount > limit;
html += '<div class="listPaging">'; html += '<div class="listPaging">';
html += '<span style="margin-right: 10px;">'; html += '<span style="margin-right: 10px;">';
var startAtDisplay = totalRecordCount ? startIndex + 1 : 0; const startAtDisplay = totalRecordCount ? startIndex + 1 : 0;
html += globalize.translate('ListPaging', startAtDisplay, recordsEnd, totalRecordCount); html += globalize.translate('ListPaging', startAtDisplay, recordsEnd, totalRecordCount);
html += '</span>'; html += '</span>';
@ -127,7 +133,7 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
} }
function downloadRemoteImage(page, apiClient, url, type, provider) { function downloadRemoteImage(page, apiClient, url, type, provider) {
var options = getBaseRemoteOptions(); const options = getBaseRemoteOptions();
options.Type = type; options.Type = type;
options.ImageUrl = url; options.ImageUrl = url;
@ -136,9 +142,8 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
loading.show(); loading.show();
apiClient.downloadRemoteImage(options).then(function () { apiClient.downloadRemoteImage(options).then(function () {
hasChanges = true; hasChanges = true;
var dlg = dom.parentWithClass(page, 'dialog'); const dlg = dom.parentWithClass(page, 'dialog');
dialogHelper.close(dlg); dialogHelper.close(dlg);
}); });
} }
@ -148,17 +153,17 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
} }
function getRemoteImageHtml(image, imageType, apiClient) { function getRemoteImageHtml(image, imageType, apiClient) {
var tagName = layoutManager.tv ? 'button' : 'div'; const tagName = layoutManager.tv ? 'button' : 'div';
var enableFooterButtons = !layoutManager.tv; const enableFooterButtons = !layoutManager.tv;
// TODO move card creation code to Card component // TODO move card creation code to Card component
var html = ''; let html = '';
var cssClass = 'card scalableCard imageEditorCard'; let cssClass = 'card scalableCard imageEditorCard';
var cardBoxCssClass = 'cardBox visualCardBox'; const cardBoxCssClass = 'cardBox visualCardBox';
var shape = 'backdrop'; let shape;
if (imageType === 'Backdrop' || imageType === 'Art' || imageType === 'Thumb' || imageType === 'Logo') { if (imageType === 'Backdrop' || imageType === 'Art' || imageType === 'Thumb' || imageType === 'Logo') {
shape = 'backdrop'; shape = 'backdrop';
} else if (imageType === 'Banner') { } else if (imageType === 'Banner') {
@ -166,7 +171,6 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
} else if (imageType === 'Disc') { } else if (imageType === 'Disc') {
shape = 'square'; shape = 'square';
} else { } else {
if (currentItemType === 'Episode') { if (currentItemType === 'Episode') {
shape = 'backdrop'; shape = 'backdrop';
} else if (currentItemType === 'MusicAlbum' || currentItemType === 'MusicArtist') { } else if (currentItemType === 'MusicAlbum' || currentItemType === 'MusicArtist') {
@ -217,19 +221,16 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
html += '<div class="cardText cardTextCentered">' + image.ProviderName + '</div>'; html += '<div class="cardText cardTextCentered">' + image.ProviderName + '</div>';
if (image.Width || image.Height || image.Language) { if (image.Width || image.Height || image.Language) {
html += '<div class="cardText cardText-secondary cardTextCentered">'; html += '<div class="cardText cardText-secondary cardTextCentered">';
if (image.Width && image.Height) { if (image.Width && image.Height) {
html += image.Width + ' x ' + image.Height; html += image.Width + ' x ' + image.Height;
if (image.Language) { if (image.Language) {
html += ' • ' + image.Language; html += ' • ' + image.Language;
} }
} else { } else {
if (image.Language) { if (image.Language) {
html += image.Language; html += image.Language;
} }
} }
@ -238,13 +239,11 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
} }
if (image.CommunityRating != null) { if (image.CommunityRating != null) {
html += '<div class="cardText cardText-secondary cardTextCentered">'; html += '<div class="cardText cardText-secondary cardTextCentered">';
if (image.RatingType === 'Likes') { if (image.RatingType === 'Likes') {
html += image.CommunityRating + (image.CommunityRating === 1 ? ' like' : ' likes'); html += image.CommunityRating + (image.CommunityRating === 1 ? ' like' : ' likes');
} else { } else {
if (image.CommunityRating) { if (image.CommunityRating) {
html += image.CommunityRating.toFixed(1); html += image.CommunityRating.toFixed(1);
@ -270,7 +269,6 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
// end footer // end footer
html += '</div>'; html += '</div>';
//html += '</div>';
html += '</' + tagName + '>'; html += '</' + tagName + '>';
@ -287,7 +285,6 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
}); });
page.querySelector('#selectImageProvider').addEventListener('change', function () { page.querySelector('#selectImageProvider').addEventListener('change', function () {
browsableImageStartIndex = 0; browsableImageStartIndex = 0;
selectedProvider = this.value; selectedProvider = this.value;
@ -295,22 +292,20 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
}); });
page.querySelector('#chkAllLanguages').addEventListener('change', function () { page.querySelector('#chkAllLanguages').addEventListener('change', function () {
browsableImageStartIndex = 0; browsableImageStartIndex = 0;
reloadBrowsableImages(page, apiClient); reloadBrowsableImages(page, apiClient);
}); });
page.addEventListener('click', function (e) { page.addEventListener('click', function (e) {
const btnDownloadRemoteImage = dom.parentWithClass(e.target, 'btnDownloadRemoteImage');
var btnDownloadRemoteImage = dom.parentWithClass(e.target, 'btnDownloadRemoteImage');
if (btnDownloadRemoteImage) { if (btnDownloadRemoteImage) {
var card = dom.parentWithClass(btnDownloadRemoteImage, 'card'); const card = dom.parentWithClass(btnDownloadRemoteImage, 'card');
downloadRemoteImage(page, apiClient, card.getAttribute('data-imageurl'), card.getAttribute('data-imagetype'), card.getAttribute('data-imageprovider')); downloadRemoteImage(page, apiClient, card.getAttribute('data-imageurl'), card.getAttribute('data-imagetype'), card.getAttribute('data-imageprovider'));
return; return;
} }
var btnImageCard = dom.parentWithClass(e.target, 'btnImageCard'); const btnImageCard = dom.parentWithClass(e.target, 'btnImageCard');
if (btnImageCard) { if (btnImageCard) {
downloadRemoteImage(page, apiClient, btnImageCard.getAttribute('data-imageurl'), btnImageCard.getAttribute('data-imagetype'), btnImageCard.getAttribute('data-imageprovider')); downloadRemoteImage(page, apiClient, btnImageCard.getAttribute('data-imageurl'), btnImageCard.getAttribute('data-imagetype'), btnImageCard.getAttribute('data-imageprovider'));
} }
@ -320,14 +315,13 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
function showEditor(itemId, serverId, itemType) { function showEditor(itemId, serverId, itemType) {
loading.show(); loading.show();
require(['text!./imageDownloader.template.html'], function (template) { import('text!./imageDownloader.template.html').then(({default: template}) => {
const apiClient = window.connectionManager.getApiClient(serverId);
var apiClient = connectionManager.getApiClient(serverId);
currentItemId = itemId; currentItemId = itemId;
currentItemType = itemType; currentItemType = itemType;
var dialogOptions = { const dialogOptions = {
removeOnClose: true removeOnClose: true
}; };
@ -337,9 +331,9 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
dialogOptions.size = 'small'; dialogOptions.size = 'small';
} }
var dlg = dialogHelper.createDialog(dialogOptions); const dlg = dialogHelper.createDialog(dialogOptions);
dlg.innerHTML = globalize.translateDocument(template, 'core'); dlg.innerHTML = globalize.translateHtml(template, 'core');
if (layoutManager.tv) { if (layoutManager.tv) {
scrollHelper.centerFocus.on(dlg, false); scrollHelper.centerFocus.on(dlg, false);
@ -350,11 +344,10 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
dialogHelper.open(dlg); dialogHelper.open(dlg);
var editorContent = dlg.querySelector('.formDialogContent'); const editorContent = dlg.querySelector('.formDialogContent');
initEditor(editorContent, apiClient); initEditor(editorContent, apiClient);
dlg.querySelector('.btnCancel').addEventListener('click', function () { dlg.querySelector('.btnCancel').addEventListener('click', function () {
dialogHelper.close(dlg); dialogHelper.close(dlg);
}); });
@ -363,7 +356,7 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
} }
function onDialogClosed() { function onDialogClosed() {
var dlg = this; const dlg = this;
if (layoutManager.tv) { if (layoutManager.tv) {
scrollHelper.centerFocus.off(dlg, false); scrollHelper.centerFocus.off(dlg, false);
@ -377,8 +370,7 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
} }
} }
return { export function show(itemId, serverId, itemType, imageType) {
show: function (itemId, serverId, itemType, imageType) {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
currentResolve = resolve; currentResolve = resolve;
currentReject = reject; currentReject = reject;
@ -386,9 +378,12 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
browsableImageStartIndex = 0; browsableImageStartIndex = 0;
browsableImageType = imageType || 'Primary'; browsableImageType = imageType || 'Primary';
selectedProvider = null; selectedProvider = null;
showEditor(itemId, serverId, itemType); showEditor(itemId, serverId, itemType);
}); });
} }
};
}); export default {
show: show
};
/* eslint-enable indent */

View file

@ -1,16 +1,27 @@
define(['globalize', 'dom', 'dialogHelper', 'emby-checkbox', 'emby-select', 'emby-input'], function (globalize, dom, dialogHelper) { /* eslint-disable indent */
'use strict';
/**
* Module for image Options Editor.
* @module components/imageOptionsEditor/imageOptionsEditor
*/
import globalize from 'globalize';
import dom from 'dom';
import dialogHelper from 'dialogHelper';
import 'emby-checkbox';
import 'emby-select';
import 'emby-input';
function getDefaultImageConfig(itemType, type) { function getDefaultImageConfig(itemType, type) {
return { return {
Type: type, Type: type,
MinWidth: 0, MinWidth: 0,
Limit: 'Primary' === type ? 1 : 0 Limit: type === 'Primary' ? 1 : 0
}; };
} }
function findImageOptions(imageOptions, type) { function findImageOptions(imageOptions, type) {
return imageOptions.filter(function (i) { return imageOptions.filter(i => {
return i.Type == type; return i.Type == type;
})[0]; })[0];
} }
@ -31,14 +42,14 @@ define(['globalize', 'dom', 'dialogHelper', 'emby-checkbox', 'emby-select', 'emb
} }
function loadValues(context, itemType, options, availableOptions) { function loadValues(context, itemType, options, availableOptions) {
var supportedImageTypes = availableOptions.SupportedImageTypes || []; const supportedImageTypes = availableOptions.SupportedImageTypes || [];
setVisibilityOfBackdrops(context.querySelector('.backdropFields'), -1 != supportedImageTypes.indexOf('Backdrop')); setVisibilityOfBackdrops(context.querySelector('.backdropFields'), supportedImageTypes.includes('Backdrop'));
setVisibilityOfBackdrops(context.querySelector('.screenshotFields'), -1 != supportedImageTypes.indexOf('Screenshot')); setVisibilityOfBackdrops(context.querySelector('.screenshotFields'), supportedImageTypes.includes('Screenshot'));
Array.prototype.forEach.call(context.querySelectorAll('.imageType'), function (i) { Array.prototype.forEach.call(context.querySelectorAll('.imageType'), i => {
var imageType = i.getAttribute('data-imagetype'); const imageType = i.getAttribute('data-imagetype');
var container = dom.parentWithTag(i, 'LABEL'); const container = dom.parentWithTag(i, 'LABEL');
if (-1 == supportedImageTypes.indexOf(imageType)) { if (!supportedImageTypes.includes(imageType)) {
container.classList.add('hide'); container.classList.add('hide');
} else { } else {
container.classList.remove('hide'); container.classList.remove('hide');
@ -50,16 +61,16 @@ define(['globalize', 'dom', 'dialogHelper', 'emby-checkbox', 'emby-select', 'emb
i.checked = false; i.checked = false;
} }
}); });
var backdropConfig = getImageConfig(options, availableOptions, 'Backdrop', itemType); const backdropConfig = getImageConfig(options, availableOptions, 'Backdrop', itemType);
context.querySelector('#txtMaxBackdrops').value = backdropConfig.Limit; context.querySelector('#txtMaxBackdrops').value = backdropConfig.Limit;
context.querySelector('#txtMinBackdropDownloadWidth').value = backdropConfig.MinWidth; context.querySelector('#txtMinBackdropDownloadWidth').value = backdropConfig.MinWidth;
var screenshotConfig = getImageConfig(options, availableOptions, 'Screenshot', itemType); const screenshotConfig = getImageConfig(options, availableOptions, 'Screenshot', itemType);
context.querySelector('#txtMaxScreenshots').value = screenshotConfig.Limit; context.querySelector('#txtMaxScreenshots').value = screenshotConfig.Limit;
context.querySelector('#txtMinScreenshotDownloadWidth').value = screenshotConfig.MinWidth; context.querySelector('#txtMinScreenshotDownloadWidth').value = screenshotConfig.MinWidth;
} }
function saveValues(context, options) { function saveValues(context, options) {
options.ImageOptions = Array.prototype.map.call(context.querySelectorAll('.imageType:not(.hide)'), function (c) { options.ImageOptions = Array.prototype.map.call(context.querySelectorAll('.imageType:not(.hide)'), c => {
return { return {
Type: c.getAttribute('data-imagetype'), Type: c.getAttribute('data-imagetype'),
Limit: c.checked ? 1 : 0, Limit: c.checked ? 1 : 0,
@ -78,35 +89,36 @@ define(['globalize', 'dom', 'dialogHelper', 'emby-checkbox', 'emby-select', 'emb
}); });
} }
function editor() { async function showEditor(itemType, options, availableOptions) {
this.show = function (itemType, options, availableOptions) { const response = await fetch('components/imageOptionsEditor/imageOptionsEditor.template.html');
return new Promise(function (resolve, reject) { const template = await response.text();
var xhr = new XMLHttpRequest();
xhr.open('GET', 'components/imageOptionsEditor/imageOptionsEditor.template.html', true);
xhr.onload = function (e) {
var template = this.response;
var dlg = dialogHelper.createDialog({ var dlg = dialogHelper.createDialog({
size: 'small', size: 'small',
removeOnClose: true, removeOnClose: true,
scrollY: false scrollY: false
}); });
dlg.classList.add('formDialog'); dlg.classList.add('formDialog');
dlg.innerHTML = globalize.translateDocument(template); dlg.innerHTML = globalize.translateHtml(template);
dlg.addEventListener('close', function () { dlg.addEventListener('close', function () {
saveValues(dlg, options); saveValues(dlg, options);
}); });
loadValues(dlg, itemType, options, availableOptions); loadValues(dlg, itemType, options, availableOptions);
dialogHelper.open(dlg).then(resolve, resolve); dialogHelper.open(dlg).then(() => {
return;
}).catch(() => {
return;
});
dlg.querySelector('.btnCancel').addEventListener('click', function () { dlg.querySelector('.btnCancel').addEventListener('click', function () {
dialogHelper.close(dlg); dialogHelper.close(dlg);
}); });
};
xhr.send();
});
};
} }
return editor; export class editor {
}); constructor() {
this.show = showEditor;
}
}
/* eslint-enable indent */
export default editor;

View file

@ -15,41 +15,41 @@
<label> <label>
<input type="checkbox" is="emby-checkbox" class="imageType" data-imagetype="Primary" /> <input type="checkbox" is="emby-checkbox" class="imageType" data-imagetype="Primary" />
<span>${OptionDownloadPrimaryImage}</span> <span>${Primary}</span>
</label> </label>
<label> <label>
<input type="checkbox" is="emby-checkbox" class="imageType" data-imagetype="Art" /> <input type="checkbox" is="emby-checkbox" class="imageType" data-imagetype="Art" />
<span>${OptionDownloadArtImage}</span> <span>${Art}</span>
</label> </label>
<label> <label>
<input type="checkbox" is="emby-checkbox" class="imageType" data-imagetype="BoxRear" /> <input type="checkbox" is="emby-checkbox" class="imageType" data-imagetype="BoxRear" />
<span>${OptionDownloadBackImage}</span> <span>${Back}</span>
</label> </label>
<label> <label>
<input type="checkbox" is="emby-checkbox" class="imageType" data-imagetype="Banner" /> <input type="checkbox" is="emby-checkbox" class="imageType" data-imagetype="Banner" />
<span>${OptionDownloadBannerImage}</span> <span>${Banner}</span>
</label> </label>
<label> <label>
<input type="checkbox" is="emby-checkbox" class="imageType" data-imagetype="Box" /> <input type="checkbox" is="emby-checkbox" class="imageType" data-imagetype="Box" />
<span>${OptionDownloadBoxImage}</span> <span>${Box}</span>
</label> </label>
<label> <label>
<input type="checkbox" is="emby-checkbox" class="imageType" data-imagetype="Disc" /> <input type="checkbox" is="emby-checkbox" class="imageType" data-imagetype="Disc" />
<span>${OptionDownloadDiscImage}</span> <span>${Disc}</span>
</label> </label>
<label> <label>
<input type="checkbox" is="emby-checkbox" class="imageType" data-imagetype="Logo" /> <input type="checkbox" is="emby-checkbox" class="imageType" data-imagetype="Logo" />
<span>${OptionDownloadLogoImage}</span> <span>${Logo}</span>
</label> </label>
<label> <label>
<input type="checkbox" is="emby-checkbox" class="imageType" data-imagetype="Menu" /> <input type="checkbox" is="emby-checkbox" class="imageType" data-imagetype="Menu" />
<span>${OptionDownloadMenuImage}</span> <span>${Menu}</span>
</label> </label>
<label> <label>
<input type="checkbox" is="emby-checkbox" class="imageType" data-imagetype="Thumb" /> <input type="checkbox" is="emby-checkbox" class="imageType" data-imagetype="Thumb" />
<span>${OptionDownloadThumbImage}</span> <span>${Thumb}</span>
</label> </label>
</div> </div>
</div> </div>

View file

@ -1,25 +1,39 @@
define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', 'layoutManager', 'globalize', 'require', 'emby-button', 'emby-select', 'formDialogStyle', 'css!./style'], function (dialogHelper, connectionManager, dom, loading, scrollHelper, layoutManager, globalize, require) { /* eslint-disable indent */
'use strict';
var currentItemId; /**
var currentServerId; * Module for imageUploader.
var currentFile; * @module components/imageUploader/imageUploader
var hasChanges = false; */
import dialogHelper from 'dialogHelper';
import dom from 'dom';
import loading from 'loading';
import scrollHelper from 'scrollHelper';
import layoutManager from 'layoutManager';
import globalize from 'globalize';
import 'emby-button';
import 'emby-select';
import 'formDialogStyle';
import 'css!./style';
let currentItemId;
let currentServerId;
let currentFile;
let hasChanges = false;
function onFileReaderError(evt) { function onFileReaderError(evt) {
loading.hide(); loading.hide();
switch (evt.target.error.code) { switch (evt.target.error.code) {
case evt.target.error.NOT_FOUND_ERR: case evt.target.error.NOT_FOUND_ERR:
require(['toast'], function (toast) { import('toast').then(({default: toast}) => {
toast(globalize.translate('MessageFileReadError')); toast(globalize.translate('MessageFileReadError'));
}); });
break; break;
case evt.target.error.ABORT_ERR: case evt.target.error.ABORT_ERR:
break; // noop break; // noop
default: default:
require(['toast'], function (toast) { import('toast').then(({default: toast}) => {
toast(globalize.translate('MessageFileReadError')); toast(globalize.translate('MessageFileReadError'));
}); });
break; break;
@ -27,8 +41,7 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
} }
function setFiles(page, files) { function setFiles(page, files) {
const file = files[0];
var file = files[0];
if (!file || !file.type.match('image.*')) { if (!file || !file.type.match('image.*')) {
page.querySelector('#imageOutput').innerHTML = ''; page.querySelector('#imageOutput').innerHTML = '';
@ -39,23 +52,22 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
currentFile = file; currentFile = file;
var reader = new FileReader(); const reader = new FileReader();
reader.onerror = onFileReaderError; reader.onerror = onFileReaderError;
reader.onloadstart = function () { reader.onloadstart = () => {
page.querySelector('#fldUpload').classList.add('hide'); page.querySelector('#fldUpload').classList.add('hide');
}; };
reader.onabort = function () { reader.onabort = () => {
loading.hide(); loading.hide();
console.debug('File read cancelled'); console.debug('File read cancelled');
}; };
// Closure to capture the file information. // Closure to capture the file information.
reader.onload = (function (theFile) { reader.onload = (theFile => {
return function (e) { return e => {
// Render thumbnail. // Render thumbnail.
var html = ['<img style="max-width:100%;max-height:100%;" src="', e.target.result, '" title="', escape(theFile.name), '"/>'].join(''); const html = ['<img style="max-width:100%;max-height:100%;" src="', e.target.result, '" title="', escape(theFile.name), '"/>'].join('');
page.querySelector('#imageOutput').innerHTML = html; page.querySelector('#imageOutput').innerHTML = html;
page.querySelector('#dropImageText').classList.add('hide'); page.querySelector('#dropImageText').classList.add('hide');
@ -68,15 +80,14 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
} }
function onSubmit(e) { function onSubmit(e) {
const file = currentFile;
var file = currentFile;
if (!file) { if (!file) {
return false; return false;
} }
if (!file.type.startsWith('image/')) { if (!file.type.startsWith('image/')) {
require(['toast'], function (toast) { import('toast').then(({default: toast}) => {
toast(globalize.translate('MessageImageFileTypeAllowed')); toast(globalize.translate('MessageImageFileTypeAllowed'));
}); });
e.preventDefault(); e.preventDefault();
@ -85,19 +96,18 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
loading.show(); loading.show();
var dlg = dom.parentWithClass(this, 'dialog'); const dlg = dom.parentWithClass(this, 'dialog');
var imageType = dlg.querySelector('#selectImageType').value; const imageType = dlg.querySelector('#selectImageType').value;
if (imageType === 'None') { if (imageType === 'None') {
require(['toast'], function(toast) { import('toast').then(({default: toast}) => {
toast(globalize.translate('MessageImageTypeNotSelected')); toast(globalize.translate('MessageImageTypeNotSelected'));
}); });
e.preventDefault(); e.preventDefault();
return false; return false;
} }
connectionManager.getApiClient(currentServerId).uploadItemImage(currentItemId, imageType, file).then(function () { window.connectionManager.getApiClient(currentServerId).uploadItemImage(currentItemId, imageType, file).then(() => {
dlg.querySelector('#uploadImage').value = ''; dlg.querySelector('#uploadImage').value = '';
loading.hide(); loading.hide();
@ -110,28 +120,25 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
} }
function initEditor(page) { function initEditor(page) {
page.querySelector('form').addEventListener('submit', onSubmit); page.querySelector('form').addEventListener('submit', onSubmit);
page.querySelector('#uploadImage').addEventListener('change', function () { page.querySelector('#uploadImage').addEventListener('change', function () {
setFiles(page, this.files); setFiles(page, this.files);
}); });
page.querySelector('.btnBrowse').addEventListener('click', function () { page.querySelector('.btnBrowse').addEventListener('click', () => {
page.querySelector('#uploadImage').click(); page.querySelector('#uploadImage').click();
}); });
} }
function showEditor(options, resolve, reject) { function showEditor(options, resolve) {
options = options || {}; options = options || {};
require(['text!./imageUploader.template.html'], function (template) { return import('text!./imageUploader.template.html').then(({default: template}) => {
currentItemId = options.itemId; currentItemId = options.itemId;
currentServerId = options.serverId; currentServerId = options.serverId;
var dialogOptions = { const dialogOptions = {
removeOnClose: true removeOnClose: true
}; };
@ -141,19 +148,18 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
dialogOptions.size = 'small'; dialogOptions.size = 'small';
} }
var dlg = dialogHelper.createDialog(dialogOptions); const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog'); dlg.classList.add('formDialog');
dlg.innerHTML = globalize.translateDocument(template, 'core'); dlg.innerHTML = globalize.translateHtml(template, 'core');
if (layoutManager.tv) { if (layoutManager.tv) {
scrollHelper.centerFocus.on(dlg, false); scrollHelper.centerFocus.on(dlg, false);
} }
// Has to be assigned a z-index after the call to .open() // Has to be assigned a z-index after the call to .open()
dlg.addEventListener('close', function () { dlg.addEventListener('close', () => {
if (layoutManager.tv) { if (layoutManager.tv) {
scrollHelper.centerFocus.off(dlg, false); scrollHelper.centerFocus.off(dlg, false);
} }
@ -168,22 +174,21 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
dlg.querySelector('#selectImageType').value = options.imageType || 'Primary'; dlg.querySelector('#selectImageType').value = options.imageType || 'Primary';
dlg.querySelector('.btnCancel').addEventListener('click', function () { dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg); dialogHelper.close(dlg);
}); });
}); });
} }
return { export function show(options) {
show: function (options) { return new Promise(resolve => {
return new Promise(function (resolve, reject) {
hasChanges = false; hasChanges = false;
showEditor(options, resolve, reject); showEditor(options, resolve);
}); });
} }
};
}); /* eslint-enable indent */
export default {
show: show
};

View file

@ -1,14 +1,28 @@
define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', 'focusManager', 'globalize', 'scrollHelper', 'imageLoader', 'require', 'browser', 'apphost', 'cardStyle', 'formDialogStyle', 'emby-button', 'paper-icon-button-light', 'css!./imageeditor'], function (dialogHelper, connectionManager, loading, dom, layoutManager, focusManager, globalize, scrollHelper, imageLoader, require, browser, appHost) { import dialogHelper from 'dialogHelper';
'use strict'; import loading from 'loading';
import dom from 'dom';
import layoutManager from 'layoutManager';
import focusManager from 'focusManager';
import globalize from 'globalize';
import scrollHelper from 'scrollHelper';
import imageLoader from 'imageLoader';
import browser from 'browser';
import appHost from 'apphost';
import 'cardStyle';
import 'formDialogStyle';
import 'emby-button';
import 'paper-icon-button-light';
import 'css!./imageeditor';
var enableFocusTransform = !browser.slow && !browser.edge; /* eslint-disable indent */
var currentItem; const enableFocusTransform = !browser.slow && !browser.edge;
var hasChanges = false;
let currentItem;
let hasChanges = false;
function getBaseRemoteOptions() { function getBaseRemoteOptions() {
const options = {};
var options = {};
options.itemId = currentItem.Id; options.itemId = currentItem.Id;
@ -16,17 +30,15 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
} }
function reload(page, item, focusContext) { function reload(page, item, focusContext) {
loading.show(); loading.show();
var apiClient; let apiClient;
if (item) { if (item) {
apiClient = connectionManager.getApiClient(item.ServerId); apiClient = window.connectionManager.getApiClient(item.ServerId);
reloadItem(page, item, apiClient, focusContext); reloadItem(page, item, apiClient, focusContext);
} else { } else {
apiClient = window.connectionManager.getApiClient(currentItem.ServerId);
apiClient = connectionManager.getApiClient(currentItem.ServerId);
apiClient.getItem(apiClient.getCurrentUserId(), currentItem.Id).then(function (item) { apiClient.getItem(apiClient.getCurrentUserId(), currentItem.Id).then(function (item) {
reloadItem(page, item, apiClient, focusContext); reloadItem(page, item, apiClient, focusContext);
}); });
@ -34,9 +46,8 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
} }
function addListeners(container, className, eventName, fn) { function addListeners(container, className, eventName, fn) {
container.addEventListener(eventName, function (e) { container.addEventListener(eventName, function (e) {
var elem = dom.parentWithClass(e.target, className); const elem = dom.parentWithClass(e.target, className);
if (elem) { if (elem) {
fn.call(elem, e); fn.call(elem, e);
} }
@ -44,14 +55,11 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
} }
function reloadItem(page, item, apiClient, focusContext) { function reloadItem(page, item, apiClient, focusContext) {
currentItem = item; currentItem = item;
apiClient.getRemoteImageProviders(getBaseRemoteOptions()).then(function (providers) { apiClient.getRemoteImageProviders(getBaseRemoteOptions()).then(function (providers) {
var btnBrowseAllImages = page.querySelectorAll('.btnBrowseAllImages'); var btnBrowseAllImages = page.querySelectorAll('.btnBrowseAllImages');
for (var i = 0, length = btnBrowseAllImages.length; i < length; i++) { for (var i = 0, length = btnBrowseAllImages.length; i < length; i++) {
if (providers.length) { if (providers.length) {
btnBrowseAllImages[i].classList.remove('hide'); btnBrowseAllImages[i].classList.remove('hide');
} else { } else {
@ -60,7 +68,6 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
} }
apiClient.getItemImageInfos(currentItem.Id).then(function (imageInfos) { apiClient.getItemImageInfos(currentItem.Id).then(function (imageInfos) {
renderStandardImages(page, apiClient, item, imageInfos, providers); renderStandardImages(page, apiClient, item, imageInfos, providers);
renderBackdrops(page, apiClient, item, imageInfos, providers); renderBackdrops(page, apiClient, item, imageInfos, providers);
renderScreenshots(page, apiClient, item, imageInfos, providers); renderScreenshots(page, apiClient, item, imageInfos, providers);
@ -74,7 +81,6 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
} }
function getImageUrl(item, apiClient, type, index, options) { function getImageUrl(item, apiClient, type, index, options) {
options = options || {}; options = options || {};
options.type = type; options.type = type;
options.index = index; options.index = index;
@ -94,13 +100,12 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
} }
function getCardHtml(image, index, numImages, apiClient, imageProviders, imageSize, tagName, enableFooterButtons) { function getCardHtml(image, index, numImages, apiClient, imageProviders, imageSize, tagName, enableFooterButtons) {
// TODO move card creation code to Card component // TODO move card creation code to Card component
var html = ''; let html = '';
var cssClass = 'card scalableCard imageEditorCard'; let cssClass = 'card scalableCard imageEditorCard';
var cardBoxCssClass = 'cardBox visualCardBox'; const cardBoxCssClass = 'cardBox visualCardBox';
cssClass += ' backdropCard backdropCard-scalable'; cssClass += ' backdropCard backdropCard-scalable';
@ -130,7 +135,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
html += '<div class="cardContent">'; html += '<div class="cardContent">';
var imageUrl = getImageUrl(currentItem, apiClient, image.ImageType, image.ImageIndex, { maxWidth: imageSize }); const imageUrl = getImageUrl(currentItem, apiClient, image.ImageType, image.ImageIndex, { maxWidth: imageSize });
html += '<div class="cardImageContainer" style="background-image:url(\'' + imageUrl + '\');background-position:center center;background-size:contain;"></div>'; html += '<div class="cardImageContainer" style="background-image:url(\'' + imageUrl + '\');background-position:center center;background-size:contain;"></div>';
@ -153,7 +158,6 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
html += '<div class="cardText cardTextCentered">'; html += '<div class="cardText cardTextCentered">';
if (image.ImageType === 'Backdrop' || image.ImageType === 'Screenshot') { if (image.ImageType === 'Backdrop' || image.ImageType === 'Screenshot') {
if (index > 0) { if (index > 0) {
html += '<button type="button" is="paper-icon-button-light" class="btnMoveImage autoSize" data-imagetype="' + image.ImageType + '" data-index="' + image.ImageIndex + '" data-newindex="' + (image.ImageIndex - 1) + '" title="' + globalize.translate('MoveLeft') + '"><span class="material-icons chevron_left"></span></button>'; html += '<button type="button" is="paper-icon-button-light" class="btnMoveImage autoSize" data-imagetype="' + image.ImageType + '" data-index="' + image.ImageIndex + '" data-newindex="' + (image.ImageIndex - 1) + '" title="' + globalize.translate('MoveLeft') + '"><span class="material-icons chevron_left"></span></button>';
} else { } else {
@ -183,13 +187,10 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
} }
function deleteImage(context, itemId, type, index, apiClient, enableConfirmation) { function deleteImage(context, itemId, type, index, apiClient, enableConfirmation) {
const afterConfirm = function () {
var afterConfirm = function () {
apiClient.deleteItemImage(itemId, type, index).then(function () { apiClient.deleteItemImage(itemId, type, index).then(function () {
hasChanges = true; hasChanges = true;
reload(context); reload(context);
}); });
}; };
@ -198,8 +199,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
return; return;
} }
require(['confirm'], function (confirm) { import('confirm').then(({default: confirm}) => {
confirm({ confirm({
text: globalize.translate('ConfirmDeleteImage'), text: globalize.translate('ConfirmDeleteImage'),
@ -211,36 +211,30 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
} }
function moveImage(context, apiClient, itemId, type, index, newIndex, focusContext) { function moveImage(context, apiClient, itemId, type, index, newIndex, focusContext) {
apiClient.updateItemImageIndex(itemId, type, index, newIndex).then(function () { apiClient.updateItemImageIndex(itemId, type, index, newIndex).then(function () {
hasChanges = true; hasChanges = true;
reload(context, null, focusContext); reload(context, null, focusContext);
}, function () { }, function () {
import('alert').then(({default: alert}) => {
require(['alert'], function (alert) { alert(globalize.translate('ErrorDefault'));
alert(globalize.translate('DefaultErrorMessage'));
}); });
}); });
} }
function renderImages(page, item, apiClient, images, imageProviders, elem) { function renderImages(page, item, apiClient, images, imageProviders, elem) {
let html = '';
var html = ''; let imageSize = 300;
const windowSize = dom.getWindowSize();
var imageSize = 300;
var windowSize = dom.getWindowSize();
if (windowSize.innerWidth >= 1280) { if (windowSize.innerWidth >= 1280) {
imageSize = Math.round(windowSize.innerWidth / 4); imageSize = Math.round(windowSize.innerWidth / 4);
} }
var tagName = layoutManager.tv ? 'button' : 'div'; const tagName = layoutManager.tv ? 'button' : 'div';
var enableFooterButtons = !layoutManager.tv; const enableFooterButtons = !layoutManager.tv;
for (var i = 0, length = images.length; i < length; i++) {
var image = images[i];
for (let i = 0, length = images.length; i < length; i++) {
const image = images[i];
html += getCardHtml(image, i, length, apiClient, imageProviders, imageSize, tagName, enableFooterButtons); html += getCardHtml(image, i, length, apiClient, imageProviders, imageSize, tagName, enableFooterButtons);
} }
@ -249,8 +243,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
} }
function renderStandardImages(page, apiClient, item, imageInfos, imageProviders) { function renderStandardImages(page, apiClient, item, imageInfos, imageProviders) {
const images = imageInfos.filter(function (i) {
var images = imageInfos.filter(function (i) {
return i.ImageType !== 'Screenshot' && i.ImageType !== 'Backdrop' && i.ImageType !== 'Chapter'; return i.ImageType !== 'Screenshot' && i.ImageType !== 'Backdrop' && i.ImageType !== 'Chapter';
}); });
@ -258,10 +251,8 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
} }
function renderBackdrops(page, apiClient, item, imageInfos, imageProviders) { function renderBackdrops(page, apiClient, item, imageInfos, imageProviders) {
const images = imageInfos.filter(function (i) {
var images = imageInfos.filter(function (i) {
return i.ImageType === 'Backdrop'; return i.ImageType === 'Backdrop';
}).sort(function (a, b) { }).sort(function (a, b) {
return a.ImageIndex - b.ImageIndex; return a.ImageIndex - b.ImageIndex;
}); });
@ -275,10 +266,8 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
} }
function renderScreenshots(page, apiClient, item, imageInfos, imageProviders) { function renderScreenshots(page, apiClient, item, imageInfos, imageProviders) {
const images = imageInfos.filter(function (i) {
var images = imageInfos.filter(function (i) {
return i.ImageType === 'Screenshot'; return i.ImageType === 'Screenshot';
}).sort(function (a, b) { }).sort(function (a, b) {
return a.ImageIndex - b.ImageIndex; return a.ImageIndex - b.ImageIndex;
}); });
@ -292,32 +281,26 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
} }
function showImageDownloader(page, imageType) { function showImageDownloader(page, imageType) {
import('imageDownloader').then(({default: ImageDownloader}) => {
require(['imageDownloader'], function (ImageDownloader) {
ImageDownloader.show(currentItem.Id, currentItem.ServerId, currentItem.Type, imageType).then(function () { ImageDownloader.show(currentItem.Id, currentItem.ServerId, currentItem.Type, imageType).then(function () {
hasChanges = true; hasChanges = true;
reload(page); reload(page);
}); });
}); });
} }
function showActionSheet(context, imageCard) { function showActionSheet(context, imageCard) {
const itemId = imageCard.getAttribute('data-id');
const serverId = imageCard.getAttribute('data-serverid');
const apiClient = window.connectionManager.getApiClient(serverId);
var itemId = imageCard.getAttribute('data-id'); const type = imageCard.getAttribute('data-imagetype');
var serverId = imageCard.getAttribute('data-serverid'); const index = parseInt(imageCard.getAttribute('data-index'));
var apiClient = connectionManager.getApiClient(serverId); const providerCount = parseInt(imageCard.getAttribute('data-providers'));
const numImages = parseInt(imageCard.getAttribute('data-numimages'));
var type = imageCard.getAttribute('data-imagetype'); import('actionsheet').then(({default: actionSheet}) => {
var index = parseInt(imageCard.getAttribute('data-index')); const commands = [];
var providerCount = parseInt(imageCard.getAttribute('data-providers'));
var numImages = parseInt(imageCard.getAttribute('data-numimages'));
require(['actionsheet'], function (actionSheet) {
var commands = [];
commands.push({ commands.push({
name: globalize.translate('Delete'), name: globalize.translate('Delete'),
@ -353,9 +336,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
positionTo: imageCard positionTo: imageCard
}).then(function (id) { }).then(function (id) {
switch (id) { switch (id) {
case 'delete': case 'delete':
deleteImage(context, itemId, type, index, apiClient, false); deleteImage(context, itemId, type, index, apiClient, false);
break; break;
@ -371,16 +352,14 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
default: default:
break; break;
} }
}); });
}); });
} }
function initEditor(context, options) { function initEditor(context, options) {
const uploadButtons = context.querySelectorAll('.btnOpenUploadMenu');
var uploadButtons = context.querySelectorAll('.btnOpenUploadMenu'); const isFileInputSupported = appHost.supports('fileinput');
var isFileInputSupported = appHost.supports('fileinput'); for (let i = 0, length = uploadButtons.length; i < length; i++) {
for (var i = 0, length = uploadButtons.length; i < length; i++) {
if (isFileInputSupported) { if (isFileInputSupported) {
uploadButtons[i].classList.remove('hide'); uploadButtons[i].classList.remove('hide');
} else { } else {
@ -389,10 +368,9 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
} }
addListeners(context, 'btnOpenUploadMenu', 'click', function () { addListeners(context, 'btnOpenUploadMenu', 'click', function () {
var imageType = this.getAttribute('data-imagetype'); const imageType = this.getAttribute('data-imagetype');
require(['imageUploader'], function (imageUploader) {
import('imageUploader').then(({default: imageUploader}) => {
imageUploader.show({ imageUploader.show({
theme: options.theme, theme: options.theme,
@ -401,7 +379,6 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
serverId: currentItem.ServerId serverId: currentItem.ServerId
}).then(function (hasChanged) { }).then(function (hasChanged) {
if (hasChanged) { if (hasChanged) {
hasChanges = true; hasChanges = true;
reload(context); reload(context);
@ -423,34 +400,32 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
}); });
addListeners(context, 'btnDeleteImage', 'click', function () { addListeners(context, 'btnDeleteImage', 'click', function () {
var type = this.getAttribute('data-imagetype'); const type = this.getAttribute('data-imagetype');
var index = this.getAttribute('data-index'); let index = this.getAttribute('data-index');
index = index === 'null' ? null : parseInt(index); index = index === 'null' ? null : parseInt(index);
var apiClient = connectionManager.getApiClient(currentItem.ServerId); const apiClient = window.connectionManager.getApiClient(currentItem.ServerId);
deleteImage(context, currentItem.Id, type, index, apiClient, true); deleteImage(context, currentItem.Id, type, index, apiClient, true);
}); });
addListeners(context, 'btnMoveImage', 'click', function () { addListeners(context, 'btnMoveImage', 'click', function () {
var type = this.getAttribute('data-imagetype'); const type = this.getAttribute('data-imagetype');
var index = this.getAttribute('data-index'); const index = this.getAttribute('data-index');
var newIndex = this.getAttribute('data-newindex'); const newIndex = this.getAttribute('data-newindex');
var apiClient = connectionManager.getApiClient(currentItem.ServerId); const apiClient = window.connectionManager.getApiClient(currentItem.ServerId);
moveImage(context, apiClient, currentItem.Id, type, index, newIndex, dom.parentWithClass(this, 'itemsContainer')); moveImage(context, apiClient, currentItem.Id, type, index, newIndex, dom.parentWithClass(this, 'itemsContainer'));
}); });
} }
function showEditor(options, resolve, reject) { function showEditor(options, resolve, reject) {
const itemId = options.itemId;
var itemId = options.itemId; const serverId = options.serverId;
var serverId = options.serverId;
loading.show(); loading.show();
require(['text!./imageeditor.template.html'], function (template) { import('text!./imageeditor.template.html').then(({default: template}) => {
var apiClient = connectionManager.getApiClient(serverId); const apiClient = window.connectionManager.getApiClient(serverId);
apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) { apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) {
const dialogOptions = {
var dialogOptions = {
removeOnClose: true removeOnClose: true
}; };
@ -460,11 +435,11 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
dialogOptions.size = 'small'; dialogOptions.size = 'small';
} }
var dlg = dialogHelper.createDialog(dialogOptions); const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog'); dlg.classList.add('formDialog');
dlg.innerHTML = globalize.translateDocument(template, 'core'); dlg.innerHTML = globalize.translateHtml(template, 'core');
if (layoutManager.tv) { if (layoutManager.tv) {
scrollHelper.centerFocus.on(dlg, false); scrollHelper.centerFocus.on(dlg, false);
@ -474,7 +449,6 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
// Has to be assigned a z-index after the call to .open() // Has to be assigned a z-index after the call to .open()
dlg.addEventListener('close', function () { dlg.addEventListener('close', function () {
if (layoutManager.tv) { if (layoutManager.tv) {
scrollHelper.centerFocus.off(dlg, false); scrollHelper.centerFocus.off(dlg, false);
} }
@ -493,22 +467,21 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
reload(dlg, item); reload(dlg, item);
dlg.querySelector('.btnCancel').addEventListener('click', function () { dlg.querySelector('.btnCancel').addEventListener('click', function () {
dialogHelper.close(dlg); dialogHelper.close(dlg);
}); });
}); });
}); });
} }
return { export function show (options) {
show: function (options) {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
hasChanges = false; hasChanges = false;
showEditor(options, resolve, reject); showEditor(options, resolve, reject);
}); });
} }
};
}); export default {
show
};
/* eslint-enable indent */

View file

@ -12,13 +12,13 @@ import 'css!./style';
fillImageElement(elem, source); fillImageElement(elem, source);
} }
async function itemBlurhashing(target, blurhashstr) { function itemBlurhashing(target, blurhashstr) {
if (blurhash.isBlurhashValid(blurhashstr)) { if (blurhash.isBlurhashValid(blurhashstr)) {
// Although the default values recommended by Blurhash developers is 32x32, a size of 18x18 seems to be the sweet spot for us, // Although the default values recommended by Blurhash developers is 32x32, a size of 18x18 seems to be the sweet spot for us,
// improving the performance and reducing the memory usage, while retaining almost full blur quality. // improving the performance and reducing the memory usage, while retaining almost full blur quality.
// Lower values had more visible pixelation // Lower values had more visible pixelation
let width = 18; const width = 18;
let height = 18; const height = 18;
let pixels; let pixels;
try { try {
pixels = blurhash.decode(blurhashstr, width, height); pixels = blurhash.decode(blurhashstr, width, height);
@ -27,33 +27,27 @@ import 'css!./style';
target.classList.add('non-blurhashable'); target.classList.add('non-blurhashable');
return; return;
} }
let canvas = document.createElement('canvas'); const canvas = document.createElement('canvas');
canvas.width = width; canvas.width = width;
canvas.height = height; canvas.height = height;
let ctx = canvas.getContext('2d'); const ctx = canvas.getContext('2d');
let imgData = ctx.createImageData(width, height); const imgData = ctx.createImageData(width, height);
imgData.data.set(pixels); imgData.data.set(pixels);
ctx.putImageData(imgData, 0, 0); ctx.putImageData(imgData, 0, 0);
let child = target.appendChild(canvas); requestAnimationFrame(() => {
child.classList.add('blurhash-canvas'); canvas.classList.add('blurhash-canvas');
child.style.opacity = 1;
if (userSettings.enableFastFadein()) { if (userSettings.enableFastFadein()) {
child.classList.add('lazy-blurhash-fadein-fast'); canvas.classList.add('lazy-blurhash-fadein-fast');
} else { } else {
child.classList.add('lazy-blurhash-fadein'); canvas.classList.add('lazy-blurhash-fadein');
} }
target.parentNode.insertBefore(canvas, target);
target.classList.add('blurhashed'); target.classList.add('blurhashed');
target.removeAttribute('data-blurhash'); target.removeAttribute('data-blurhash');
} });
}
function switchCanvas(elem) {
let child = elem.getElementsByClassName('blurhash-canvas')[0];
if (child) {
child.style.opacity = elem.getAttribute('data-src') ? 1 : 0;
} }
} }
@ -61,28 +55,21 @@ import 'css!./style';
if (!entry) { if (!entry) {
throw new Error('entry cannot be null'); throw new Error('entry cannot be null');
} }
let target = entry.target; const target = entry.target;
var source = undefined; var source = undefined;
if (target) { if (target) {
source = target.getAttribute('data-src'); source = target.getAttribute('data-src');
var blurhashstr = target.getAttribute('data-blurhash');
} else { } else {
source = entry; source = entry;
} }
if (userSettings.enableBlurhash()) {
if (!target.classList.contains('blurhashed', 'non-blurhashable') && blurhashstr) {
itemBlurhashing(target, blurhashstr);
} else if (!blurhashstr && !target.classList.contains('blurhashed')) {
target.classList.add('non-blurhashable');
}
}
if (entry.intersectionRatio > 0) { if (entry.intersectionRatio > 0) {
if (source) fillImageElement(target, source); if (source) fillImageElement(target, source);
} else if (!source) { } else if (!source) {
requestAnimationFrame(() => {
emptyImageElement(target); emptyImageElement(target);
});
} }
} }
@ -91,32 +78,30 @@ import 'css!./style';
throw new TypeError('url cannot be undefined'); throw new TypeError('url cannot be undefined');
} }
let preloaderImg = new Image(); const preloaderImg = new Image();
preloaderImg.src = url; preloaderImg.src = url;
// This is necessary here, so changing blurhash settings without reloading the page works
if (!userSettings.enableBlurhash() || elem.classList.contains('non-blurhashable')) {
elem.classList.add('lazy-hidden'); elem.classList.add('lazy-hidden');
}
preloaderImg.addEventListener('load', () => { preloaderImg.addEventListener('load', () => {
requestAnimationFrame(() => {
if (elem.tagName !== 'IMG') { if (elem.tagName !== 'IMG') {
elem.style.backgroundImage = "url('" + url + "')"; elem.style.backgroundImage = "url('" + url + "')";
if (elem.classList.contains('blurhashed')) {
elem.style.backgroundColor = '#fff';
}
} else { } else {
elem.setAttribute('src', url); elem.setAttribute('src', url);
} }
elem.removeAttribute('data-src'); elem.removeAttribute('data-src');
if (elem.classList.contains('non-blurhashable') || !userSettings.enableBlurhash()) {
elem.classList.remove('lazy-hidden'); elem.classList.remove('lazy-hidden');
if (userSettings.enableFastFadein()) { if (userSettings.enableFastFadein()) {
elem.classList.add('lazy-image-fadein-fast'); elem.classList.add('lazy-image-fadein-fast');
} else { } else {
elem.classList.add('lazy-image-fadein'); elem.classList.add('lazy-image-fadein');
} }
} else { });
switchCanvas(elem);
}
}); });
} }
@ -126,30 +111,35 @@ import 'css!./style';
if (elem.tagName !== 'IMG') { if (elem.tagName !== 'IMG') {
url = elem.style.backgroundImage.slice(4, -1).replace(/"/g, ''); url = elem.style.backgroundImage.slice(4, -1).replace(/"/g, '');
elem.style.backgroundImage = 'none'; elem.style.backgroundImage = 'none';
elem.style.backgroundColor = null;
} else { } else {
url = elem.getAttribute('src'); url = elem.getAttribute('src');
elem.setAttribute('src', ''); elem.setAttribute('src', '');
} }
elem.setAttribute('data-src', url); elem.setAttribute('data-src', url);
if (elem.classList.contains('non-blurhashable') || !userSettings.enableBlurhash()) {
elem.classList.remove('lazy-image-fadein-fast', 'lazy-image-fadein'); elem.classList.remove('lazy-image-fadein-fast', 'lazy-image-fadein');
elem.classList.add('lazy-hidden'); elem.classList.add('lazy-hidden');
} else {
switchCanvas(elem);
}
} }
export function lazyChildren(elem) { export function lazyChildren(elem) {
if (userSettings.enableBlurhash()) {
for (const lazyElem of elem.querySelectorAll('.lazy')) {
const blurhashstr = lazyElem.getAttribute('data-blurhash');
if (!lazyElem.classList.contains('blurhashed', 'non-blurhashable') && blurhashstr) {
itemBlurhashing(lazyElem, blurhashstr);
} else if (!blurhashstr && !lazyElem.classList.contains('blurhashed')) {
lazyElem.classList.add('non-blurhashable');
}
}
}
lazyLoader.lazyChildren(elem, fillImage); lazyLoader.lazyChildren(elem, fillImage);
} }
export function getPrimaryImageAspectRatio(items) { export function getPrimaryImageAspectRatio(items) {
var values = []; var values = [];
for (var i = 0, length = items.length; i < length; i++) { for (var i = 0, length = items.length; i < length; i++) {
var ratio = items[i].PrimaryImageAspectRatio || 0; var ratio = items[i].PrimaryImageAspectRatio || 0;
if (!ratio) { if (!ratio) {
@ -205,7 +195,6 @@ import 'css!./style';
} }
export function fillImages(elems) { export function fillImages(elems) {
for (var i = 0, length = elems.length; i < length; i++) { for (var i = 0, length = elems.length; i < length; i++) {
var elem = elems[0]; var elem = elems[0];
fillImage(elem); fillImage(elem);
@ -220,7 +209,7 @@ import 'css!./style';
/* eslint-enable indent */ /* eslint-enable indent */
export default { export default {
serLazyImage: setLazyImage, setLazyImage: setLazyImage,
fillImages: fillImages, fillImages: fillImages,
fillImage: fillImage, fillImage: fillImage,
lazyImage: lazyImage, lazyImage: lazyImage,

View file

@ -12,12 +12,22 @@
opacity: 0; opacity: 0;
} }
@keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.lazy-blurhash-fadein-fast { .lazy-blurhash-fadein-fast {
transition: opacity 0.2s; animation: fadein 0.1s;
} }
.lazy-blurhash-fadein { .lazy-blurhash-fadein {
transition: opacity 0.7s; animation: fadein 0.4s;
} }
.blurhash-canvas { .blurhash-canvas {
@ -28,6 +38,5 @@
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
z-index: 100;
pointer-events: none; pointer-events: none;
} }

View file

@ -82,7 +82,7 @@ export function enablePlayedIndicator(item) {
export function getPlayedIndicatorHtml(item) { export function getPlayedIndicatorHtml(item) {
if (enablePlayedIndicator(item)) { if (enablePlayedIndicator(item)) {
let userData = item.UserData || {}; const userData = item.UserData || {};
if (userData.UnplayedItemCount) { if (userData.UnplayedItemCount) {
return '<div class="countIndicator indicator">' + userData.UnplayedItemCount + '</div>'; return '<div class="countIndicator indicator">' + userData.UnplayedItemCount + '</div>';
} }

View file

@ -1,14 +1,20 @@
define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', 'playbackManager', 'loading', 'appSettings', 'browser', 'actionsheet'], function (appHost, globalize, connectionManager, itemHelper, appRouter, playbackManager, loading, appSettings, browser, actionsheet) { import appHost from 'apphost';
'use strict'; import globalize from 'globalize';
import itemHelper from 'itemHelper';
import appRouter from 'appRouter';
import playbackManager from 'playbackManager';
import browser from 'browser';
import actionsheet from 'actionsheet';
function getCommands(options) { /* eslint-disable indent */
var item = options.item; export function getCommands(options) {
var user = options.user; const item = options.item;
const user = options.user;
var canPlay = playbackManager.canPlay(item); const canPlay = playbackManager.canPlay(item);
var restrictOptions = (browser.operaTv || browser.web0s) && !user.Policy.IsAdministrator; const restrictOptions = (browser.operaTv || browser.web0s) && !user.Policy.IsAdministrator;
var commands = []; const commands = [];
if (canPlay && item.MediaType !== 'Photo') { if (canPlay && item.MediaType !== 'Photo') {
if (options.play !== false) { if (options.play !== false) {
@ -28,6 +34,23 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
} }
} }
if (playbackManager.getCurrentPlayer() !== null) {
if (options.stopPlayback) {
commands.push({
name: globalize.translate('StopPlayback'),
id: 'stopPlayback',
icon: 'stop'
});
}
if (options.clearQueue) {
commands.push({
name: globalize.translate('ClearQueue'),
id: 'clearQueue',
icon: 'clear_all'
});
}
}
if (playbackManager.canQueue(item)) { if (playbackManager.canQueue(item)) {
if (options.queue !== false) { if (options.queue !== false) {
commands.push({ commands.push({
@ -44,13 +67,6 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
icon: 'playlist_add' icon: 'playlist_add'
}); });
} }
//if (options.queueAllFromHere) {
// commands.push({
// name: globalize.translate("QueueAllFromHere"),
// id: "queueallfromhere"
// });
//}
} }
if (item.IsFolder || item.Type === 'MusicArtist' || item.Type === 'MusicGenre') { if (item.IsFolder || item.Type === 'MusicArtist' || item.Type === 'MusicGenre') {
@ -124,7 +140,6 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
} }
if (item.CanDelete && options.deleteItem !== false) { if (item.CanDelete && options.deleteItem !== false) {
if (item.Type === 'Playlist' || item.Type === 'BoxSet') { if (item.Type === 'Playlist' || item.Type === 'BoxSet') {
commands.push({ commands.push({
name: globalize.translate('Delete'), name: globalize.translate('Delete'),
@ -161,10 +176,10 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
}); });
} }
var canEdit = itemHelper.canEdit(user, item); const canEdit = itemHelper.canEdit(user, item);
if (canEdit) { if (canEdit) {
if (options.edit !== false && item.Type !== 'SeriesTimer') { if (options.edit !== false && item.Type !== 'SeriesTimer') {
var text = (item.Type === 'Timer' || item.Type === 'SeriesTimer') ? globalize.translate('Edit') : globalize.translate('EditMetadata'); const text = (item.Type === 'Timer' || item.Type === 'SeriesTimer') ? globalize.translate('Edit') : globalize.translate('EditMetadata');
commands.push({ commands.push({
name: text, name: text,
id: 'edit', id: 'edit',
@ -288,10 +303,11 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
icon: 'album' icon: 'album'
}); });
} }
// Show Album Artist by default, as a song can have multiple artists, which specific one would this option refer to?
if (options.openArtist !== false && item.ArtistItems && item.ArtistItems.length) { // Although some albums can have multiple artists, it's not as common as songs.
if (options.openArtist !== false && item.AlbumArtists && item.AlbumArtists.length) {
commands.push({ commands.push({
name: globalize.translate('ViewArtist'), name: globalize.translate('ViewAlbumArtist'),
id: 'artist', id: 'artist',
icon: 'person' icon: 'person'
}); });
@ -311,31 +327,31 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
} }
function executeCommand(item, id, options) { function executeCommand(item, id, options) {
var itemId = item.Id; const itemId = item.Id;
var serverId = item.ServerId; const serverId = item.ServerId;
var apiClient = connectionManager.getApiClient(serverId); const apiClient = window.connectionManager.getApiClient(serverId);
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
switch (id) { switch (id) {
case 'addtocollection': case 'addtocollection':
require(['collectionEditor'], function (collectionEditor) { import('collectionEditor').then(({default: collectionEditor}) => {
new collectionEditor().show({ new collectionEditor({
items: [itemId], items: [itemId],
serverId: serverId serverId: serverId
}).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); }).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
}); });
break; break;
case 'addtoplaylist': case 'addtoplaylist':
require(['playlistEditor'], function (playlistEditor) { import('playlistEditor').then(({default: playlistEditor}) => {
new playlistEditor().show({ new playlistEditor({
items: [itemId], items: [itemId],
serverId: serverId serverId: serverId
}).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); }).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
}); });
break; break;
case 'download': case 'download':
require(['fileDownloader'], function (fileDownloader) { import('fileDownloader').then((fileDownloader) => {
var downloadHref = apiClient.getItemDownloadUrl(itemId); const downloadHref = apiClient.getItemDownloadUrl(itemId);
fileDownloader.download([{ fileDownloader.download([{
url: downloadHref, url: downloadHref,
itemId: itemId, itemId: itemId,
@ -346,17 +362,17 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
getResolveFunction(getResolveFunction(resolve, id), id)(); getResolveFunction(getResolveFunction(resolve, id), id)();
}); });
break; break;
case 'copy-stream': case 'copy-stream': {
var downloadHref = apiClient.getItemDownloadUrl(itemId); const downloadHref = apiClient.getItemDownloadUrl(itemId);
var textAreaCopy = function () { const textAreaCopy = function () {
var textArea = document.createElement('textarea'); const textArea = document.createElement('textarea');
textArea.value = downloadHref; textArea.value = downloadHref;
document.body.appendChild(textArea); document.body.appendChild(textArea);
textArea.focus(); textArea.focus();
textArea.select(); textArea.select();
if (document.execCommand('copy')) { if (document.execCommand('copy')) {
require(['toast'], function (toast) { import('toast').then(({default: toast}) => {
toast(globalize.translate('CopyStreamURLSuccess')); toast(globalize.translate('CopyStreamURLSuccess'));
}); });
} else { } else {
@ -371,7 +387,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
} else { } else {
/* eslint-disable-next-line compat/compat */ /* eslint-disable-next-line compat/compat */
navigator.clipboard.writeText(downloadHref).then(function () { navigator.clipboard.writeText(downloadHref).then(function () {
require(['toast'], function (toast) { import('toast').then(({default: toast}) => {
toast(globalize.translate('CopyStreamURLSuccess')); toast(globalize.translate('CopyStreamURLSuccess'));
}); });
}).catch(function () { }).catch(function () {
@ -380,8 +396,9 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
} }
getResolveFunction(resolve, id)(); getResolveFunction(resolve, id)();
break; break;
}
case 'editsubtitles': case 'editsubtitles':
require(['subtitleEditor'], function (subtitleEditor) { import('subtitleEditor').then(({default: subtitleEditor}) => {
subtitleEditor.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); subtitleEditor.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
}); });
break; break;
@ -389,7 +406,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
editItem(apiClient, item).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); editItem(apiClient, item).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
break; break;
case 'editimages': case 'editimages':
require(['imageEditor'], function (imageEditor) { import('imageEditor').then(({default: imageEditor}) => {
imageEditor.show({ imageEditor.show({
itemId: itemId, itemId: itemId,
serverId: serverId serverId: serverId
@ -397,12 +414,12 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
}); });
break; break;
case 'identify': case 'identify':
require(['itemIdentifier'], function (itemIdentifier) { import('itemIdentifier').then(({default: itemIdentifier}) => {
itemIdentifier.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); itemIdentifier.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
}); });
break; break;
case 'moremediainfo': case 'moremediainfo':
require(['itemMediaInfo'], function (itemMediaInfo) { import('itemMediaInfo').then(({default: itemMediaInfo}) => {
itemMediaInfo.show(itemId, serverId).then(getResolveFunction(resolve, id), getResolveFunction(resolve, id)); itemMediaInfo.show(itemId, serverId).then(getResolveFunction(resolve, id), getResolveFunction(resolve, id));
}); });
break; break;
@ -430,8 +447,14 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
play(item, false, true, true); play(item, false, true, true);
getResolveFunction(resolve, id)(); getResolveFunction(resolve, id)();
break; break;
case 'stopPlayback':
playbackManager.stop();
break;
case 'clearQueue':
playbackManager.clearQueue();
break;
case 'record': case 'record':
require(['recordingCreator'], function (recordingCreator) { import('recordingCreator').then(({default: recordingCreator}) => {
recordingCreator.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); recordingCreator.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
}); });
break; break;
@ -458,7 +481,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
getResolveFunction(resolve, id)(); getResolveFunction(resolve, id)();
break; break;
case 'artist': case 'artist':
appRouter.showItem(item.ArtistItems[0].Id, item.ServerId); appRouter.showItem(item.AlbumArtists[0].Id, item.ServerId);
getResolveFunction(resolve, id)(); getResolveFunction(resolve, id)();
break; break;
case 'playallfromhere': case 'playallfromhere':
@ -502,8 +525,8 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
} }
function deleteTimer(apiClient, item, resolve, command) { function deleteTimer(apiClient, item, resolve, command) {
require(['recordingHelper'], function (recordingHelper) { import('recordingHelper').then(({default: recordingHelper}) => {
var timerId = item.TimerId || item.Id; const timerId = item.TimerId || item.Id;
recordingHelper.cancelTimerWithConfirmation(timerId, item.ServerId).then(function () { recordingHelper.cancelTimerWithConfirmation(timerId, item.ServerId).then(function () {
getResolveFunction(resolve, command, true)(); getResolveFunction(resolve, command, true)();
}); });
@ -511,7 +534,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
} }
function deleteSeriesTimer(apiClient, item, resolve, command) { function deleteSeriesTimer(apiClient, item, resolve, command) {
require(['recordingHelper'], function (recordingHelper) { import('recordingHelper').then(({default: recordingHelper}) => {
recordingHelper.cancelSeriesTimerWithConfirmation(item.Id, item.ServerId).then(function () { recordingHelper.cancelSeriesTimerWithConfirmation(item.Id, item.ServerId).then(function () {
getResolveFunction(resolve, command, true)(); getResolveFunction(resolve, command, true)();
}); });
@ -519,9 +542,9 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
} }
function play(item, resume, queue, queueNext) { function play(item, resume, queue, queueNext) {
var method = queue ? (queueNext ? 'queueNext' : 'queue') : 'play'; const method = queue ? (queueNext ? 'queueNext' : 'queue') : 'play';
var startPosition = 0; let startPosition = 0;
if (resume && item.UserData && item.UserData.PlaybackPositionTicks) { if (resume && item.UserData && item.UserData.PlaybackPositionTicks) {
startPosition = item.UserData.PlaybackPositionTicks; startPosition = item.UserData.PlaybackPositionTicks;
} }
@ -542,18 +565,18 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
function editItem(apiClient, item) { function editItem(apiClient, item) {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
var serverId = apiClient.serverInfo().Id; const serverId = apiClient.serverInfo().Id;
if (item.Type === 'Timer') { if (item.Type === 'Timer') {
require(['recordingEditor'], function (recordingEditor) { import('recordingEditor').then(({default: recordingEditor}) => {
recordingEditor.show(item.Id, serverId).then(resolve, reject); recordingEditor.show(item.Id, serverId).then(resolve, reject);
}); });
} else if (item.Type === 'SeriesTimer') { } else if (item.Type === 'SeriesTimer') {
require(['seriesRecordingEditor'], function (recordingEditor) { import('seriesRecordingEditor').then(({default: recordingEditor}) => {
recordingEditor.show(item.Id, serverId).then(resolve, reject); recordingEditor.show(item.Id, serverId).then(resolve, reject);
}); });
} else { } else {
require(['metadataEditor'], function (metadataEditor) { import('metadataEditor').then(({default: metadataEditor}) => {
metadataEditor.show(item.Id, serverId).then(resolve, reject); metadataEditor.show(item.Id, serverId).then(resolve, reject);
}); });
} }
@ -562,7 +585,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
function deleteItem(apiClient, item) { function deleteItem(apiClient, item) {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
require(['deleteHelper'], function (deleteHelper) { import('deleteHelper').then(({default: deleteHelper}) => {
deleteHelper.deleteItem({ deleteHelper.deleteItem({
item: item, item: item,
navigate: false navigate: false
@ -574,7 +597,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
} }
function refresh(apiClient, item) { function refresh(apiClient, item) {
require(['refreshDialog'], function (refreshDialog) { import('refreshDialog').then(({default: refreshDialog}) => {
new refreshDialog({ new refreshDialog({
itemIds: [item.Id], itemIds: [item.Id],
serverId: apiClient.serverInfo().Id, serverId: apiClient.serverInfo().Id,
@ -583,8 +606,8 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
}); });
} }
function show(options) { export function show(options) {
var commands = getCommands(options); const commands = getCommands(options);
if (!commands.length) { if (!commands.length) {
return Promise.reject(); return Promise.reject();
} }
@ -598,8 +621,9 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
}); });
} }
return { /* eslint-enable indent */
export default {
getCommands: getCommands, getCommands: getCommands,
show: show show: show
}; };
});

View file

@ -1,8 +1,7 @@
define(['apphost', 'globalize'], function (appHost, globalize) { import appHost from 'apphost';
'use strict'; import globalize from 'globalize';
function getDisplayName(item, options = {}) {
export function getDisplayName(item, options = {}) {
if (!item) { if (!item) {
throw new Error('null item passed into getDisplayName'); throw new Error('null item passed into getDisplayName');
} }
@ -11,7 +10,7 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
item = item.ProgramInfo || item; item = item.ProgramInfo || item;
} }
var name = ((item.Type === 'Program' || item.Type === 'Recording') && (item.IsSeries || item.EpisodeTitle) ? item.EpisodeTitle : item.Name) || ''; let name = ((item.Type === 'Program' || item.Type === 'Recording') && (item.IsSeries || item.EpisodeTitle) ? item.EpisodeTitle : item.Name) || '';
if (item.Type === 'TvChannel') { if (item.Type === 'TvChannel') {
if (item.ChannelNumber) { if (item.ChannelNumber) {
@ -22,11 +21,10 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
if (item.Type === 'Episode' && item.ParentIndexNumber === 0) { if (item.Type === 'Episode' && item.ParentIndexNumber === 0) {
name = globalize.translate('ValueSpecialEpisodeName', name); name = globalize.translate('ValueSpecialEpisodeName', name);
} else if ((item.Type === 'Episode' || item.Type === 'Program') && item.IndexNumber != null && item.ParentIndexNumber != null && options.includeIndexNumber !== false) { } else if ((item.Type === 'Episode' || item.Type === 'Program') && item.IndexNumber != null && item.ParentIndexNumber != null && options.includeIndexNumber !== false) {
let displayIndexNumber = item.IndexNumber;
var displayIndexNumber = item.IndexNumber; let number = displayIndexNumber;
let nameSeparator = ' - ';
var number = displayIndexNumber;
var nameSeparator = ' - ';
if (options.includeParentInfo !== false) { if (options.includeParentInfo !== false) {
number = 'S' + item.ParentIndexNumber + ':E' + number; number = 'S' + item.ParentIndexNumber + ':E' + number;
@ -35,7 +33,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
} }
if (item.IndexNumberEnd) { if (item.IndexNumberEnd) {
displayIndexNumber = item.IndexNumberEnd; displayIndexNumber = item.IndexNumberEnd;
number += '-' + displayIndexNumber; number += '-' + displayIndexNumber;
} }
@ -46,11 +43,10 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
} }
return name; return name;
} }
function supportsAddingToCollection(item) { export function supportsAddingToCollection(item) {
const invalidTypes = ['Genre', 'MusicGenre', 'Studio', 'UserView', 'CollectionFolder', 'Audio', 'Program', 'Timer', 'SeriesTimer'];
var invalidTypes = ['Genre', 'MusicGenre', 'Studio', 'UserView', 'CollectionFolder', 'Audio', 'Program', 'Timer', 'SeriesTimer'];
if (item.Type === 'Recording') { if (item.Type === 'Recording') {
if (item.Status !== 'Completed') { if (item.Status !== 'Completed') {
@ -59,10 +55,9 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
} }
return !item.CollectionType && invalidTypes.indexOf(item.Type) === -1 && item.MediaType !== 'Photo' && !isLocalItem(item); return !item.CollectionType && invalidTypes.indexOf(item.Type) === -1 && item.MediaType !== 'Photo' && !isLocalItem(item);
} }
function supportsAddingToPlaylist(item) {
export function supportsAddingToPlaylist(item) {
if (item.Type === 'Program') { if (item.Type === 'Program') {
return false; return false;
} }
@ -93,11 +88,10 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
} }
return item.MediaType || item.IsFolder || item.Type === 'Genre' || item.Type === 'MusicGenre' || item.Type === 'MusicArtist'; return item.MediaType || item.IsFolder || item.Type === 'Genre' || item.Type === 'MusicGenre' || item.Type === 'MusicArtist';
} }
function canEdit(user, item) { export function canEdit(user, item) {
const itemType = item.Type;
var itemType = item.Type;
if (itemType === 'UserRootFolder' || itemType === 'UserView') { if (itemType === 'UserRootFolder' || itemType === 'UserView') {
return false; return false;
@ -126,26 +120,18 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
} }
return user.Policy.IsAdministrator; return user.Policy.IsAdministrator;
} }
function isLocalItem(item) {
export function isLocalItem(item) {
if (item && item.Id && item.Id.indexOf('local') === 0) { if (item && item.Id && item.Id.indexOf('local') === 0) {
return true; return true;
} }
return false; return false;
} }
return { export function canIdentify (user, item) {
getDisplayName: getDisplayName, const itemType = item.Type;
supportsAddingToCollection: supportsAddingToCollection,
supportsAddingToPlaylist: supportsAddingToPlaylist,
isLocalItem: isLocalItem,
canIdentify: function (user, item) {
var itemType = item.Type;
if (itemType === 'Movie' || if (itemType === 'Movie' ||
itemType === 'Trailer' || itemType === 'Trailer' ||
@ -156,9 +142,7 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
itemType === 'MusicAlbum' || itemType === 'MusicAlbum' ||
itemType === 'MusicArtist' || itemType === 'MusicArtist' ||
itemType === 'MusicVideo') { itemType === 'MusicVideo') {
if (user.Policy.IsAdministrator) { if (user.Policy.IsAdministrator) {
if (!isLocalItem(item)) { if (!isLocalItem(item)) {
return true; return true;
} }
@ -166,13 +150,10 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
} }
return false; return false;
}, }
canEdit: canEdit, export function canEditImages (user, item) {
const itemType = item.Type;
canEditImages: function (user, item) {
var itemType = item.Type;
if (item.MediaType === 'Photo') { if (item.MediaType === 'Photo') {
return false; return false;
@ -180,7 +161,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
if (itemType === 'UserView') { if (itemType === 'UserView') {
if (user.Policy.IsAdministrator) { if (user.Policy.IsAdministrator) {
return true; return true;
} }
@ -194,10 +174,9 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
} }
return itemType !== 'Timer' && itemType !== 'SeriesTimer' && canEdit(user, item) && !isLocalItem(item); return itemType !== 'Timer' && itemType !== 'SeriesTimer' && canEdit(user, item) && !isLocalItem(item);
}, }
canSync: function (user, item) {
export function canSync (user, item) {
if (user && !user.Policy.EnableContentDownloading) { if (user && !user.Policy.EnableContentDownloading) {
return false; return false;
} }
@ -207,10 +186,9 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
} }
return item.SupportsSync; return item.SupportsSync;
}, }
canShare: function (item, user) {
export function canShare (item, user) {
if (item.Type === 'Program') { if (item.Type === 'Program') {
return false; return false;
} }
@ -232,14 +210,13 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
return false; return false;
} }
return user.Policy.EnablePublicSharing && appHost.supports('sharing'); return user.Policy.EnablePublicSharing && appHost.supports('sharing');
}, }
enableDateAddedDisplay: function (item) { export function enableDateAddedDisplay (item) {
return !item.IsFolder && item.MediaType && item.Type !== 'Program' && item.Type !== 'TvChannel' && item.Type !== 'Trailer'; return !item.IsFolder && item.MediaType && item.Type !== 'Program' && item.Type !== 'TvChannel' && item.Type !== 'Trailer';
}, }
canMarkPlayed: function (item) {
export function canMarkPlayed (item) {
if (item.Type === 'Program') { if (item.Type === 'Program') {
return false; return false;
} }
@ -266,10 +243,9 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
} }
return false; return false;
}, }
canRate: function (item) {
export function canRate (item) {
if (item.Type === 'Program' if (item.Type === 'Program'
|| item.Type === 'Timer' || item.Type === 'Timer'
|| item.Type === 'SeriesTimer' || item.Type === 'SeriesTimer'
@ -281,10 +257,9 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
} }
return true; return true;
}, }
canConvert: function (item, user) {
export function canConvert (item, user) {
if (!user.Policy.EnableMediaConversion) { if (!user.Policy.EnableMediaConversion) {
return false; return false;
} }
@ -293,17 +268,17 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
return false; return false;
} }
var mediaType = item.MediaType; const mediaType = item.MediaType;
if (mediaType === 'Book' || mediaType === 'Photo' || mediaType === 'Audio') { if (mediaType === 'Book' || mediaType === 'Photo' || mediaType === 'Audio') {
return false; return false;
} }
var collectionType = item.CollectionType; const collectionType = item.CollectionType;
if (collectionType === 'livetv') { if (collectionType === 'livetv') {
return false; return false;
} }
var type = item.Type; const type = item.Type;
if (type === 'Channel' || type === 'Person' || type === 'Year' || type === 'Program' || type === 'Timer' || type === 'SeriesTimer') { if (type === 'Channel' || type === 'Person' || type === 'Year' || type === 'Program' || type === 'Timer' || type === 'SeriesTimer') {
return false; return false;
} }
@ -317,19 +292,16 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
} }
return true; return true;
}, }
canRefreshMetadata: function (item, user) {
export function canRefreshMetadata (item, user) {
if (user.Policy.IsAdministrator) { if (user.Policy.IsAdministrator) {
const collectionType = item.CollectionType;
var collectionType = item.CollectionType;
if (collectionType === 'livetv') { if (collectionType === 'livetv') {
return false; return false;
} }
if (item.Type !== 'Timer' && item.Type !== 'SeriesTimer' && item.Type !== 'Program' && item.Type !== 'TvChannel' && !(item.Type === 'Recording' && item.Status !== 'Completed')) { if (item.Type !== 'Timer' && item.Type !== 'SeriesTimer' && item.Type !== 'Program' && item.Type !== 'TvChannel' && !(item.Type === 'Recording' && item.Status !== 'Completed')) {
if (!isLocalItem(item)) { if (!isLocalItem(item)) {
return true; return true;
} }
@ -337,10 +309,9 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
} }
return false; return false;
}, }
supportsMediaSourceSelection: function (item) {
export function supportsMediaSourceSelection (item) {
if (item.MediaType !== 'Video') { if (item.MediaType !== 'Video') {
return false; return false;
} }
@ -358,6 +329,22 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
} }
return true; return true;
} }
};
}); export default {
getDisplayName: getDisplayName,
supportsAddingToCollection: supportsAddingToCollection,
supportsAddingToPlaylist: supportsAddingToPlaylist,
isLocalItem: isLocalItem,
canIdentify: canIdentify,
canEdit: canEdit,
canEditImages: canEditImages,
canSync: canSync,
canShare: canShare,
enableDateAddedDisplay: enableDateAddedDisplay,
canMarkPlayed: canMarkPlayed,
canRate: canRate,
canConvert: canConvert,
canRefreshMetadata: canRefreshMetadata,
supportsMediaSourceSelection: supportsMediaSourceSelection
};

View file

@ -1,44 +1,74 @@
define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings', 'connectionManager', 'loading', 'focusManager', 'dom', 'apphost', 'emby-select', 'listViewStyle', 'paper-icon-button-light', 'css!./../formdialog', 'material-icons', 'emby-button', 'flexStyles'], function (dialogHelper, require, layoutManager, globalize, userSettings, connectionManager, loading, focusManager, dom, appHost) { /* eslint-disable indent */
'use strict';
/**
* Module for display media info.
* @module components/itemMediaInfo/itemMediaInfo
*/
import dialogHelper from 'dialogHelper';
import layoutManager from 'layoutManager';
import globalize from 'globalize';
import loading from 'loading';
import 'emby-select';
import 'listViewStyle';
import 'paper-icon-button-light';
import 'css!./../formdialog';
import 'material-icons';
import 'emby-button';
import 'flexStyles';
function setMediaInfo(user, page, item) { function setMediaInfo(user, page, item) {
var html = item.MediaSources.map(function (version) { let html = item.MediaSources.map(version => {
return getMediaSourceHtml(user, item, version); return getMediaSourceHtml(user, item, version);
}).join('<div style="border-top:1px solid #444;margin: 1em 0;"></div>'); }).join('<div style="border-top:1px solid #444;margin: 1em 0;"></div>');
if (item.MediaSources.length > 1) { if (item.MediaSources.length > 1) {
html = '<br/>' + html; html = `<br/>${html}`;
} }
var mediaInfoContent = page.querySelector('#mediaInfoContent'); const mediaInfoContent = page.querySelector('#mediaInfoContent');
mediaInfoContent.innerHTML = html; mediaInfoContent.innerHTML = html;
} }
function getMediaSourceHtml(user, item, version) { function getMediaSourceHtml(user, item, version) {
var html = ''; let html = '';
if (version.Name) { if (version.Name) {
html += '<div><h2 class="mediaInfoStreamType">' + version.Name + '</h2></div>'; html += `<div><h2 class="mediaInfoStreamType">${version.Name}</h2></div>`;
} }
if (version.Container) { if (version.Container) {
html += createAttribute(globalize.translate('MediaInfoContainer'), version.Container) + '<br/>'; html += `${createAttribute(globalize.translate('MediaInfoContainer'), version.Container)}<br/>`;
} }
if (version.Formats && version.Formats.length) { if (version.Formats && version.Formats.length) {
html += createAttribute(globalize.translate('MediaInfoFormat'), version.Formats.join(',')) + '<br/>'; html += `${createAttribute(globalize.translate('MediaInfoFormat'), version.Formats.join(','))}<br/>`;
} }
if (version.Path && user && user.Policy.IsAdministrator) { if (version.Path && user && user.Policy.IsAdministrator) {
html += createAttribute(globalize.translate('MediaInfoPath'), version.Path) + '<br/>'; html += `${createAttribute(globalize.translate('MediaInfoPath'), version.Path)}<br/>`;
} }
if (version.Size) { if (version.Size) {
var size = (version.Size / (1024 * 1024)).toFixed(0) + ' MB'; const size = `${(version.Size / (1024 * 1024)).toFixed(0)} MB`;
html += createAttribute(globalize.translate('MediaInfoSize'), size) + '<br/>'; html += `${createAttribute(globalize.translate('MediaInfoSize'), size)}<br/>`;
} }
for (var i = 0, length = version.MediaStreams.length; i < length; i++) { for (let i = 0, length = version.MediaStreams.length; i < length; i++) {
var stream = version.MediaStreams[i]; const stream = version.MediaStreams[i];
if (stream.Type === 'Data') { if (stream.Type === 'Data') {
continue; continue;
} }
html += '<div class="mediaInfoStream">'; html += '<div class="mediaInfoStream">';
var displayType = globalize.translate('MediaInfoStreamType' + stream.Type); let translateString;
html += '<h2 class="mediaInfoStreamType">' + displayType + '</h2>'; switch (stream.Type) {
var attributes = []; case 'Audio':
case 'Data':
case 'Subtitle':
case 'Video':
translateString = stream.Type;
break;
case 'EmbeddedImage':
translateString = 'Image';
break;
}
const displayType = globalize.translate(translateString);
html += `<h2 class="mediaInfoStreamType">${displayType}</h2>`;
const attributes = [];
if (stream.DisplayTitle) { if (stream.DisplayTitle) {
attributes.push(createAttribute('Title', stream.DisplayTitle)); attributes.push(createAttribute('Title', stream.DisplayTitle));
} }
@ -61,7 +91,7 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings',
attributes.push(createAttribute(globalize.translate('MediaInfoLevel'), stream.Level)); attributes.push(createAttribute(globalize.translate('MediaInfoLevel'), stream.Level));
} }
if (stream.Width || stream.Height) { if (stream.Width || stream.Height) {
attributes.push(createAttribute(globalize.translate('MediaInfoResolution'), stream.Width + 'x' + stream.Height)); attributes.push(createAttribute(globalize.translate('MediaInfoResolution'), `${stream.Width}x${stream.Height}`));
} }
if (stream.AspectRatio && stream.Codec !== 'mjpeg') { if (stream.AspectRatio && stream.Codec !== 'mjpeg') {
attributes.push(createAttribute(globalize.translate('MediaInfoAspectRatio'), stream.AspectRatio)); attributes.push(createAttribute(globalize.translate('MediaInfoAspectRatio'), stream.AspectRatio));
@ -79,16 +109,28 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings',
attributes.push(createAttribute(globalize.translate('MediaInfoLayout'), stream.ChannelLayout)); attributes.push(createAttribute(globalize.translate('MediaInfoLayout'), stream.ChannelLayout));
} }
if (stream.Channels) { if (stream.Channels) {
attributes.push(createAttribute(globalize.translate('MediaInfoChannels'), stream.Channels + ' ch')); attributes.push(createAttribute(globalize.translate('MediaInfoChannels'), `${stream.Channels} ch`));
} }
if (stream.BitRate && stream.Codec !== 'mjpeg') { if (stream.BitRate && stream.Codec !== 'mjpeg') {
attributes.push(createAttribute(globalize.translate('MediaInfoBitrate'), (parseInt(stream.BitRate / 1000)) + ' kbps')); attributes.push(createAttribute(globalize.translate('MediaInfoBitrate'), `${parseInt(stream.BitRate / 1000)} kbps`));
} }
if (stream.SampleRate) { if (stream.SampleRate) {
attributes.push(createAttribute(globalize.translate('MediaInfoSampleRate'), stream.SampleRate + ' Hz')); attributes.push(createAttribute(globalize.translate('MediaInfoSampleRate'), `${stream.SampleRate} Hz`));
} }
if (stream.BitDepth) { if (stream.BitDepth) {
attributes.push(createAttribute(globalize.translate('MediaInfoBitDepth'), stream.BitDepth + ' bit')); attributes.push(createAttribute(globalize.translate('MediaInfoBitDepth'), `${stream.BitDepth} bit`));
}
if (stream.VideoRange) {
attributes.push(createAttribute(globalize.translate('MediaInfoVideoRange'), stream.VideoRange));
}
if (stream.ColorSpace) {
attributes.push(createAttribute(globalize.translate('MediaInfoColorSpace'), stream.ColorSpace));
}
if (stream.ColorTransfer) {
attributes.push(createAttribute(globalize.translate('MediaInfoColorTransfer'), stream.ColorTransfer));
}
if (stream.ColorPrimaries) {
attributes.push(createAttribute(globalize.translate('MediaInfoColorPrimaries'), stream.ColorPrimaries));
} }
if (stream.PixelFormat) { if (stream.PixelFormat) {
attributes.push(createAttribute(globalize.translate('MediaInfoPixelFormat'), stream.PixelFormat)); attributes.push(createAttribute(globalize.translate('MediaInfoPixelFormat'), stream.PixelFormat));
@ -116,13 +158,13 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings',
} }
function createAttribute(label, value) { function createAttribute(label, value) {
return '<span class="mediaInfoLabel">' + label + '</span><span class="mediaInfoAttribute">' + value + '</span>'; return `<span class="mediaInfoLabel">${label}</span><span class="mediaInfoAttribute">${value}</span>`;
} }
function showMediaInfoMore(itemId, serverId, template) { function loadMediaInfo(itemId, serverId, template) {
var apiClient = connectionManager.getApiClient(serverId); const apiClient = window.connectionManager.getApiClient(serverId);
return apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) { return apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(item => {
var dialogOptions = { const dialogOptions = {
size: 'small', size: 'small',
removeOnClose: true, removeOnClose: true,
scrollY: false scrollY: false
@ -130,35 +172,35 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings',
if (layoutManager.tv) { if (layoutManager.tv) {
dialogOptions.size = 'fullscreen'; dialogOptions.size = 'fullscreen';
} }
var dlg = dialogHelper.createDialog(dialogOptions); const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog'); dlg.classList.add('formDialog');
var html = ''; let html = '';
html += globalize.translateDocument(template, 'core'); html += globalize.translateHtml(template, 'core');
dlg.innerHTML = html; dlg.innerHTML = html;
if (layoutManager.tv) { if (layoutManager.tv) {
dlg.querySelector('.formDialogContent'); dlg.querySelector('.formDialogContent');
} }
dialogHelper.open(dlg); dialogHelper.open(dlg);
dlg.querySelector('.btnCancel').addEventListener('click', function (e) { dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg); dialogHelper.close(dlg);
}); });
apiClient.getCurrentUser().then(function (user) { apiClient.getCurrentUser().then(user => {
setMediaInfo(user, dlg, item); setMediaInfo(user, dlg, item);
}); });
loading.hide(); loading.hide();
}); });
} }
function showMediaInfo(itemId, serverId) { export function show(itemId, serverId) {
loading.show(); loading.show();
return new Promise(function (resolve, reject) { return import('text!./itemMediaInfo.template.html').then(({default: template}) => {
require(['text!./itemMediaInfo.template.html'], function (template) { return new Promise((resolve, reject) => {
showMediaInfoMore(itemId, serverId, template).then(resolve, reject); loadMediaInfo(itemId, serverId, template).then(resolve, reject);
}); });
}); });
} }
return { /* eslint-enable indent */
show: showMediaInfo export default {
}; show: show
}); };

View file

@ -2,7 +2,7 @@
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"> <button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1">
<span class="material-icons arrow_back"></span> <span class="material-icons arrow_back"></span>
</button> </button>
<h3 class="formDialogHeaderTitle">${HeaderMediaInfo}</h3> <h3 class="formDialogHeaderTitle">${MoreMediaInfo}</h3>
</div> </div>
<div class="formDialogContent smoothScrollY"> <div class="formDialogContent smoothScrollY">

View file

@ -1,36 +1,51 @@
define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', 'scrollHelper', 'layoutManager', 'focusManager', 'browser', 'emby-input', 'emby-checkbox', 'paper-icon-button-light', 'css!./../formdialog', 'material-icons', 'cardStyle'], function (dialogHelper, loading, connectionManager, require, globalize, scrollHelper, layoutManager, focusManager, browser) { /* eslint-disable indent */
'use strict';
var enableFocusTransform = !browser.slow && !browser.edge; /**
* Module for itemidentifier media item.
* @module components/itemidentifier/itemidentifier
*/
var currentItem; import dialogHelper from 'dialogHelper';
var currentItemType; import loading from 'loading';
var currentServerId; import globalize from 'globalize';
var currentResolve; import scrollHelper from 'scrollHelper';
var currentReject; import layoutManager from 'layoutManager';
var hasChanges = false; import focusManager from 'focusManager';
var currentSearchResult; import browser from 'browser';
import 'emby-input';
import 'emby-checkbox';
import 'paper-icon-button-light';
import 'css!./../formdialog';
import 'material-icons';
import 'cardStyle';
const enableFocusTransform = !browser.slow && !browser.edge;
let currentItem;
let currentItemType;
let currentServerId;
let currentResolve;
let currentReject;
let hasChanges = false;
let currentSearchResult;
function getApiClient() { function getApiClient() {
return connectionManager.getApiClient(currentServerId); return window.connectionManager.getApiClient(currentServerId);
} }
function searchForIdentificationResults(page) { function searchForIdentificationResults(page) {
let lookupInfo = {
var lookupInfo = {
ProviderIds: {} ProviderIds: {}
}; };
var i; let i;
var length; let length;
var identifyField = page.querySelectorAll('.identifyField'); const identifyField = page.querySelectorAll('.identifyField');
var value; let value;
for (i = 0, length = identifyField.length; i < length; i++) { for (i = 0, length = identifyField.length; i < length; i++) {
value = identifyField[i].value; value = identifyField[i].value;
if (value) { if (value) {
if (identifyField[i].type === 'number') { if (identifyField[i].type === 'number') {
value = parseInt(value); value = parseInt(value);
} }
@ -39,11 +54,10 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
} }
} }
var hasId = false; let hasId = false;
var txtLookupId = page.querySelectorAll('.txtLookupId'); const txtLookupId = page.querySelectorAll('.txtLookupId');
for (i = 0, length = txtLookupId.length; i < length; i++) { for (i = 0, length = txtLookupId.length; i < length; i++) {
value = txtLookupId[i].value; value = txtLookupId[i].value;
if (value) { if (value) {
@ -53,7 +67,7 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
} }
if (!hasId && !lookupInfo.Name) { if (!hasId && !lookupInfo.Name) {
require(['toast'], function (toast) { import('toast').then(({default: toast}) => {
toast(globalize.translate('PleaseEnterNameOrId')); toast(globalize.translate('PleaseEnterNameOrId'));
}); });
return; return;
@ -71,60 +85,54 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
loading.show(); loading.show();
var apiClient = getApiClient(); const apiClient = getApiClient();
apiClient.ajax({ apiClient.ajax({
type: 'POST', type: 'POST',
url: apiClient.getUrl('Items/RemoteSearch/' + currentItemType), url: apiClient.getUrl(`Items/RemoteSearch/${currentItemType}`),
data: JSON.stringify(lookupInfo), data: JSON.stringify(lookupInfo),
contentType: 'application/json', contentType: 'application/json',
dataType: 'json' dataType: 'json'
}).then(function (results) { }).then(results => {
loading.hide(); loading.hide();
showIdentificationSearchResults(page, results); showIdentificationSearchResults(page, results);
}); });
} }
function showIdentificationSearchResults(page, results) { function showIdentificationSearchResults(page, results) {
const identificationSearchResults = page.querySelector('.identificationSearchResults');
var identificationSearchResults = page.querySelector('.identificationSearchResults');
page.querySelector('.popupIdentifyForm').classList.add('hide'); page.querySelector('.popupIdentifyForm').classList.add('hide');
identificationSearchResults.classList.remove('hide'); identificationSearchResults.classList.remove('hide');
page.querySelector('.identifyOptionsForm').classList.add('hide'); page.querySelector('.identifyOptionsForm').classList.add('hide');
page.querySelector('.dialogContentInner').classList.remove('dialog-content-centered'); page.querySelector('.dialogContentInner').classList.remove('dialog-content-centered');
var html = ''; let html = '';
var i; let i;
var length; let length;
for (i = 0, length = results.length; i < length; i++) { for (i = 0, length = results.length; i < length; i++) {
const result = results[i];
var result = results[i];
html += getSearchResultHtml(result, i); html += getSearchResultHtml(result, i);
} }
var elem = page.querySelector('.identificationSearchResultList'); const elem = page.querySelector('.identificationSearchResultList');
elem.innerHTML = html; elem.innerHTML = html;
function onSearchImageClick() { function onSearchImageClick() {
var index = parseInt(this.getAttribute('data-index')); const index = parseInt(this.getAttribute('data-index'));
var currentResult = results[index]; const currentResult = results[index];
if (currentItem != null) { if (currentItem != null) {
showIdentifyOptions(page, currentResult); showIdentifyOptions(page, currentResult);
} else { } else {
finishFindNewDialog(page, currentResult); finishFindNewDialog(page, currentResult);
} }
} }
var searchImages = elem.querySelectorAll('.card'); const searchImages = elem.querySelectorAll('.card');
for (i = 0, length = searchImages.length; i < length; i++) { for (i = 0, length = searchImages.length; i < length; i++) {
searchImages[i].addEventListener('click', onSearchImageClick); searchImages[i].addEventListener('click', onSearchImageClick);
} }
@ -142,8 +150,7 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
} }
function showIdentifyOptions(page, identifyResult) { function showIdentifyOptions(page, identifyResult) {
const identifyOptionsForm = page.querySelector('.identifyOptionsForm');
var identifyOptionsForm = page.querySelector('.identifyOptionsForm');
page.querySelector('.popupIdentifyForm').classList.add('hide'); page.querySelector('.popupIdentifyForm').classList.add('hide');
page.querySelector('.identificationSearchResults').classList.add('hide'); page.querySelector('.identificationSearchResults').classList.add('hide');
@ -153,19 +160,19 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
currentSearchResult = identifyResult; currentSearchResult = identifyResult;
var lines = []; const lines = [];
lines.push(identifyResult.Name); lines.push(identifyResult.Name);
if (identifyResult.ProductionYear) { if (identifyResult.ProductionYear) {
lines.push(identifyResult.ProductionYear); lines.push(identifyResult.ProductionYear);
} }
var resultHtml = lines.join('<br/>'); let resultHtml = lines.join('<br/>');
if (identifyResult.ImageUrl) { if (identifyResult.ImageUrl) {
var displayUrl = getSearchImageDisplayUrl(identifyResult.ImageUrl, identifyResult.SearchProviderName); const displayUrl = getSearchImageDisplayUrl(identifyResult.ImageUrl, identifyResult.SearchProviderName);
resultHtml = '<div style="display:flex;align-items:center;"><img src="' + displayUrl + '" style="max-height:240px;" /><div style="margin-left:1em;">' + resultHtml + '</div>'; resultHtml = `<div style="display:flex;align-items:center;"><img src="${displayUrl}" style="max-height:240px;" /><div style="margin-left:1em;">${resultHtml}</div>`;
} }
page.querySelector('.selectedSearchResult').innerHTML = resultHtml; page.querySelector('.selectedSearchResult').innerHTML = resultHtml;
@ -174,13 +181,12 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
} }
function getSearchResultHtml(result, index) { function getSearchResultHtml(result, index) {
// TODO move card creation code to Card component // TODO move card creation code to Card component
var html = ''; let html = '';
var cssClass = 'card scalableCard'; let cssClass = 'card scalableCard';
var cardBoxCssClass = 'cardBox'; let cardBoxCssClass = 'cardBox';
var padderClass; let padderClass;
if (currentItemType === 'Episode') { if (currentItemType === 'Episode') {
cssClass += ' backdropCard backdropCard-scalable'; cssClass += ' backdropCard backdropCard-scalable';
@ -203,30 +209,31 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
cardBoxCssClass += ' cardBox-bottompadded'; cardBoxCssClass += ' cardBox-bottompadded';
html += '<button type="button" class="' + cssClass + '" data-index="' + index + '">'; html += `<button type="button" class="${cssClass}" data-index="${index}">`;
html += '<div class="' + cardBoxCssClass + '">'; html += `<div class="${cardBoxCssClass}">`;
html += '<div class="cardScalable">'; html += '<div class="cardScalable">';
html += '<div class="' + padderClass + '"></div>'; html += `<div class="${padderClass}"></div>`;
html += '<div class="cardContent searchImage">'; html += '<div class="cardContent searchImage">';
if (result.ImageUrl) { if (result.ImageUrl) {
var displayUrl = getSearchImageDisplayUrl(result.ImageUrl, result.SearchProviderName); const displayUrl = getSearchImageDisplayUrl(result.ImageUrl, result.SearchProviderName);
html += '<div class="cardImageContainer coveredImage" style="background-image:url(\'' + displayUrl + '\');"></div>'; html += `<div class="cardImageContainer coveredImage" style="background-image:url('${displayUrl}');"></div>`;
} else { } else {
html += `<div class="cardImageContainer coveredImage defaultCardBackground defaultCardBackground1"><div class="cardText cardCenteredText">${result.Name}</div></div>`;
html += '<div class="cardImageContainer coveredImage defaultCardBackground defaultCardBackground1"><div class="cardText cardCenteredText">' + result.Name + '</div></div>';
} }
html += '</div>'; html += '</div>';
html += '</div>'; html += '</div>';
var numLines = 2; let numLines = 3;
if (currentItemType === 'MusicAlbum') { if (currentItemType === 'MusicAlbum') {
numLines++; numLines++;
} }
var lines = [result.Name]; const lines = [result.Name];
lines.push(result.SearchProviderName);
if (result.AlbumArtist) { if (result.AlbumArtist) {
lines.push(result.AlbumArtist.Name); lines.push(result.AlbumArtist.Name);
@ -235,8 +242,7 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
lines.push(result.ProductionYear); lines.push(result.ProductionYear);
} }
for (var i = 0; i < numLines; i++) { for (let i = 0; i < numLines; i++) {
if (i === 0) { if (i === 0) {
html += '<div class="cardText cardText-first cardTextCentered">'; html += '<div class="cardText cardText-first cardTextCentered">';
} else { } else {
@ -252,36 +258,32 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
} }
function getSearchImageDisplayUrl(url, provider) { function getSearchImageDisplayUrl(url, provider) {
var apiClient = getApiClient(); const apiClient = getApiClient();
return apiClient.getUrl('Items/RemoteSearch/Image', { imageUrl: url, ProviderName: provider }); return apiClient.getUrl('Items/RemoteSearch/Image', { imageUrl: url, ProviderName: provider });
} }
function submitIdentficationResult(page) { function submitIdentficationResult(page) {
loading.show(); loading.show();
var options = { const options = {
ReplaceAllImages: page.querySelector('#chkIdentifyReplaceImages').checked ReplaceAllImages: page.querySelector('#chkIdentifyReplaceImages').checked
}; };
var apiClient = getApiClient(); const apiClient = getApiClient();
apiClient.ajax({ apiClient.ajax({
type: 'POST', type: 'POST',
url: apiClient.getUrl('Items/RemoteSearch/Apply/' + currentItem.Id, options), url: apiClient.getUrl(`Items/RemoteSearch/Apply/${currentItem.Id}`, options),
data: JSON.stringify(currentSearchResult), data: JSON.stringify(currentSearchResult),
contentType: 'application/json' contentType: 'application/json'
}).then(function () { }).then(() => {
hasChanges = true; hasChanges = true;
loading.hide(); loading.hide();
dialogHelper.close(page); dialogHelper.close(page);
}, () => {
}, function () {
loading.hide(); loading.hide();
dialogHelper.close(page); dialogHelper.close(page);
@ -289,29 +291,26 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
} }
function showIdentificationForm(page, item) { function showIdentificationForm(page, item) {
const apiClient = getApiClient();
var apiClient = getApiClient(); apiClient.getJSON(apiClient.getUrl(`Items/${item.Id}/ExternalIdInfos`)).then(idList => {
let html = '';
apiClient.getJSON(apiClient.getUrl('Items/' + item.Id + '/ExternalIdInfos')).then(function (idList) { for (let i = 0, length = idList.length; i < length; i++) {
const idInfo = idList[i];
var html = ''; const id = `txtLookup${idInfo.Key}`;
for (var i = 0, length = idList.length; i < length; i++) {
var idInfo = idList[i];
var id = 'txtLookup' + idInfo.Key;
html += '<div class="inputContainer">'; html += '<div class="inputContainer">';
var fullName = idInfo.Name; let fullName = idInfo.Name;
if (idInfo.Type) { if (idInfo.Type) {
fullName = idInfo.Name + ' ' + globalize.translate(idInfo.Type); fullName = `${idInfo.Name} ${globalize.translate(idInfo.Type)}`;
} }
var idLabel = globalize.translate('LabelDynamicExternalId', fullName); const idLabel = globalize.translate('LabelDynamicExternalId', fullName);
html += '<input is="emby-input" class="txtLookupId" data-providerkey="' + idInfo.Key + '" id="' + id + '" label="' + idLabel + '"/>'; html += `<input is="emby-input" class="txtLookupId" data-providerkey="${idInfo.Key}" id="${id}" label="${idLabel}"/>`;
html += '</div>'; html += '</div>';
} }
@ -319,11 +318,9 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
page.querySelector('#txtLookupName').value = ''; page.querySelector('#txtLookupName').value = '';
if (item.Type === 'Person' || item.Type === 'BoxSet') { if (item.Type === 'Person' || item.Type === 'BoxSet') {
page.querySelector('.fldLookupYear').classList.add('hide'); page.querySelector('.fldLookupYear').classList.add('hide');
page.querySelector('#txtLookupYear').value = ''; page.querySelector('#txtLookupYear').value = '';
} else { } else {
page.querySelector('.fldLookupYear').classList.remove('hide'); page.querySelector('.fldLookupYear').classList.remove('hide');
page.querySelector('#txtLookupYear').value = ''; page.querySelector('#txtLookupYear').value = '';
} }
@ -335,19 +332,16 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
} }
function showEditor(itemId) { function showEditor(itemId) {
loading.show(); loading.show();
require(['text!./itemidentifier.template.html'], function (template) { return import('text!./itemidentifier.template.html').then(({default: template}) => {
const apiClient = getApiClient();
var apiClient = getApiClient();
apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) {
apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(item => {
currentItem = item; currentItem = item;
currentItemType = currentItem.Type; currentItemType = currentItem.Type;
var dialogOptions = { const dialogOptions = {
size: 'small', size: 'small',
removeOnClose: true, removeOnClose: true,
scrollY: false scrollY: false
@ -357,13 +351,13 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
dialogOptions.size = 'fullscreen'; dialogOptions.size = 'fullscreen';
} }
var dlg = dialogHelper.createDialog(dialogOptions); const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog'); dlg.classList.add('formDialog');
dlg.classList.add('recordingDialog'); dlg.classList.add('recordingDialog');
var html = ''; let html = '';
html += globalize.translateDocument(template, 'core'); html += globalize.translateHtml(template, 'core');
dlg.innerHTML = html; dlg.innerHTML = html;
@ -384,22 +378,19 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
dialogHelper.open(dlg); dialogHelper.open(dlg);
dlg.querySelector('.popupIdentifyForm').addEventListener('submit', function (e) { dlg.querySelector('.popupIdentifyForm').addEventListener('submit', e => {
e.preventDefault(); e.preventDefault();
searchForIdentificationResults(dlg); searchForIdentificationResults(dlg);
return false; return false;
}); });
dlg.querySelector('.identifyOptionsForm').addEventListener('submit', function (e) { dlg.querySelector('.identifyOptionsForm').addEventListener('submit', e => {
e.preventDefault(); e.preventDefault();
submitIdentficationResult(dlg); submitIdentficationResult(dlg);
return false; return false;
}); });
dlg.querySelector('.btnCancel').addEventListener('click', function (e) { dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg); dialogHelper.close(dlg);
}); });
@ -412,7 +403,6 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
} }
function onDialogClosed() { function onDialogClosed() {
loading.hide(); loading.hide();
if (hasChanges) { if (hasChanges) {
currentResolve(); currentResolve();
@ -421,14 +411,13 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
} }
} }
// TODO investigate where this was used
function showEditorFindNew(itemName, itemYear, itemType, resolveFunc) { function showEditorFindNew(itemName, itemYear, itemType, resolveFunc) {
currentItem = null; currentItem = null;
currentItemType = itemType; currentItemType = itemType;
require(['text!./itemidentifier.template.html'], function (template) { return import('text!./itemidentifier.template.html').then(({default: template}) => {
const dialogOptions = {
var dialogOptions = {
size: 'small', size: 'small',
removeOnClose: true, removeOnClose: true,
scrollY: false scrollY: false
@ -438,13 +427,13 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
dialogOptions.size = 'fullscreen'; dialogOptions.size = 'fullscreen';
} }
var dlg = dialogHelper.createDialog(dialogOptions); const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog'); dlg.classList.add('formDialog');
dlg.classList.add('recordingDialog'); dlg.classList.add('recordingDialog');
var html = ''; let html = '';
html += globalize.translateDocument(template, 'core'); html += globalize.translateHtml(template, 'core');
dlg.innerHTML = html; dlg.innerHTML = html;
@ -454,22 +443,19 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
dialogHelper.open(dlg); dialogHelper.open(dlg);
dlg.querySelector('.btnCancel').addEventListener('click', function (e) { dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg); dialogHelper.close(dlg);
}); });
dlg.querySelector('.popupIdentifyForm').addEventListener('submit', function (e) { dlg.querySelector('.popupIdentifyForm').addEventListener('submit', e => {
e.preventDefault(); e.preventDefault();
searchForIdentificationResults(dlg); searchForIdentificationResults(dlg);
return false; return false;
}); });
dlg.addEventListener('close', function () { dlg.addEventListener('close', () => {
loading.hide(); loading.hide();
var foundItem = hasChanges ? currentSearchResult : null; const foundItem = hasChanges ? currentSearchResult : null;
resolveFunc(foundItem); resolveFunc(foundItem);
}); });
@ -481,16 +467,12 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
} }
function showIdentificationFormFindNew(dlg, itemName, itemYear, itemType) { function showIdentificationFormFindNew(dlg, itemName, itemYear, itemType) {
dlg.querySelector('#txtLookupName').value = itemName; dlg.querySelector('#txtLookupName').value = itemName;
if (itemType === 'Person' || itemType === 'BoxSet') { if (itemType === 'Person' || itemType === 'BoxSet') {
dlg.querySelector('.fldLookupYear').classList.add('hide'); dlg.querySelector('.fldLookupYear').classList.add('hide');
dlg.querySelector('#txtLookupYear').value = ''; dlg.querySelector('#txtLookupYear').value = '';
} else { } else {
dlg.querySelector('.fldLookupYear').classList.remove('hide'); dlg.querySelector('.fldLookupYear').classList.remove('hide');
dlg.querySelector('#txtLookupYear').value = itemYear; dlg.querySelector('#txtLookupYear').value = itemYear;
} }
@ -498,11 +480,8 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
dlg.querySelector('.formDialogHeaderTitle').innerHTML = globalize.translate('Search'); dlg.querySelector('.formDialogHeaderTitle').innerHTML = globalize.translate('Search');
} }
return { export function show(itemId, serverId) {
show: function (itemId, serverId) { return new Promise((resolve, reject) => {
return new Promise(function (resolve, reject) {
currentResolve = resolve; currentResolve = resolve;
currentReject = reject; currentReject = reject;
currentServerId = serverId; currentServerId = serverId;
@ -510,17 +489,19 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
showEditor(itemId); showEditor(itemId);
}); });
}, }
showFindNew: function (itemName, itemYear, itemType, serverId) {
return new Promise(function (resolve, reject) {
export function showFindNew(itemName, itemYear, itemType, serverId) {
return new Promise((resolve) => {
currentServerId = serverId; currentServerId = serverId;
hasChanges = false; hasChanges = false;
showEditorFindNew(itemName, itemYear, itemType, resolve); showEditorFindNew(itemName, itemYear, itemType, resolve);
}); });
} }
};
}); /* eslint-enable indent */
export default {
show: show,
showFindNew: showFindNew
};

View file

@ -1,96 +1,84 @@
define(['playbackManager', 'serverNotifications', 'events'], function (playbackManager, serverNotifications, events) { import playbackManager from 'playbackManager';
'use strict'; import serverNotifications from 'serverNotifications';
import events from 'events';
function onUserDataChanged(e, apiClient, userData) { function onUserDataChanged(e, apiClient, userData) {
const instance = this;
var instance = this; const eventsToMonitor = getEventsToMonitor(instance);
var eventsToMonitor = getEventsToMonitor(instance);
// TODO: Check user data change reason? // TODO: Check user data change reason?
if (eventsToMonitor.indexOf('markfavorite') !== -1) { if (eventsToMonitor.indexOf('markfavorite') !== -1) {
instance.notifyRefreshNeeded(); instance.notifyRefreshNeeded();
} else if (eventsToMonitor.indexOf('markplayed') !== -1) { } else if (eventsToMonitor.indexOf('markplayed') !== -1) {
instance.notifyRefreshNeeded(); instance.notifyRefreshNeeded();
} }
} }
function getEventsToMonitor(instance) { function getEventsToMonitor(instance) {
const options = instance.options;
var options = instance.options; const monitor = options ? options.monitorEvents : null;
var monitor = options ? options.monitorEvents : null;
if (monitor) { if (monitor) {
return monitor.split(','); return monitor.split(',');
} }
return []; return [];
} }
function onTimerCreated(e, apiClient, data) { function onTimerCreated(e, apiClient, data) {
const instance = this;
var instance = this;
if (getEventsToMonitor(instance).indexOf('timers') !== -1) { if (getEventsToMonitor(instance).indexOf('timers') !== -1) {
instance.notifyRefreshNeeded(); instance.notifyRefreshNeeded();
return; return;
} }
} }
function onSeriesTimerCreated(e, apiClient, data) { function onSeriesTimerCreated(e, apiClient, data) {
const instance = this;
var instance = this;
if (getEventsToMonitor(instance).indexOf('seriestimers') !== -1) { if (getEventsToMonitor(instance).indexOf('seriestimers') !== -1) {
instance.notifyRefreshNeeded(); instance.notifyRefreshNeeded();
return; return;
} }
} }
function onTimerCancelled(e, apiClient, data) { function onTimerCancelled(e, apiClient, data) {
var instance = this; const instance = this;
if (getEventsToMonitor(instance).indexOf('timers') !== -1) { if (getEventsToMonitor(instance).indexOf('timers') !== -1) {
instance.notifyRefreshNeeded(); instance.notifyRefreshNeeded();
return; return;
} }
} }
function onSeriesTimerCancelled(e, apiClient, data) { function onSeriesTimerCancelled(e, apiClient, data) {
const instance = this;
var instance = this;
if (getEventsToMonitor(instance).indexOf('seriestimers') !== -1) { if (getEventsToMonitor(instance).indexOf('seriestimers') !== -1) {
instance.notifyRefreshNeeded(); instance.notifyRefreshNeeded();
return; return;
} }
} }
function onLibraryChanged(e, apiClient, data) { function onLibraryChanged(e, apiClient, data) {
const instance = this;
var instance = this; const eventsToMonitor = getEventsToMonitor(instance);
var eventsToMonitor = getEventsToMonitor(instance);
if (eventsToMonitor.indexOf('seriestimers') !== -1 || eventsToMonitor.indexOf('timers') !== -1) { if (eventsToMonitor.indexOf('seriestimers') !== -1 || eventsToMonitor.indexOf('timers') !== -1) {
// yes this is an assumption // yes this is an assumption
return; return;
} }
var itemsAdded = data.ItemsAdded || []; const itemsAdded = data.ItemsAdded || [];
var itemsRemoved = data.ItemsRemoved || []; const itemsRemoved = data.ItemsRemoved || [];
if (!itemsAdded.length && !itemsRemoved.length) { if (!itemsAdded.length && !itemsRemoved.length) {
return; return;
} }
var options = instance.options || {}; const options = instance.options || {};
var parentId = options.parentId; const parentId = options.parentId;
if (parentId) { if (parentId) {
var foldersAddedTo = data.FoldersAddedTo || []; const foldersAddedTo = data.FoldersAddedTo || [];
var foldersRemovedFrom = data.FoldersRemovedFrom || []; const foldersRemovedFrom = data.FoldersRemovedFrom || [];
var collectionFolders = data.CollectionFolders || []; const collectionFolders = data.CollectionFolders || [];
if (foldersAddedTo.indexOf(parentId) === -1 && foldersRemovedFrom.indexOf(parentId) === -1 && collectionFolders.indexOf(parentId) === -1) { if (foldersAddedTo.indexOf(parentId) === -1 && foldersRemovedFrom.indexOf(parentId) === -1 && collectionFolders.indexOf(parentId) === -1) {
return; return;
@ -98,52 +86,45 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
} }
instance.notifyRefreshNeeded(); instance.notifyRefreshNeeded();
} }
function onPlaybackStopped(e, stopInfo) { function onPlaybackStopped(e, stopInfo) {
const instance = this;
var instance = this; const state = stopInfo.state;
var state = stopInfo.state; const eventsToMonitor = getEventsToMonitor(instance);
var eventsToMonitor = getEventsToMonitor(instance);
if (state.NowPlayingItem && state.NowPlayingItem.MediaType === 'Video') { if (state.NowPlayingItem && state.NowPlayingItem.MediaType === 'Video') {
if (eventsToMonitor.indexOf('videoplayback') !== -1) { if (eventsToMonitor.indexOf('videoplayback') !== -1) {
instance.notifyRefreshNeeded(true); instance.notifyRefreshNeeded(true);
return; return;
} }
} else if (state.NowPlayingItem && state.NowPlayingItem.MediaType === 'Audio') { } else if (state.NowPlayingItem && state.NowPlayingItem.MediaType === 'Audio') {
if (eventsToMonitor.indexOf('audioplayback') !== -1) { if (eventsToMonitor.indexOf('audioplayback') !== -1) {
instance.notifyRefreshNeeded(true); instance.notifyRefreshNeeded(true);
return; return;
} }
} }
} }
function addNotificationEvent(instance, name, handler, owner) { function addNotificationEvent(instance, name, handler, owner) {
const localHandler = handler.bind(instance);
var localHandler = handler.bind(instance);
owner = owner || serverNotifications; owner = owner || serverNotifications;
events.on(owner, name, localHandler); events.on(owner, name, localHandler);
instance['event_' + name] = localHandler; instance['event_' + name] = localHandler;
} }
function removeNotificationEvent(instance, name, owner) { function removeNotificationEvent(instance, name, owner) {
const handler = instance['event_' + name];
var handler = instance['event_' + name];
if (handler) { if (handler) {
owner = owner || serverNotifications; owner = owner || serverNotifications;
events.off(owner, name, handler); events.off(owner, name, handler);
instance['event_' + name] = null; instance['event_' + name] = null;
} }
} }
function ItemsRefresher(options) {
class ItemsRefresher {
constructor(options) {
this.options = options || {}; this.options = options || {};
addNotificationEvent(this, 'UserDataChanged', onUserDataChanged); addNotificationEvent(this, 'UserDataChanged', onUserDataChanged);
@ -155,25 +136,20 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
addNotificationEvent(this, 'playbackstop', onPlaybackStopped, playbackManager); addNotificationEvent(this, 'playbackstop', onPlaybackStopped, playbackManager);
} }
ItemsRefresher.prototype.pause = function () { pause() {
clearRefreshInterval(this, true); clearRefreshInterval(this, true);
this.paused = true; this.paused = true;
}; }
ItemsRefresher.prototype.resume = function (options) {
resume(options) {
this.paused = false; this.paused = false;
var refreshIntervalEndTime = this.refreshIntervalEndTime; const refreshIntervalEndTime = this.refreshIntervalEndTime;
if (refreshIntervalEndTime) { if (refreshIntervalEndTime) {
const remainingMs = refreshIntervalEndTime - new Date().getTime();
var remainingMs = refreshIntervalEndTime - new Date().getTime();
if (remainingMs > 0 && !this.needsRefresh) { if (remainingMs > 0 && !this.needsRefresh) {
resetRefreshInterval(this, remainingMs); resetRefreshInterval(this, remainingMs);
} else { } else {
this.needsRefresh = true; this.needsRefresh = true;
this.refreshIntervalEndTime = null; this.refreshIntervalEndTime = null;
@ -185,10 +161,9 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
} }
return Promise.resolve(); return Promise.resolve();
}; }
ItemsRefresher.prototype.refreshItems = function () {
refreshItems() {
if (!this.fetchData) { if (!this.fetchData) {
return Promise.resolve(); return Promise.resolve();
} }
@ -201,16 +176,15 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
this.needsRefresh = false; this.needsRefresh = false;
return this.fetchData().then(onDataFetched.bind(this)); return this.fetchData().then(onDataFetched.bind(this));
}; }
ItemsRefresher.prototype.notifyRefreshNeeded = function (isInForeground) {
notifyRefreshNeeded(isInForeground) {
if (this.paused) { if (this.paused) {
this.needsRefresh = true; this.needsRefresh = true;
return; return;
} }
var timeout = this.refreshTimeout; const timeout = this.refreshTimeout;
if (timeout) { if (timeout) {
clearTimeout(timeout); clearTimeout(timeout);
} }
@ -220,49 +194,9 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
} else { } else {
this.refreshTimeout = setTimeout(this.refreshItems.bind(this), 10000); this.refreshTimeout = setTimeout(this.refreshItems.bind(this), 10000);
} }
};
function clearRefreshInterval(instance, isPausing) {
if (instance.refreshInterval) {
clearInterval(instance.refreshInterval);
instance.refreshInterval = null;
if (!isPausing) {
instance.refreshIntervalEndTime = null;
}
}
} }
function resetRefreshInterval(instance, intervalMs) { destroy() {
clearRefreshInterval(instance);
if (!intervalMs) {
var options = instance.options;
if (options) {
intervalMs = options.refreshIntervalMs;
}
}
if (intervalMs) {
instance.refreshInterval = setInterval(instance.notifyRefreshNeeded.bind(instance), intervalMs);
instance.refreshIntervalEndTime = new Date().getTime() + intervalMs;
}
}
function onDataFetched(result) {
resetRefreshInterval(this);
if (this.afterRefresh) {
this.afterRefresh(result);
}
}
ItemsRefresher.prototype.destroy = function () {
clearRefreshInterval(this); clearRefreshInterval(this);
removeNotificationEvent(this, 'UserDataChanged'); removeNotificationEvent(this, 'UserDataChanged');
@ -275,7 +209,42 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
this.fetchData = null; this.fetchData = null;
this.options = null; this.options = null;
}; }
}
return ItemsRefresher; function clearRefreshInterval(instance, isPausing) {
}); if (instance.refreshInterval) {
clearInterval(instance.refreshInterval);
instance.refreshInterval = null;
if (!isPausing) {
instance.refreshIntervalEndTime = null;
}
}
}
function resetRefreshInterval(instance, intervalMs) {
clearRefreshInterval(instance);
if (!intervalMs) {
const options = instance.options;
if (options) {
intervalMs = options.refreshIntervalMs;
}
}
if (intervalMs) {
instance.refreshInterval = setInterval(instance.notifyRefreshNeeded.bind(instance), intervalMs);
instance.refreshIntervalEndTime = new Date().getTime() + intervalMs;
}
}
function onDataFetched(result) {
resetRefreshInterval(this);
if (this.afterRefresh) {
this.afterRefresh(result);
}
}
export default ItemsRefresher;

View file

@ -1,7 +1,8 @@
define(['browser', 'appSettings', 'events'], function (browser, appSettings, events) { import browser from 'browser';
'use strict'; import appSettings from 'appSettings';
import events from 'events';
function setLayout(instance, layout, selectedLayout) { function setLayout(instance, layout, selectedLayout) {
if (layout === selectedLayout) { if (layout === selectedLayout) {
instance[layout] = true; instance[layout] = true;
document.documentElement.classList.add('layout-' + layout); document.documentElement.classList.add('layout-' + layout);
@ -9,14 +10,10 @@ define(['browser', 'appSettings', 'events'], function (browser, appSettings, eve
instance[layout] = false; instance[layout] = false;
document.documentElement.classList.remove('layout-' + layout); document.documentElement.classList.remove('layout-' + layout);
} }
} }
function LayoutManager() {
}
LayoutManager.prototype.setLayout = function (layout, save) {
class LayoutManager {
setLayout(layout, save) {
if (!layout || layout === 'auto') { if (!layout || layout === 'auto') {
this.autoLayout(); this.autoLayout();
@ -34,14 +31,13 @@ define(['browser', 'appSettings', 'events'], function (browser, appSettings, eve
} }
events.trigger(this, 'modechange'); events.trigger(this, 'modechange');
}; }
LayoutManager.prototype.getSavedLayout = function (layout) { getSavedLayout(layout) {
return appSettings.get('layout'); return appSettings.get('layout');
}; }
LayoutManager.prototype.autoLayout = function () {
autoLayout() {
// Take a guess at initial layout. The consuming app can override // Take a guess at initial layout. The consuming app can override
if (browser.mobile) { if (browser.mobile) {
this.setLayout('mobile', false); this.setLayout('mobile', false);
@ -50,16 +46,16 @@ define(['browser', 'appSettings', 'events'], function (browser, appSettings, eve
} else { } else {
this.setLayout(this.defaultLayout || 'tv', false); this.setLayout(this.defaultLayout || 'tv', false);
} }
}; }
LayoutManager.prototype.init = function () { init() {
var saved = this.getSavedLayout(); const saved = this.getSavedLayout();
if (saved) { if (saved) {
this.setLayout(saved, false); this.setLayout(saved, false);
} else { } else {
this.autoLayout(); this.autoLayout();
} }
}; }
}
return new LayoutManager(); export default new LayoutManager();
});

View file

@ -1,63 +1,73 @@
define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], function(globalize, dom) { /* eslint-disable indent */
'use strict';
/**
* Module for library options editor.
* @module components/libraryoptionseditor/libraryoptionseditor
*/
import globalize from 'globalize';
import dom from 'dom';
import 'emby-checkbox';
import 'emby-select';
import 'emby-input';
function populateLanguages(parent) { function populateLanguages(parent) {
return ApiClient.getCultures().then(function(languages) { return ApiClient.getCultures().then(languages => {
populateLanguagesIntoSelect(parent.querySelector('#selectLanguage'), languages); populateLanguagesIntoSelect(parent.querySelector('#selectLanguage'), languages);
populateLanguagesIntoList(parent.querySelector('.subtitleDownloadLanguages'), languages); populateLanguagesIntoList(parent.querySelector('.subtitleDownloadLanguages'), languages);
}); });
} }
function populateLanguagesIntoSelect(select, languages) { function populateLanguagesIntoSelect(select, languages) {
var html = ''; let html = '';
html += "<option value=''></option>"; html += "<option value=''></option>";
for (var i = 0; i < languages.length; i++) { for (let i = 0; i < languages.length; i++) {
var culture = languages[i]; const culture = languages[i];
html += "<option value='" + culture.TwoLetterISOLanguageName + "'>" + culture.DisplayName + '</option>'; html += `<option value='${culture.TwoLetterISOLanguageName}'>${culture.DisplayName}</option>`;
} }
select.innerHTML = html; select.innerHTML = html;
} }
function populateLanguagesIntoList(element, languages) { function populateLanguagesIntoList(element, languages) {
var html = ''; let html = '';
for (var i = 0; i < languages.length; i++) { for (let i = 0; i < languages.length; i++) {
var culture = languages[i]; const culture = languages[i];
html += '<label><input type="checkbox" is="emby-checkbox" class="chkSubtitleLanguage" data-lang="' + culture.ThreeLetterISOLanguageName.toLowerCase() + '" /><span>' + culture.DisplayName + '</span></label>'; html += `<label><input type="checkbox" is="emby-checkbox" class="chkSubtitleLanguage" data-lang="${culture.ThreeLetterISOLanguageName.toLowerCase()}" /><span>${culture.DisplayName}</span></label>`;
} }
element.innerHTML = html; element.innerHTML = html;
} }
function populateCountries(select) { function populateCountries(select) {
return ApiClient.getCountries().then(function(allCountries) { return ApiClient.getCountries().then(allCountries => {
var html = ''; let html = '';
html += "<option value=''></option>"; html += "<option value=''></option>";
for (var i = 0; i < allCountries.length; i++) { for (let i = 0; i < allCountries.length; i++) {
var culture = allCountries[i]; const culture = allCountries[i];
html += "<option value='" + culture.TwoLetterISORegionName + "'>" + culture.DisplayName + '</option>'; html += `<option value='${culture.TwoLetterISORegionName}'>${culture.DisplayName}</option>`;
} }
select.innerHTML = html; select.innerHTML = html;
}); });
} }
function populateRefreshInterval(select) { function populateRefreshInterval(select) {
var html = ''; let html = '';
html += "<option value='0'>" + globalize.translate('Never') + '</option>'; html += `<option value='0'>${globalize.translate('Never')}</option>`;
html += [30, 60, 90].map(function(val) { html += [30, 60, 90].map(val => {
return "<option value='" + val + "'>" + globalize.translate('EveryNDays', val) + '</option>'; return `<option value='${val}'>${globalize.translate('EveryNDays', val)}</option>`;
}).join(''); }).join('');
select.innerHTML = html; select.innerHTML = html;
} }
function renderMetadataReaders(page, plugins) { function renderMetadataReaders(page, plugins) {
var html = ''; let html = '';
var elem = page.querySelector('.metadataReaders'); const elem = page.querySelector('.metadataReaders');
if (plugins.length < 1) return elem.innerHTML = '', elem.classList.add('hide'), !1; if (plugins.length < 1) return elem.innerHTML = '', elem.classList.add('hide'), !1;
html += '<h3 class="checkboxListLabel">' + globalize.translate('LabelMetadataReaders') + '</h3>'; html += `<h3 class="checkboxListLabel">${globalize.translate('LabelMetadataReaders')}</h3>`;
html += '<div class="checkboxList paperList checkboxList-paperList">'; html += '<div class="checkboxList paperList checkboxList-paperList">';
for (var i = 0; i < plugins.length; i++) { for (let i = 0; i < plugins.length; i++) {
var plugin = plugins[i]; const plugin = plugins[i];
html += '<div class="listItem localReaderOption sortableOption" data-pluginname="' + plugin.Name + '">'; html += `<div class="listItem localReaderOption sortableOption" data-pluginname="${plugin.Name}">`;
html += '<span class="listItemIcon material-icons live_tv"></span>'; html += '<span class="listItemIcon material-icons live_tv"></span>';
html += '<div class="listItemBody">'; html += '<div class="listItemBody">';
html += '<h3 class="listItemBodyText">'; html += '<h3 class="listItemBodyText">';
@ -65,14 +75,14 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
html += '</h3>'; html += '</h3>';
html += '</div>'; html += '</div>';
if (i > 0) { if (i > 0) {
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('ButtonUp') + '" class="btnSortableMoveUp btnSortable" data-pluginindex="' + i + '"><span class="material-icons keyboard_arrow_up"></span></button>'; html += `<button type="button" is="paper-icon-button-light" title="${globalize.translate('Up')}" class="btnSortableMoveUp btnSortable" data-pluginindex="${i}"><span class="material-icons keyboard_arrow_up"></span></button>`;
} else if (plugins.length > 1) { } else if (plugins.length > 1) {
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('ButtonDown') + '" class="btnSortableMoveDown btnSortable" data-pluginindex="' + i + '"><span class="material-icons keyboard_arrow_down"></span></button>'; html += `<button type="button" is="paper-icon-button-light" title="${globalize.translate('Down')}" class="btnSortableMoveDown btnSortable" data-pluginindex="${i}"><span class="material-icons keyboard_arrow_down"></span></button>`;
} }
html += '</div>'; html += '</div>';
} }
html += '</div>'; html += '</div>';
html += '<div class="fieldDescription">' + globalize.translate('LabelMetadataReadersHelp') + '</div>'; html += `<div class="fieldDescription">${globalize.translate('LabelMetadataReadersHelp')}</div>`;
if (plugins.length < 2) { if (plugins.length < 2) {
elem.classList.add('hide'); elem.classList.add('hide');
} else { } else {
@ -83,25 +93,25 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
} }
function renderMetadataSavers(page, metadataSavers) { function renderMetadataSavers(page, metadataSavers) {
var html = ''; let html = '';
var elem = page.querySelector('.metadataSavers'); const elem = page.querySelector('.metadataSavers');
if (!metadataSavers.length) return elem.innerHTML = '', elem.classList.add('hide'), false; if (!metadataSavers.length) return elem.innerHTML = '', elem.classList.add('hide'), false;
html += '<h3 class="checkboxListLabel">' + globalize.translate('LabelMetadataSavers') + '</h3>'; html += `<h3 class="checkboxListLabel">${globalize.translate('LabelMetadataSavers')}</h3>`;
html += '<div class="checkboxList paperList checkboxList-paperList">'; html += '<div class="checkboxList paperList checkboxList-paperList">';
for (var i = 0; i < metadataSavers.length; i++) { for (let i = 0; i < metadataSavers.length; i++) {
var plugin = metadataSavers[i]; const plugin = metadataSavers[i];
html += '<label><input type="checkbox" data-defaultenabled="' + plugin.DefaultEnabled + '" is="emby-checkbox" class="chkMetadataSaver" data-pluginname="' + plugin.Name + '" ' + false + '><span>' + plugin.Name + '</span></label>'; html += `<label><input type="checkbox" data-defaultenabled="${plugin.DefaultEnabled}" is="emby-checkbox" class="chkMetadataSaver" data-pluginname="${plugin.Name}" ${false}><span>${plugin.Name}</span></label>`;
} }
html += '</div>'; html += '</div>';
html += '<div class="fieldDescription" style="margin-top:.25em;">' + globalize.translate('LabelMetadataSaversHelp') + '</div>'; html += `<div class="fieldDescription" style="margin-top:.25em;">${globalize.translate('LabelMetadataSaversHelp')}</div>`;
elem.innerHTML = html; elem.innerHTML = html;
elem.classList.remove('hide'); elem.classList.remove('hide');
return true; return true;
} }
function getMetadataFetchersForTypeHtml(availableTypeOptions, libraryOptionsForType) { function getMetadataFetchersForTypeHtml(availableTypeOptions, libraryOptionsForType) {
var html = ''; let html = '';
var plugins = availableTypeOptions.MetadataFetchers; let plugins = availableTypeOptions.MetadataFetchers;
plugins = getOrderedPlugins(plugins, libraryOptionsForType.MetadataFetcherOrder || []); plugins = getOrderedPlugins(plugins, libraryOptionsForType.MetadataFetcherOrder || []);
if (!plugins.length) return html; if (!plugins.length) return html;
@ -112,8 +122,8 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
plugins.forEach((plugin, index) => { plugins.forEach((plugin, index) => {
html += '<div class="listItem metadataFetcherItem sortableOption" data-pluginname="' + plugin.Name + '">'; html += '<div class="listItem metadataFetcherItem sortableOption" data-pluginname="' + plugin.Name + '">';
var isChecked = libraryOptionsForType.MetadataFetchers ? -1 !== libraryOptionsForType.MetadataFetchers.indexOf(plugin.Name) : plugin.DefaultEnabled; const isChecked = libraryOptionsForType.MetadataFetchers ? libraryOptionsForType.MetadataFetchers.includes(plugin.Name) : plugin.DefaultEnabled;
var checkedHtml = isChecked ? ' checked="checked"' : ''; const checkedHtml = isChecked ? ' checked="checked"' : '';
html += '<label class="listItemCheckboxContainer"><input type="checkbox" is="emby-checkbox" class="chkMetadataFetcher" data-pluginname="' + plugin.Name + '" ' + checkedHtml + '><span></span></label>'; html += '<label class="listItemCheckboxContainer"><input type="checkbox" is="emby-checkbox" class="chkMetadataFetcher" data-pluginname="' + plugin.Name + '" ' + checkedHtml + '><span></span></label>';
html += '<div class="listItemBody">'; html += '<div class="listItemBody">';
html += '<h3 class="listItemBodyText">'; html += '<h3 class="listItemBodyText">';
@ -121,9 +131,9 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
html += '</h3>'; html += '</h3>';
html += '</div>'; html += '</div>';
if (index > 0) { if (index > 0) {
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('ButtonUp') + '" class="btnSortableMoveUp btnSortable" data-pluginindex="' + index + '"><span class="material-icons keyboard_arrow_up"></span></button>'; html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('Up') + '" class="btnSortableMoveUp btnSortable" data-pluginindex="' + index + '"><span class="material-icons keyboard_arrow_up"></span></button>';
} else if (plugins.length > 1) { } else if (plugins.length > 1) {
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('ButtonDown') + '" class="btnSortableMoveDown btnSortable" data-pluginindex="' + index + '"><span class="material-icons keyboard_arrow_down"></span></button>'; html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('Down') + '" class="btnSortableMoveDown btnSortable" data-pluginindex="' + index + '"><span class="material-icons keyboard_arrow_down"></span></button>';
} }
html += '</div>'; html += '</div>';
}); });
@ -135,19 +145,19 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
} }
function getTypeOptions(allOptions, type) { function getTypeOptions(allOptions, type) {
var allTypeOptions = allOptions.TypeOptions || []; const allTypeOptions = allOptions.TypeOptions || [];
for (var i = 0; i < allTypeOptions.length; i++) { for (let i = 0; i < allTypeOptions.length; i++) {
var typeOptions = allTypeOptions[i]; const typeOptions = allTypeOptions[i];
if (typeOptions.Type === type) return typeOptions; if (typeOptions.Type === type) return typeOptions;
} }
return null; return null;
} }
function renderMetadataFetchers(page, availableOptions, libraryOptions) { function renderMetadataFetchers(page, availableOptions, libraryOptions) {
var html = ''; let html = '';
var elem = page.querySelector('.metadataFetchers'); const elem = page.querySelector('.metadataFetchers');
for (var i = 0; i < availableOptions.TypeOptions.length; i++) { for (let i = 0; i < availableOptions.TypeOptions.length; i++) {
var availableTypeOptions = availableOptions.TypeOptions[i]; const availableTypeOptions = availableOptions.TypeOptions[i];
html += getMetadataFetchersForTypeHtml(availableTypeOptions, getTypeOptions(libraryOptions, availableTypeOptions.Type) || {}); html += getMetadataFetchersForTypeHtml(availableTypeOptions, getTypeOptions(libraryOptions, availableTypeOptions.Type) || {});
} }
elem.innerHTML = html; elem.innerHTML = html;
@ -166,41 +176,41 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
} }
function renderSubtitleFetchers(page, availableOptions, libraryOptions) { function renderSubtitleFetchers(page, availableOptions, libraryOptions) {
var html = ''; let html = '';
var elem = page.querySelector('.subtitleFetchers'); const elem = page.querySelector('.subtitleFetchers');
var plugins = availableOptions.SubtitleFetchers; let plugins = availableOptions.SubtitleFetchers;
plugins = getOrderedPlugins(plugins, libraryOptions.SubtitleFetcherOrder || []); plugins = getOrderedPlugins(plugins, libraryOptions.SubtitleFetcherOrder || []);
if (!plugins.length) return html; if (!plugins.length) return html;
html += '<h3 class="checkboxListLabel">' + globalize.translate('LabelSubtitleDownloaders') + '</h3>'; html += `<h3 class="checkboxListLabel">${globalize.translate('LabelSubtitleDownloaders')}</h3>`;
html += '<div class="checkboxList paperList checkboxList-paperList">'; html += '<div class="checkboxList paperList checkboxList-paperList">';
for (var i = 0; i < plugins.length; i++) { for (let i = 0; i < plugins.length; i++) {
var plugin = plugins[i]; const plugin = plugins[i];
html += '<div class="listItem subtitleFetcherItem sortableOption" data-pluginname="' + plugin.Name + '">'; html += `<div class="listItem subtitleFetcherItem sortableOption" data-pluginname="${plugin.Name}">`;
var isChecked = libraryOptions.DisabledSubtitleFetchers ? -1 === libraryOptions.DisabledSubtitleFetchers.indexOf(plugin.Name) : plugin.DefaultEnabled; const isChecked = libraryOptions.DisabledSubtitleFetchers ? !libraryOptions.DisabledSubtitleFetchers.includes(plugin.Name) : plugin.DefaultEnabled;
var checkedHtml = isChecked ? ' checked="checked"' : ''; const checkedHtml = isChecked ? ' checked="checked"' : '';
html += '<label class="listItemCheckboxContainer"><input type="checkbox" is="emby-checkbox" class="chkSubtitleFetcher" data-pluginname="' + plugin.Name + '" ' + checkedHtml + '><span></span></label>'; html += `<label class="listItemCheckboxContainer"><input type="checkbox" is="emby-checkbox" class="chkSubtitleFetcher" data-pluginname="${plugin.Name}" ${checkedHtml}><span></span></label>`;
html += '<div class="listItemBody">'; html += '<div class="listItemBody">';
html += '<h3 class="listItemBodyText">'; html += '<h3 class="listItemBodyText">';
html += plugin.Name; html += plugin.Name;
html += '</h3>'; html += '</h3>';
html += '</div>'; html += '</div>';
if (i > 0) { if (i > 0) {
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('ButtonUp') + '" class="btnSortableMoveUp btnSortable" data-pluginindex="' + i + '"><span class="material-icons keyboard_arrow_up"></span></button>'; html += `<button type="button" is="paper-icon-button-light" title="${globalize.translate('Up')}" class="btnSortableMoveUp btnSortable" data-pluginindex="${i}"><span class="material-icons keyboard_arrow_up"></span></button>`;
} else if (plugins.length > 1) { } else if (plugins.length > 1) {
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('ButtonDown') + '" class="btnSortableMoveDown btnSortable" data-pluginindex="' + i + '"><span class="material-icons keyboard_arrow_down"></span></button>'; html += `<button type="button" is="paper-icon-button-light" title="${globalize.translate('Down')}" class="btnSortableMoveDown btnSortable" data-pluginindex="${i}"><span class="material-icons keyboard_arrow_down"></span></button>`;
} }
html += '</div>'; html += '</div>';
} }
html += '</div>'; html += '</div>';
html += '<div class="fieldDescription">' + globalize.translate('SubtitleDownloadersHelp') + '</div>'; html += `<div class="fieldDescription">${globalize.translate('SubtitleDownloadersHelp')}</div>`;
elem.innerHTML = html; elem.innerHTML = html;
} }
function getImageFetchersForTypeHtml(availableTypeOptions, libraryOptionsForType) { function getImageFetchersForTypeHtml(availableTypeOptions, libraryOptionsForType) {
var html = ''; let html = '';
var plugins = availableTypeOptions.ImageFetchers; let plugins = availableTypeOptions.ImageFetchers;
plugins = getOrderedPlugins(plugins, libraryOptionsForType.ImageFetcherOrder || []); plugins = getOrderedPlugins(plugins, libraryOptionsForType.ImageFetcherOrder || []);
if (!plugins.length) return html; if (!plugins.length) return html;
@ -208,17 +218,17 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
html += '<div class="imageFetcher" data-type="' + availableTypeOptions.Type + '">'; html += '<div class="imageFetcher" data-type="' + availableTypeOptions.Type + '">';
html += '<div class="flex align-items-center" style="margin:1.5em 0 .5em;">'; html += '<div class="flex align-items-center" style="margin:1.5em 0 .5em;">';
html += '<h3 class="checkboxListLabel" style="margin:0;">' + globalize.translate('HeaderTypeImageFetchers', availableTypeOptions.Type) + '</h3>'; html += '<h3 class="checkboxListLabel" style="margin:0;">' + globalize.translate('HeaderTypeImageFetchers', availableTypeOptions.Type) + '</h3>';
var supportedImageTypes = availableTypeOptions.SupportedImageTypes || []; const supportedImageTypes = availableTypeOptions.SupportedImageTypes || [];
if (supportedImageTypes.length > 1 || 1 === supportedImageTypes.length && 'Primary' !== supportedImageTypes[0]) { if (supportedImageTypes.length > 1 || supportedImageTypes.length === 1 && supportedImageTypes[0] !== 'Primary') {
html += '<button is="emby-button" class="raised btnImageOptionsForType" type="button" style="margin-left:1.5em;font-size:90%;"><span>' + globalize.translate('HeaderFetcherSettings') + '</span></button>'; html += '<button is="emby-button" class="raised btnImageOptionsForType" type="button" style="margin-left:1.5em;font-size:90%;"><span>' + globalize.translate('HeaderFetcherSettings') + '</span></button>';
} }
html += '</div>'; html += '</div>';
html += '<div class="checkboxList paperList checkboxList-paperList">'; html += '<div class="checkboxList paperList checkboxList-paperList">';
for (var i = 0; i < plugins.length; i++) { for (let i = 0; i < plugins.length; i++) {
var plugin = plugins[i]; const plugin = plugins[i];
html += '<div class="listItem imageFetcherItem sortableOption" data-pluginname="' + plugin.Name + '">'; html += '<div class="listItem imageFetcherItem sortableOption" data-pluginname="' + plugin.Name + '">';
var isChecked = libraryOptionsForType.ImageFetchers ? -1 !== libraryOptionsForType.ImageFetchers.indexOf(plugin.Name) : plugin.DefaultEnabled; const isChecked = libraryOptionsForType.ImageFetchers ? libraryOptionsForType.ImageFetchers.includes(plugin.Name) : plugin.DefaultEnabled;
var checkedHtml = isChecked ? ' checked="checked"' : ''; const checkedHtml = isChecked ? ' checked="checked"' : '';
html += '<label class="listItemCheckboxContainer"><input type="checkbox" is="emby-checkbox" class="chkImageFetcher" data-pluginname="' + plugin.Name + '" ' + checkedHtml + '><span></span></label>'; html += '<label class="listItemCheckboxContainer"><input type="checkbox" is="emby-checkbox" class="chkImageFetcher" data-pluginname="' + plugin.Name + '" ' + checkedHtml + '><span></span></label>';
html += '<div class="listItemBody">'; html += '<div class="listItemBody">';
html += '<h3 class="listItemBodyText">'; html += '<h3 class="listItemBodyText">';
@ -226,9 +236,9 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
html += '</h3>'; html += '</h3>';
html += '</div>'; html += '</div>';
if (i > 0) { if (i > 0) {
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('ButtonUp') + '" class="btnSortableMoveUp btnSortable" data-pluginindex="' + i + '"><span class="material-icons keyboard_arrow_up"></span></button>'; html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('Up') + '" class="btnSortableMoveUp btnSortable" data-pluginindex="' + i + '"><span class="material-icons keyboard_arrow_up"></span></button>';
} else if (plugins.length > 1) { } else if (plugins.length > 1) {
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('ButtonDown') + '" class="btnSortableMoveDown btnSortable" data-pluginindex="' + i + '"><span class="material-icons keyboard_arrow_down"></span></button>'; html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('Down') + '" class="btnSortableMoveDown btnSortable" data-pluginindex="' + i + '"><span class="material-icons keyboard_arrow_down"></span></button>';
} }
html += '</div>'; html += '</div>';
} }
@ -239,10 +249,10 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
} }
function renderImageFetchers(page, availableOptions, libraryOptions) { function renderImageFetchers(page, availableOptions, libraryOptions) {
var html = ''; let html = '';
var elem = page.querySelector('.imageFetchers'); const elem = page.querySelector('.imageFetchers');
for (var i = 0; i < availableOptions.TypeOptions.length; i++) { for (let i = 0; i < availableOptions.TypeOptions.length; i++) {
var availableTypeOptions = availableOptions.TypeOptions[i]; const availableTypeOptions = availableOptions.TypeOptions[i];
html += getImageFetchersForTypeHtml(availableTypeOptions, getTypeOptions(libraryOptions, availableTypeOptions.Type) || {}); html += getImageFetchersForTypeHtml(availableTypeOptions, getTypeOptions(libraryOptions, availableTypeOptions.Type) || {});
} }
elem.innerHTML = html; elem.innerHTML = html;
@ -258,12 +268,12 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
return true; return true;
} }
function populateMetadataSettings(parent, contentType, isNewLibrary) { function populateMetadataSettings(parent, contentType) {
var isNewLibrary = parent.classList.contains('newlibrary'); const isNewLibrary = parent.classList.contains('newlibrary');
return ApiClient.getJSON(ApiClient.getUrl('Libraries/AvailableOptions', { return ApiClient.getJSON(ApiClient.getUrl('Libraries/AvailableOptions', {
LibraryContentType: contentType, LibraryContentType: contentType,
IsNewLibrary: isNewLibrary IsNewLibrary: isNewLibrary
})).then(function(availableOptions) { })).then(availableOptions => {
currentAvailableOptions = availableOptions; currentAvailableOptions = availableOptions;
parent.availableOptions = availableOptions; parent.availableOptions = availableOptions;
renderMetadataSavers(parent, availableOptions.MetadataSavers); renderMetadataSavers(parent, availableOptions.MetadataSavers);
@ -272,22 +282,22 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
renderSubtitleFetchers(parent, availableOptions, {}); renderSubtitleFetchers(parent, availableOptions, {});
renderImageFetchers(parent, availableOptions, {}); renderImageFetchers(parent, availableOptions, {});
availableOptions.SubtitleFetchers.length ? parent.querySelector('.subtitleDownloadSettings').classList.remove('hide') : parent.querySelector('.subtitleDownloadSettings').classList.add('hide'); availableOptions.SubtitleFetchers.length ? parent.querySelector('.subtitleDownloadSettings').classList.remove('hide') : parent.querySelector('.subtitleDownloadSettings').classList.add('hide');
}).catch(function() { }).catch(() => {
return Promise.resolve(); return Promise.resolve();
}); });
} }
function adjustSortableListElement(elem) { function adjustSortableListElement(elem) {
var btnSortable = elem.querySelector('.btnSortable'); const btnSortable = elem.querySelector('.btnSortable');
var inner = btnSortable.querySelector('.material-icons'); const inner = btnSortable.querySelector('.material-icons');
if (elem.previousSibling) { if (elem.previousSibling) {
btnSortable.title = globalize.translate('ButtonUp'); btnSortable.title = globalize.translate('Up');
btnSortable.classList.add('btnSortableMoveUp'); btnSortable.classList.add('btnSortableMoveUp');
btnSortable.classList.remove('btnSortableMoveDown'); btnSortable.classList.remove('btnSortableMoveDown');
inner.classList.remove('keyboard_arrow_down'); inner.classList.remove('keyboard_arrow_down');
inner.classList.add('keyboard_arrow_up'); inner.classList.add('keyboard_arrow_up');
} else { } else {
btnSortable.title = globalize.translate('ButtonDown'); btnSortable.title = globalize.translate('Down');
btnSortable.classList.remove('btnSortableMoveUp'); btnSortable.classList.remove('btnSortableMoveUp');
btnSortable.classList.add('btnSortableMoveDown'); btnSortable.classList.add('btnSortableMoveDown');
inner.classList.remove('keyboard_arrow_up'); inner.classList.remove('keyboard_arrow_up');
@ -296,22 +306,22 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
} }
function showImageOptionsForType(type) { function showImageOptionsForType(type) {
require(['imageoptionseditor'], function(ImageOptionsEditor) { import('imageoptionseditor').then(({default: ImageOptionsEditor}) => {
var typeOptions = getTypeOptions(currentLibraryOptions, type); let typeOptions = getTypeOptions(currentLibraryOptions, type);
if (!typeOptions) { if (!typeOptions) {
typeOptions = { typeOptions = {
Type: type Type: type
}; };
currentLibraryOptions.TypeOptions.push(typeOptions); currentLibraryOptions.TypeOptions.push(typeOptions);
} }
var availableOptions = getTypeOptions(currentAvailableOptions || {}, type); const availableOptions = getTypeOptions(currentAvailableOptions || {}, type);
var imageOptionsEditor = new ImageOptionsEditor(); const imageOptionsEditor = new ImageOptionsEditor();
imageOptionsEditor.show(type, typeOptions, availableOptions); imageOptionsEditor.show(type, typeOptions, availableOptions);
}); });
} }
function onImageFetchersContainerClick(e) { function onImageFetchersContainerClick(e) {
var btnImageOptionsForType = dom.parentWithClass(e.target, 'btnImageOptionsForType'); const btnImageOptionsForType = dom.parentWithClass(e.target, 'btnImageOptionsForType');
if (btnImageOptionsForType) { if (btnImageOptionsForType) {
return void showImageOptionsForType(dom.parentWithClass(btnImageOptionsForType, 'imageFetcher').getAttribute('data-type')); return void showImageOptionsForType(dom.parentWithClass(btnImageOptionsForType, 'imageFetcher').getAttribute('data-type'));
} }
@ -319,18 +329,18 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
} }
function onSortableContainerClick(e) { function onSortableContainerClick(e) {
var btnSortable = dom.parentWithClass(e.target, 'btnSortable'); const btnSortable = dom.parentWithClass(e.target, 'btnSortable');
if (btnSortable) { if (btnSortable) {
var li = dom.parentWithClass(btnSortable, 'sortableOption'); const li = dom.parentWithClass(btnSortable, 'sortableOption');
var list = dom.parentWithClass(li, 'paperList'); const list = dom.parentWithClass(li, 'paperList');
if (btnSortable.classList.contains('btnSortableMoveDown')) { if (btnSortable.classList.contains('btnSortableMoveDown')) {
var next = li.nextSibling; const next = li.nextSibling;
if (next) { if (next) {
li.parentNode.removeChild(li); li.parentNode.removeChild(li);
next.parentNode.insertBefore(li, next.nextSibling); next.parentNode.insertBefore(li, next.nextSibling);
} }
} else { } else {
var prev = li.previousSibling; const prev = li.previousSibling;
if (prev) { if (prev) {
li.parentNode.removeChild(li); li.parentNode.removeChild(li);
prev.parentNode.insertBefore(li, prev); prev.parentNode.insertBefore(li, prev);
@ -347,41 +357,35 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
parent.querySelector('.imageFetchers').addEventListener('click', onImageFetchersContainerClick); parent.querySelector('.imageFetchers').addEventListener('click', onImageFetchersContainerClick);
} }
function embed(parent, contentType, libraryOptions) { export async function embed(parent, contentType, libraryOptions) {
currentLibraryOptions = { currentLibraryOptions = {
TypeOptions: [] TypeOptions: []
}; };
currentAvailableOptions = null; currentAvailableOptions = null;
var isNewLibrary = null === libraryOptions; const isNewLibrary = libraryOptions === null;
isNewLibrary && parent.classList.add('newlibrary'); isNewLibrary && parent.classList.add('newlibrary');
return new Promise(function(resolve, reject) { const response = await fetch('components/libraryoptionseditor/libraryoptionseditor.template.html');
var xhr = new XMLHttpRequest; const template = await response.text();
xhr.open('GET', 'components/libraryoptionseditor/libraryoptionseditor.template.html', true); parent.innerHTML = globalize.translateHtml(template);
xhr.onload = function(e) {
var template = this.response;
parent.innerHTML = globalize.translateDocument(template);
populateRefreshInterval(parent.querySelector('#selectAutoRefreshInterval')); populateRefreshInterval(parent.querySelector('#selectAutoRefreshInterval'));
var promises = [populateLanguages(parent), populateCountries(parent.querySelector('#selectCountry'))]; const promises = [populateLanguages(parent), populateCountries(parent.querySelector('#selectCountry'))];
Promise.all(promises).then(function() { Promise.all(promises).then(function() {
return setContentType(parent, contentType).then(function() { return setContentType(parent, contentType).then(function() {
libraryOptions && setLibraryOptions(parent, libraryOptions); libraryOptions && setLibraryOptions(parent, libraryOptions);
bindEvents(parent); bindEvents(parent);
resolve(); return;
}); });
}); });
};
xhr.send();
});
} }
function setAdvancedVisible(parent, visible) { export function setAdvancedVisible(parent, visible) {
var elems = parent.querySelectorAll('.advanced'); const elems = parent.querySelectorAll('.advanced');
for (var i = 0; i < elems.length; i++) { for (let i = 0; i < elems.length; i++) {
visible ? elems[i].classList.remove('advancedHide') : elems[i].classList.add('advancedHide'); visible ? elems[i].classList.remove('advancedHide') : elems[i].classList.add('advancedHide');
} }
} }
function setContentType(parent, contentType) { export function setContentType(parent, contentType) {
if (contentType === 'homevideos' || contentType === 'photos') { if (contentType === 'homevideos' || contentType === 'photos') {
parent.querySelector('.chkEnablePhotosContainer').classList.remove('hide'); parent.querySelector('.chkEnablePhotosContainer').classList.remove('hide');
} else { } else {
@ -422,47 +426,47 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
} }
function setSubtitleFetchersIntoOptions(parent, options) { function setSubtitleFetchersIntoOptions(parent, options) {
options.DisabledSubtitleFetchers = Array.prototype.map.call(Array.prototype.filter.call(parent.querySelectorAll('.chkSubtitleFetcher'), function(elem) { options.DisabledSubtitleFetchers = Array.prototype.map.call(Array.prototype.filter.call(parent.querySelectorAll('.chkSubtitleFetcher'), elem => {
return !elem.checked; return !elem.checked;
}), function(elem) { }), elem => {
return elem.getAttribute('data-pluginname'); return elem.getAttribute('data-pluginname');
}); });
options.SubtitleFetcherOrder = Array.prototype.map.call(parent.querySelectorAll('.subtitleFetcherItem'), function(elem) { options.SubtitleFetcherOrder = Array.prototype.map.call(parent.querySelectorAll('.subtitleFetcherItem'), elem => {
return elem.getAttribute('data-pluginname'); return elem.getAttribute('data-pluginname');
}); });
} }
function setMetadataFetchersIntoOptions(parent, options) { function setMetadataFetchersIntoOptions(parent, options) {
var sections = parent.querySelectorAll('.metadataFetcher'); const sections = parent.querySelectorAll('.metadataFetcher');
for (var i = 0; i < sections.length; i++) { for (let i = 0; i < sections.length; i++) {
var section = sections[i]; const section = sections[i];
var type = section.getAttribute('data-type'); const type = section.getAttribute('data-type');
var typeOptions = getTypeOptions(options, type); let typeOptions = getTypeOptions(options, type);
if (!typeOptions) { if (!typeOptions) {
typeOptions = { typeOptions = {
Type: type Type: type
}; };
options.TypeOptions.push(typeOptions); options.TypeOptions.push(typeOptions);
} }
typeOptions.MetadataFetchers = Array.prototype.map.call(Array.prototype.filter.call(section.querySelectorAll('.chkMetadataFetcher'), function(elem) { typeOptions.MetadataFetchers = Array.prototype.map.call(Array.prototype.filter.call(section.querySelectorAll('.chkMetadataFetcher'), elem => {
return elem.checked; return elem.checked;
}), function(elem) { }), elem => {
return elem.getAttribute('data-pluginname'); return elem.getAttribute('data-pluginname');
}); });
typeOptions.MetadataFetcherOrder = Array.prototype.map.call(section.querySelectorAll('.metadataFetcherItem'), function(elem) { typeOptions.MetadataFetcherOrder = Array.prototype.map.call(section.querySelectorAll('.metadataFetcherItem'), elem => {
return elem.getAttribute('data-pluginname'); return elem.getAttribute('data-pluginname');
}); });
} }
} }
function setImageFetchersIntoOptions(parent, options) { function setImageFetchersIntoOptions(parent, options) {
var sections = parent.querySelectorAll('.imageFetcher'); const sections = parent.querySelectorAll('.imageFetcher');
for (var i = 0; i < sections.length; i++) { for (let i = 0; i < sections.length; i++) {
var section = sections[i]; const section = sections[i];
var type = section.getAttribute('data-type'); const type = section.getAttribute('data-type');
var typeOptions = getTypeOptions(options, type); let typeOptions = getTypeOptions(options, type);
if (!typeOptions) { if (!typeOptions) {
typeOptions = { typeOptions = {
Type: type Type: type
@ -470,23 +474,23 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
options.TypeOptions.push(typeOptions); options.TypeOptions.push(typeOptions);
} }
typeOptions.ImageFetchers = Array.prototype.map.call(Array.prototype.filter.call(section.querySelectorAll('.chkImageFetcher'), function(elem) { typeOptions.ImageFetchers = Array.prototype.map.call(Array.prototype.filter.call(section.querySelectorAll('.chkImageFetcher'), elem => {
return elem.checked; return elem.checked;
}), function(elem) { }), elem => {
return elem.getAttribute('data-pluginname'); return elem.getAttribute('data-pluginname');
}); });
typeOptions.ImageFetcherOrder = Array.prototype.map.call(section.querySelectorAll('.imageFetcherItem'), function(elem) { typeOptions.ImageFetcherOrder = Array.prototype.map.call(section.querySelectorAll('.imageFetcherItem'), elem => {
return elem.getAttribute('data-pluginname'); return elem.getAttribute('data-pluginname');
}); });
} }
} }
function setImageOptionsIntoOptions(parent, options) { function setImageOptionsIntoOptions(options) {
var originalTypeOptions = (currentLibraryOptions || {}).TypeOptions || []; const originalTypeOptions = (currentLibraryOptions || {}).TypeOptions || [];
for (var i = 0; i < originalTypeOptions.length; i++) { for (let i = 0; i < originalTypeOptions.length; i++) {
var originalTypeOption = originalTypeOptions[i]; const originalTypeOption = originalTypeOptions[i];
var typeOptions = getTypeOptions(options, originalTypeOption.Type); let typeOptions = getTypeOptions(options, originalTypeOption.Type);
if (!typeOptions) { if (!typeOptions) {
typeOptions = { typeOptions = {
@ -498,8 +502,8 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
} }
} }
function getLibraryOptions(parent) { export function getLibraryOptions(parent) {
var options = { const options = {
EnableArchiveMediaFiles: false, EnableArchiveMediaFiles: false,
EnablePhotos: parent.querySelector('.chkEnablePhotos').checked, EnablePhotos: parent.querySelector('.chkEnablePhotos').checked,
EnableRealtimeMonitor: parent.querySelector('.chkEnableRealtimeMonitor').checked, EnableRealtimeMonitor: parent.querySelector('.chkEnableRealtimeMonitor').checked,
@ -520,39 +524,39 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
SkipSubtitlesIfAudioTrackMatches: parent.querySelector('#chkSkipIfAudioTrackPresent').checked, SkipSubtitlesIfAudioTrackMatches: parent.querySelector('#chkSkipIfAudioTrackPresent').checked,
SaveSubtitlesWithMedia: parent.querySelector('#chkSaveSubtitlesLocally').checked, SaveSubtitlesWithMedia: parent.querySelector('#chkSaveSubtitlesLocally').checked,
RequirePerfectSubtitleMatch: parent.querySelector('#chkRequirePerfectMatch').checked, RequirePerfectSubtitleMatch: parent.querySelector('#chkRequirePerfectMatch').checked,
MetadataSavers: Array.prototype.map.call(Array.prototype.filter.call(parent.querySelectorAll('.chkMetadataSaver'), function(elem) { MetadataSavers: Array.prototype.map.call(Array.prototype.filter.call(parent.querySelectorAll('.chkMetadataSaver'), elem => {
return elem.checked; return elem.checked;
}), function(elem) { }), elem => {
return elem.getAttribute('data-pluginname'); return elem.getAttribute('data-pluginname');
}), }),
TypeOptions: [] TypeOptions: []
}; };
options.LocalMetadataReaderOrder = Array.prototype.map.call(parent.querySelectorAll('.localReaderOption'), function(elem) { options.LocalMetadataReaderOrder = Array.prototype.map.call(parent.querySelectorAll('.localReaderOption'), elem => {
return elem.getAttribute('data-pluginname'); return elem.getAttribute('data-pluginname');
}); });
options.SubtitleDownloadLanguages = Array.prototype.map.call(Array.prototype.filter.call(parent.querySelectorAll('.chkSubtitleLanguage'), function(elem) { options.SubtitleDownloadLanguages = Array.prototype.map.call(Array.prototype.filter.call(parent.querySelectorAll('.chkSubtitleLanguage'), elem => {
return elem.checked; return elem.checked;
}), function(elem) { }), elem => {
return elem.getAttribute('data-lang'); return elem.getAttribute('data-lang');
}); });
setSubtitleFetchersIntoOptions(parent, options); setSubtitleFetchersIntoOptions(parent, options);
setMetadataFetchersIntoOptions(parent, options); setMetadataFetchersIntoOptions(parent, options);
setImageFetchersIntoOptions(parent, options); setImageFetchersIntoOptions(parent, options);
setImageOptionsIntoOptions(parent, options); setImageOptionsIntoOptions(options);
return options; return options;
} }
function getOrderedPlugins(plugins, configuredOrder) { function getOrderedPlugins(plugins, configuredOrder) {
plugins = plugins.slice(0); plugins = plugins.slice(0);
plugins.sort(function(a, b) { plugins.sort((a, b) => {
return a = configuredOrder.indexOf(a.Name), b = configuredOrder.indexOf(b.Name), a < b ? -1 : a > b ? 1 : 0; return a = configuredOrder.indexOf(a.Name), b = configuredOrder.indexOf(b.Name), a < b ? -1 : a > b ? 1 : 0;
}); });
return plugins; return plugins;
} }
function setLibraryOptions(parent, options) { export function setLibraryOptions(parent, options) {
currentLibraryOptions = options; currentLibraryOptions = options;
currentAvailableOptions = parent.availableOptions; currentAvailableOptions = parent.availableOptions;
parent.querySelector('#selectLanguage').value = options.PreferredMetadataLanguage || ''; parent.querySelector('#selectLanguage').value = options.PreferredMetadataLanguage || '';
@ -573,11 +577,11 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
parent.querySelector('#chkSaveSubtitlesLocally').checked = options.SaveSubtitlesWithMedia; parent.querySelector('#chkSaveSubtitlesLocally').checked = options.SaveSubtitlesWithMedia;
parent.querySelector('#chkSkipIfAudioTrackPresent').checked = options.SkipSubtitlesIfAudioTrackMatches; parent.querySelector('#chkSkipIfAudioTrackPresent').checked = options.SkipSubtitlesIfAudioTrackMatches;
parent.querySelector('#chkRequirePerfectMatch').checked = options.RequirePerfectSubtitleMatch; parent.querySelector('#chkRequirePerfectMatch').checked = options.RequirePerfectSubtitleMatch;
Array.prototype.forEach.call(parent.querySelectorAll('.chkMetadataSaver'), function(elem) { Array.prototype.forEach.call(parent.querySelectorAll('.chkMetadataSaver'), elem => {
elem.checked = options.MetadataSavers ? -1 !== options.MetadataSavers.indexOf(elem.getAttribute('data-pluginname')) : 'true' === elem.getAttribute('data-defaultenabled'); elem.checked = options.MetadataSavers ? options.MetadataSavers.includes(elem.getAttribute('data-pluginname')) : elem.getAttribute('data-defaultenabled') === 'true';
}); });
Array.prototype.forEach.call(parent.querySelectorAll('.chkSubtitleLanguage'), function(elem) { Array.prototype.forEach.call(parent.querySelectorAll('.chkSubtitleLanguage'), elem => {
elem.checked = !!options.SubtitleDownloadLanguages && -1 !== options.SubtitleDownloadLanguages.indexOf(elem.getAttribute('data-lang')); elem.checked = !!options.SubtitleDownloadLanguages && options.SubtitleDownloadLanguages.includes(elem.getAttribute('data-lang'));
}); });
renderMetadataReaders(parent, getOrderedPlugins(parent.availableOptions.MetadataReaders, options.LocalMetadataReaderOrder || [])); renderMetadataReaders(parent, getOrderedPlugins(parent.availableOptions.MetadataReaders, options.LocalMetadataReaderOrder || []));
renderMetadataFetchers(parent, parent.availableOptions, options); renderMetadataFetchers(parent, parent.availableOptions, options);
@ -585,14 +589,14 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
renderSubtitleFetchers(parent, parent.availableOptions, options); renderSubtitleFetchers(parent, parent.availableOptions, options);
} }
var currentLibraryOptions; let currentLibraryOptions;
var currentAvailableOptions; let currentAvailableOptions;
return { /* eslint-enable indent */
export default {
embed: embed, embed: embed,
setContentType: setContentType, setContentType: setContentType,
getLibraryOptions: getLibraryOptions, getLibraryOptions: getLibraryOptions,
setLibraryOptions: setLibraryOptions, setLibraryOptions: setLibraryOptions,
setAdvancedVisible: setAdvancedVisible setAdvancedVisible: setAdvancedVisible
}; };
});

View file

@ -88,7 +88,7 @@
<div class="checkboxContainer checkboxContainer-withDescription hide chkImportMissingEpisodesContainer advanced"> <div class="checkboxContainer checkboxContainer-withDescription hide chkImportMissingEpisodesContainer advanced">
<label> <label>
<input is="emby-checkbox" type="checkbox" id="chkImportMissingEpisodes" /> <input is="emby-checkbox" type="checkbox" id="chkImportMissingEpisodes" />
<span>${LabelDisplayMissingEpisodesWithinSeasons}</span> <span>${DisplayMissingEpisodesWithinSeasons}</span>
</label> </label>
<div class="fieldDescription checkboxFieldDescription">${ImportMissingEpisodesHelp}</div> <div class="fieldDescription checkboxFieldDescription">${ImportMissingEpisodesHelp}</div>
</div> </div>

View file

@ -185,6 +185,17 @@
.listItemBody { .listItemBody {
padding-right: 0.5em; padding-right: 0.5em;
} }
.listItemMediaInfo {
display: none;
}
}
@media all and (max-width: 40em) {
[data-type='Movie'] .listItemImage,
[data-type='Series'] .listItemImage {
display: none;
}
} }
.listItemImage-large-tv { .listItemImage-large-tv {

View file

@ -1,19 +1,31 @@
define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutManager', 'globalize', 'datetime', 'apphost', 'css!./listview', 'emby-ratingbutton', 'emby-playstatebutton'], function (itemHelper, mediaInfo, indicators, connectionManager, layoutManager, globalize, datetime, appHost) { /* eslint-disable indent */
'use strict';
/**
* Module for display list view.
* @module components/listview/listview
*/
import itemHelper from 'itemHelper';
import mediaInfo from 'mediaInfo';
import indicators from 'indicators';
import layoutManager from 'layoutManager';
import globalize from 'globalize';
import datetime from 'datetime';
import cardBuilder from 'cardBuilder';
import 'css!./listview';
import 'emby-ratingbutton';
import 'emby-playstatebutton';
function getIndex(item, options) { function getIndex(item, options) {
if (options.index === 'disc') { if (options.index === 'disc') {
return item.ParentIndexNumber == null ? '' : globalize.translate('ValueDiscNumber', item.ParentIndexNumber); return item.ParentIndexNumber == null ? '' : globalize.translate('ValueDiscNumber', item.ParentIndexNumber);
} }
var sortBy = (options.sortBy || '').toLowerCase(); const sortBy = (options.sortBy || '').toLowerCase();
var code; let code;
var name; let name;
if (sortBy.indexOf('sortname') === 0) { if (sortBy.indexOf('sortname') === 0) {
if (item.Type === 'Episode') { if (item.Type === 'Episode') {
return ''; return '';
} }
@ -29,11 +41,9 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
return name.toUpperCase(); return name.toUpperCase();
} }
if (sortBy.indexOf('officialrating') === 0) { if (sortBy.indexOf('officialrating') === 0) {
return item.OfficialRating || globalize.translate('Unrated'); return item.OfficialRating || globalize.translate('Unrated');
} }
if (sortBy.indexOf('communityrating') === 0) { if (sortBy.indexOf('communityrating') === 0) {
if (item.CommunityRating == null) { if (item.CommunityRating == null) {
return globalize.translate('Unrated'); return globalize.translate('Unrated');
} }
@ -41,7 +51,6 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
return Math.floor(item.CommunityRating); return Math.floor(item.CommunityRating);
} }
if (sortBy.indexOf('criticrating') === 0) { if (sortBy.indexOf('criticrating') === 0) {
if (item.CriticRating == null) { if (item.CriticRating == null) {
return globalize.translate('Unrated'); return globalize.translate('Unrated');
} }
@ -49,7 +58,6 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
return Math.floor(item.CriticRating); return Math.floor(item.CriticRating);
} }
if (sortBy.indexOf('albumartist') === 0) { if (sortBy.indexOf('albumartist') === 0) {
// SortName // SortName
if (!item.AlbumArtist) { if (!item.AlbumArtist) {
return ''; return '';
@ -68,12 +76,11 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
} }
function getImageUrl(item, width) { function getImageUrl(item, width) {
const apiClient = window.connectionManager.getApiClient(item.ServerId);
var apiClient = connectionManager.getApiClient(item.ServerId);
let itemId; let itemId;
var options = { const options = {
maxWidth: width * 2, maxWidth: width,
type: 'Primary' type: 'Primary'
}; };
@ -91,39 +98,32 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
itemId = item.ParentPrimaryImageItemId; itemId = item.ParentPrimaryImageItemId;
} }
let blurHashes = item.ImageBlurHashes || {};
let blurhashstr = (blurHashes[options.type] || {})[options.tag];
if (itemId) { if (itemId) {
return { url: apiClient.getScaledImageUrl(itemId, options), blurhash: blurhashstr }; return apiClient.getScaledImageUrl(itemId, options);
} }
return null; return null;
} }
function getChannelImageUrl(item, width) { function getChannelImageUrl(item, width) {
const apiClient = window.connectionManager.getApiClient(item.ServerId);
var apiClient = connectionManager.getApiClient(item.ServerId); const options = {
var options = { maxWidth: width,
maxWidth: width * 2,
type: 'Primary' type: 'Primary'
}; };
if (item.ChannelId && item.ChannelPrimaryImageTag) { if (item.ChannelId && item.ChannelPrimaryImageTag) {
options.tag = item.ChannelPrimaryImageTag; options.tag = item.ChannelPrimaryImageTag;
} }
let blurHashes = item.ImageBlurHashes || {};
let blurhashstr = (blurHashes[options.type])[options.tag];
if (item.ChannelId) { if (item.ChannelId) {
return { url: apiClient.getScaledImageUrl(item.ChannelId, options), blurhash: blurhashstr }; return apiClient.getScaledImageUrl(item.ChannelId, options);
} }
} }
function getTextLinesHtml(textlines, isLargeStyle) { function getTextLinesHtml(textlines, isLargeStyle) {
let html = '';
var html = ''; const largeTitleTagName = layoutManager.tv ? 'h2' : 'div';
var largeTitleTagName = layoutManager.tv ? 'h2' : 'div';
for (const [i, text] of textlines.entries()) { for (const [i, text] of textlines.entries()) {
if (!text) { if (!text) {
@ -132,7 +132,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
if (i === 0) { if (i === 0) {
if (isLargeStyle) { if (isLargeStyle) {
html += '<' + largeTitleTagName + ' class="listItemBodyText">'; html += `<${largeTitleTagName} class="listItemBodyText">`;
} else { } else {
html += '<div class="listItemBodyText">'; html += '<div class="listItemBodyText">';
} }
@ -141,7 +141,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
} }
html += (textlines[i] || '&nbsp;'); html += (textlines[i] || '&nbsp;');
if (i === 0 && isLargeStyle) { if (i === 0 && isLargeStyle) {
html += '</' + largeTitleTagName + '>'; html += `</${largeTitleTagName}>`;
} else { } else {
html += '</div>'; html += '</div>';
} }
@ -151,14 +151,12 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
} }
function getRightButtonsHtml(options) { function getRightButtonsHtml(options) {
let html = '';
var html = ''; for (let i = 0, length = options.rightButtons.length; i < length; i++) {
const button = options.rightButtons[i];
for (var i = 0, length = options.rightButtons.length; i < length; i++) { html += `<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="custom" data-customaction="${button.id}" title="${button.title}"><span class="material-icons ${button.icon}"></span></button>`;
var button = options.rightButtons[i];
html += '<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="custom" data-customaction="' + button.id + '" title="' + button.title + '"><span class="material-icons ' + button.icon + '"></span></button>';
} }
return html; return html;
@ -168,37 +166,33 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
return item.Id; return item.Id;
} }
function getListViewHtml(options) { export function getListViewHtml(options) {
const items = options.items;
var items = options.items; let groupTitle = '';
const action = options.action || 'link';
var groupTitle = ''; const isLargeStyle = options.imageSize === 'large';
var action = options.action || 'link'; const enableOverview = options.enableOverview;
var isLargeStyle = options.imageSize === 'large'; const clickEntireItem = layoutManager.tv ? true : false;
var enableOverview = options.enableOverview; const outerTagName = clickEntireItem ? 'button' : 'div';
const enableSideMediaInfo = options.enableSideMediaInfo != null ? options.enableSideMediaInfo : true;
var clickEntireItem = layoutManager.tv ? true : false; let outerHtml = '';
var outerTagName = clickEntireItem ? 'button' : 'div';
var enableSideMediaInfo = options.enableSideMediaInfo != null ? options.enableSideMediaInfo : true;
var outerHtml = ''; const enableContentWrapper = options.enableOverview && !layoutManager.tv;
const containerAlbumArtistIds = (options.containerAlbumArtists || []).map(getId);
var enableContentWrapper = options.enableOverview && !layoutManager.tv; for (let i = 0, length = items.length; i < length; i++) {
var containerAlbumArtistIds = (options.containerAlbumArtists || []).map(getId); const item = items[i];
for (var i = 0, length = items.length; i < length; i++) { let html = '';
var item = items[i];
var html = '';
if (options.showIndex) { if (options.showIndex) {
const itemGroupTitle = getIndex(item, options);
var itemGroupTitle = getIndex(item, options);
if (itemGroupTitle !== groupTitle) { if (itemGroupTitle !== groupTitle) {
if (html) { if (html) {
html += '</div>'; html += '</div>';
} }
@ -217,7 +211,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
} }
} }
var cssClass = 'listItem'; let cssClass = 'listItem';
if (options.border || (options.highlight !== false && !layoutManager.tv)) { if (options.border || (options.highlight !== false && !layoutManager.tv)) {
cssClass += ' listItem-border'; cssClass += ' listItem-border';
@ -231,81 +225,70 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
cssClass += ' listItem-focusscale'; cssClass += ' listItem-focusscale';
} }
var downloadWidth = 80; let downloadWidth = 80;
if (isLargeStyle) { if (isLargeStyle) {
cssClass += ' listItem-largeImage'; cssClass += ' listItem-largeImage';
downloadWidth = 500; downloadWidth = 500;
} }
var playlistItemId = item.PlaylistItemId ? (' data-playlistitemid="' + item.PlaylistItemId + '"') : ''; const playlistItemId = item.PlaylistItemId ? (` data-playlistitemid="${item.PlaylistItemId}"`) : '';
var positionTicksData = item.UserData && item.UserData.PlaybackPositionTicks ? (' data-positionticks="' + item.UserData.PlaybackPositionTicks + '"') : ''; const positionTicksData = item.UserData && item.UserData.PlaybackPositionTicks ? (` data-positionticks="${item.UserData.PlaybackPositionTicks}"`) : '';
var collectionIdData = options.collectionId ? (' data-collectionid="' + options.collectionId + '"') : ''; const collectionIdData = options.collectionId ? (` data-collectionid="${options.collectionId}"`) : '';
var playlistIdData = options.playlistId ? (' data-playlistid="' + options.playlistId + '"') : ''; const playlistIdData = options.playlistId ? (` data-playlistid="${options.playlistId}"`) : '';
var mediaTypeData = item.MediaType ? (' data-mediatype="' + item.MediaType + '"') : ''; const mediaTypeData = item.MediaType ? (` data-mediatype="${item.MediaType}"`) : '';
var collectionTypeData = item.CollectionType ? (' data-collectiontype="' + item.CollectionType + '"') : ''; const collectionTypeData = item.CollectionType ? (` data-collectiontype="${item.CollectionType}"`) : '';
var channelIdData = item.ChannelId ? (' data-channelid="' + item.ChannelId + '"') : ''; const channelIdData = item.ChannelId ? (` data-channelid="${item.ChannelId}"`) : '';
if (enableContentWrapper) { if (enableContentWrapper) {
cssClass += ' listItem-withContentWrapper'; cssClass += ' listItem-withContentWrapper';
} }
html += '<' + outerTagName + ' class="' + cssClass + '"' + playlistItemId + ' data-action="' + action + '" data-isfolder="' + item.IsFolder + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-type="' + item.Type + '"' + mediaTypeData + collectionTypeData + channelIdData + positionTicksData + collectionIdData + playlistIdData + '>'; html += `<${outerTagName} class="${cssClass}"${playlistItemId} data-action="${action}" data-isfolder="${item.IsFolder}" data-id="${item.Id}" data-serverid="${item.ServerId}" data-type="${item.Type}"${mediaTypeData}${collectionTypeData}${channelIdData}${positionTicksData}${collectionIdData}${playlistIdData}>`;
if (enableContentWrapper) { if (enableContentWrapper) {
html += '<div class="listItem-content">'; html += '<div class="listItem-content">';
} }
if (!clickEntireItem && options.dragHandle) { if (!clickEntireItem && options.dragHandle) {
//html += '<button is="paper-icon-button-light" class="listViewDragHandle listItemButton"><span class="material-icons drag_handle"></span></button>';
// Firefox and Edge are not allowing the button to be draggable
html += '<span class="listViewDragHandle material-icons listItemIcon listItemIcon-transparent drag_handle"></span>'; html += '<span class="listViewDragHandle material-icons listItemIcon listItemIcon-transparent drag_handle"></span>';
} }
if (options.image !== false) { if (options.image !== false) {
let imgData = options.imageSource === 'channel' ? getChannelImageUrl(item, downloadWidth) : getImageUrl(item, downloadWidth); var imgUrl = options.imageSource === 'channel' ? getChannelImageUrl(item, downloadWidth) : getImageUrl(item, downloadWidth);
let imgUrl = imgData.url; var imageClass = isLargeStyle ? 'listItemImage listItemImage-large' : 'listItemImage';
let blurhash = imgData.blurhash;
let imageClass = isLargeStyle ? 'listItemImage listItemImage-large' : 'listItemImage';
if (isLargeStyle && layoutManager.tv) { if (isLargeStyle && layoutManager.tv) {
imageClass += ' listItemImage-large-tv'; imageClass += ' listItemImage-large-tv';
} }
var playOnImageClick = options.imagePlayButton && !layoutManager.tv; const playOnImageClick = options.imagePlayButton && !layoutManager.tv;
if (!clickEntireItem) { if (!clickEntireItem) {
imageClass += ' itemAction'; imageClass += ' itemAction';
} }
var imageAction = playOnImageClick ? 'resume' : action; const imageAction = playOnImageClick ? 'link' : action;
let blurhashAttrib = '';
if (blurhash && blurhash.length > 0) {
blurhashAttrib = 'data-blurhash="' + blurhash + '"';
}
if (imgUrl) { if (imgUrl) {
html += '<div data-action="' + imageAction + '" class="' + imageClass + ' lazy" data-src="' + imgUrl + '" ' + blurhashAttrib + ' item-icon>'; html += '<div data-action="' + imageAction + '" class="' + imageClass + ' lazy" data-src="' + imgUrl + '" item-icon>';
} else { } else {
html += '<div class="' + imageClass + '">'; html += '<div class="' + imageClass + ' cardImageContainer ' + cardBuilder.getDefaultBackgroundClass(item.Name) + '">' + cardBuilder.getDefaultText(item, options);
} }
var indicatorsHtml = ''; let indicatorsHtml = '';
indicatorsHtml += indicators.getPlayedIndicatorHtml(item); indicatorsHtml += indicators.getPlayedIndicatorHtml(item);
if (indicatorsHtml) { if (indicatorsHtml) {
html += '<div class="indicators listItemIndicators">' + indicatorsHtml + '</div>'; html += `<div class="indicators listItemIndicators">${indicatorsHtml}</div>`;
} }
if (playOnImageClick) { if (playOnImageClick) {
html += '<button is="paper-icon-button-light" class="listItemImageButton itemAction" data-action="resume"><span class="material-icons listItemImageButton-icon play_arrow"></span></button>'; html += '<button is="paper-icon-button-light" class="listItemImageButton itemAction" data-action="resume"><span class="material-icons listItemImageButton-icon play_arrow"></span></button>';
} }
var progressHtml = indicators.getProgressBarHtml(item, { const progressHtml = indicators.getProgressBarHtml(item, {
containerClass: 'listItemProgressBar' containerClass: 'listItemProgressBar'
}); });
@ -316,13 +299,12 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
} }
if (options.showIndexNumberLeft) { if (options.showIndexNumberLeft) {
html += '<div class="listItem-indexnumberleft">'; html += '<div class="listItem-indexnumberleft">';
html += (item.IndexNumber || '&nbsp;'); html += (item.IndexNumber || '&nbsp;');
html += '</div>'; html += '</div>';
} }
var textlines = []; const textlines = [];
if (options.showProgramDateTime) { if (options.showProgramDateTime) {
textlines.push(datetime.toLocaleString(datetime.parseISO8601Date(item.StartDate), { textlines.push(datetime.toLocaleString(datetime.parseISO8601Date(item.StartDate), {
@ -345,7 +327,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
} }
} }
var parentTitle = null; let parentTitle = null;
if (options.showParentTitle) { if (options.showParentTitle) {
if (item.Type === 'Episode') { if (item.Type === 'Episode') {
@ -355,18 +337,16 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
} }
} }
var displayName = itemHelper.getDisplayName(item, { let displayName = itemHelper.getDisplayName(item, {
includeParentInfo: options.includeParentInfoInTitle includeParentInfo: options.includeParentInfoInTitle
}); });
if (options.showIndexNumber && item.IndexNumber != null) { if (options.showIndexNumber && item.IndexNumber != null) {
displayName = item.IndexNumber + '. ' + displayName; displayName = `${item.IndexNumber}. ${displayName}`;
} }
if (options.showParentTitle && options.parentTitleWithTitle) { if (options.showParentTitle && options.parentTitleWithTitle) {
if (displayName) { if (displayName) {
if (parentTitle) { if (parentTitle) {
parentTitle += ' - '; parentTitle += ' - ';
} }
@ -384,29 +364,15 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
if (item.IsFolder) { if (item.IsFolder) {
if (options.artist !== false) { if (options.artist !== false) {
if (item.AlbumArtist && item.Type === 'MusicAlbum') { if (item.AlbumArtist && item.Type === 'MusicAlbum') {
textlines.push(item.AlbumArtist); textlines.push(item.AlbumArtist);
} }
} }
} else { } else {
if (options.artist) {
var showArtist = options.artist === true; const artistItems = item.ArtistItems;
var artistItems = item.ArtistItems;
if (!showArtist && options.artist !== false) {
if (!artistItems || !artistItems.length) {
showArtist = true;
} else if (artistItems.length > 1 || containerAlbumArtistIds.indexOf(artistItems[0].Id) === -1) {
showArtist = true;
}
}
if (showArtist) {
if (artistItems && item.Type !== 'MusicAlbum') { if (artistItems && item.Type !== 'MusicAlbum') {
textlines.push(artistItems.map(function (a) { textlines.push(artistItems.map(a => {
return a.Name; return a.Name;
}).join(', ')); }).join(', '));
} }
@ -414,7 +380,6 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
} }
if (item.Type === 'TvChannel') { if (item.Type === 'TvChannel') {
if (item.CurrentProgram) { if (item.CurrentProgram) {
textlines.push(itemHelper.getDisplayName(item.CurrentProgram)); textlines.push(itemHelper.getDisplayName(item.CurrentProgram));
} }
@ -429,21 +394,22 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
cssClass += ' listItemBody-noleftpadding'; cssClass += ' listItemBody-noleftpadding';
} }
html += '<div class="' + cssClass + '">'; html += `<div class="${cssClass}">`;
html += getTextLinesHtml(textlines, isLargeStyle); html += getTextLinesHtml(textlines, isLargeStyle);
if (options.mediaInfo !== false) { if (options.mediaInfo !== false) {
if (!enableSideMediaInfo) { if (!enableSideMediaInfo) {
const mediaInfoClass = 'secondary listItemMediaInfo listItemBodyText';
var mediaInfoClass = 'secondary listItemMediaInfo listItemBodyText'; html += `<div class="${mediaInfoClass}">`;
html += mediaInfo.getPrimaryMediaInfoHtml(item, {
html += '<div class="' + mediaInfoClass + '">' + mediaInfo.getPrimaryMediaInfoHtml(item, {
episodeTitle: false, episodeTitle: false,
originalAirDate: false, originalAirDate: false,
subtitles: false subtitles: false
}) + '</div>'; });
html += '</div>';
} }
} }
@ -457,7 +423,8 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
if (options.mediaInfo !== false) { if (options.mediaInfo !== false) {
if (enableSideMediaInfo) { if (enableSideMediaInfo) {
html += '<div class="secondary listItemMediaInfo">' + mediaInfo.getPrimaryMediaInfoHtml(item, { html += '<div class="secondary listItemMediaInfo">';
html += mediaInfo.getPrimaryMediaInfoHtml(item, {
year: false, year: false,
container: false, container: false,
@ -465,7 +432,8 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
criticRating: false, criticRating: false,
endsAt: false endsAt: false
}) + '</div>'; });
html += '</div>';
} }
} }
@ -476,7 +444,6 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
html += '<div class="listViewUserDataButtons">'; html += '<div class="listViewUserDataButtons">';
if (!clickEntireItem) { if (!clickEntireItem) {
if (options.addToListButton) { if (options.addToListButton) {
html += '<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="addtoplaylist"><span class="material-icons playlist_add"></span></button>'; html += '<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="addtoplaylist"><span class="material-icons playlist_add"></span></button>';
} }
@ -490,9 +457,8 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
} }
if (options.enableUserDataButtons !== false) { if (options.enableUserDataButtons !== false) {
const userData = item.UserData || {};
var userData = item.UserData || {}; const likes = userData.Likes == null ? '' : userData.Likes;
var likes = userData.Likes == null ? '' : userData.Likes;
if (itemHelper.canMarkPlayed(item) && options.enablePlayedButton !== false) { if (itemHelper.canMarkPlayed(item) && options.enablePlayedButton !== false) {
html += '<button is="emby-playstatebutton" type="button" class="listItemButton paper-icon-button-light" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-played="' + (userData.Played) + '"><span class="material-icons check"></span></button>'; html += '<button is="emby-playstatebutton" type="button" class="listItemButton paper-icon-button-light" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-played="' + (userData.Played) + '"><span class="material-icons check"></span></button>';
@ -519,7 +485,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
} }
} }
html += '</' + outerTagName + '>'; html += `</${outerTagName}>`;
outerHtml += html; outerHtml += html;
} }
@ -527,7 +493,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
return outerHtml; return outerHtml;
} }
return { /* eslint-enable indent */
export default {
getListViewHtml: getListViewHtml getListViewHtml: getListViewHtml
}; };
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View file

@ -1,24 +1,17 @@
define(['components/loading/loadingLegacy', 'browser', 'css!./loading'], function (loadingLegacy, browser) { import 'css!./loading';
'use strict';
if (browser.tizen || browser.operaTv || browser.chromecast || browser.orsay || browser.web0s || browser.ps4) { let loadingElem;
return loadingLegacy; let layer1;
} let layer2;
let layer3;
let layer4;
let circleLefts;
let circleRights;
var loadingElem; export function show() {
var layer1; let elem = loadingElem;
var layer2;
var layer3;
var layer4;
var circleLefts;
var circleRights;
return {
show: function () {
var elem = loadingElem;
if (!elem) { if (!elem) {
elem = document.createElement('div'); elem = document.createElement('div');
loadingElem = elem; loadingElem = elem;
@ -45,22 +38,19 @@ define(['components/loading/loadingLegacy', 'browser', 'css!./loading'], functio
layer3.classList.add('mdl-spinner__layer-3-active'); layer3.classList.add('mdl-spinner__layer-3-active');
layer4.classList.add('mdl-spinner__layer-4-active'); layer4.classList.add('mdl-spinner__layer-4-active');
var i; for (let i = 0, length = circleLefts.length; i < length; i++) {
var length;
for (i = 0, length = circleLefts.length; i < length; i++) {
circleLefts[i].classList.add('mdl-spinner__circleLeft-active'); circleLefts[i].classList.add('mdl-spinner__circleLeft-active');
} }
for (i = 0, length = circleRights.length; i < length; i++) { for (let i = 0, length = circleRights.length; i < length; i++) {
circleRights[i].classList.add('mdl-spinner__circleRight-active'); circleRights[i].classList.add('mdl-spinner__circleRight-active');
} }
}, }
hide: function () {
var elem = loadingElem; export function hide() {
const elem = loadingElem;
if (elem) { if (elem) {
elem.classList.remove('mdlSpinnerActive'); elem.classList.remove('mdlSpinnerActive');
elem.classList.remove('mdl-spinner__layer-1-active'); elem.classList.remove('mdl-spinner__layer-1-active');
@ -68,17 +58,17 @@ define(['components/loading/loadingLegacy', 'browser', 'css!./loading'], functio
elem.classList.remove('mdl-spinner__layer-3-active'); elem.classList.remove('mdl-spinner__layer-3-active');
elem.classList.remove('mdl-spinner__layer-4-active'); elem.classList.remove('mdl-spinner__layer-4-active');
var i; for (let i = 0, length = circleLefts.length; i < length; i++) {
var length;
for (i = 0, length = circleLefts.length; i < length; i++) {
circleLefts[i].classList.remove('mdl-spinner__circleLeft-active'); circleLefts[i].classList.remove('mdl-spinner__circleLeft-active');
} }
for (i = 0, length = circleRights.length; i < length; i++) { for (let i = 0, length = circleRights.length; i < length; i++) {
circleRights[i].classList.remove('mdl-spinner__circleRight-active'); circleRights[i].classList.remove('mdl-spinner__circleRight-active');
} }
} }
} }
};
}); export default {
show: show,
hide: hide
};

View file

@ -1,10 +0,0 @@
.loading-spinner {
margin-top: -3em;
margin-left: -3em;
width: 6em;
height: 6em;
position: fixed;
top: 50%;
left: 50%;
z-index: 9999999;
}

View file

@ -1,28 +0,0 @@
define(['require', 'css!./loadingLegacy'], function (require) {
'use strict';
var loadingElem;
return {
show: function () {
var elem = loadingElem;
if (!elem) {
elem = document.createElement('img');
elem.src = require.toUrl('.').split('?')[0] + '/loader.gif';
loadingElem = elem;
elem.classList.add('loading-spinner');
document.body.appendChild(elem);
}
elem.classList.remove('hide');
},
hide: function () {
var elem = loadingElem;
if (elem) {
elem.classList.add('hide');
}
}
};
});

View file

@ -1,31 +1,17 @@
define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom, browser, events) { import dom from 'dom';
'use strict'; import browser from 'browser';
import events from 'events';
import 'emby-tabs';
import 'emby-button';
var tabOwnerView; /* eslint-disable indent */
var queryScope = document.querySelector('.skinHeader');
var footerTabsContainer;
var headerTabsContainer;
var tabsElem;
function enableTabsInFooter() { let tabOwnerView;
return false; const queryScope = document.querySelector('.skinHeader');
} let headerTabsContainer;
let tabsElem;
function getTabsContainerElem() {
}
function ensureElements(enableInFooter) {
if (enableInFooter) {
if (!footerTabsContainer) {
footerTabsContainer = document.createElement('div');
footerTabsContainer.classList.add('footerTabs');
footerTabsContainer.classList.add('sectionTabs');
footerTabsContainer.classList.add('hide');
//appFooter.add(footerTabsContainer);
}
}
function ensureElements() {
if (!headerTabsContainer) { if (!headerTabsContainer) {
headerTabsContainer = queryScope.querySelector('.headerTabs'); headerTabsContainer = queryScope.querySelector('.headerTabs');
} }
@ -37,14 +23,12 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
} }
function allowSwipe(target) { function allowSwipe(target) {
function allowSwipeOn(elem) { function allowSwipeOn(elem) {
if (dom.parentWithTag(elem, 'input')) { if (dom.parentWithTag(elem, 'input')) {
return false; return false;
} }
var classList = elem.classList; const classList = elem.classList;
if (classList) { if (classList) {
return !classList.contains('scrollX') && !classList.contains('animatedScrollX'); return !classList.contains('scrollX') && !classList.contains('animatedScrollX');
} }
@ -52,7 +36,7 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
return true; return true;
} }
var parent = target; let parent = target;
while (parent != null) { while (parent != null) {
if (!allowSwipeOn(parent)) { if (!allowSwipeOn(parent)) {
return false; return false;
@ -64,28 +48,25 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
} }
function configureSwipeTabs(view, tabsElem, getTabContainersFn) { function configureSwipeTabs(view, tabsElem, getTabContainersFn) {
if (!browser.touch) { if (!browser.touch) {
return; return;
} }
// implement without hammer // implement without hammer
var pageCount = getTabContainersFn().length; const onSwipeLeft = function (e, target) {
var onSwipeLeft = function (e, target) {
if (allowSwipe(target) && view.contains(target)) { if (allowSwipe(target) && view.contains(target)) {
tabsElem.selectNext(); tabsElem.selectNext();
} }
}; };
var onSwipeRight = function (e, target) { const onSwipeRight = function (e, target) {
if (allowSwipe(target) && view.contains(target)) { if (allowSwipe(target) && view.contains(target)) {
tabsElem.selectPrevious(); tabsElem.selectPrevious();
} }
}; };
require(['touchHelper'], function (TouchHelper) { import('touchHelper').then(({default: TouchHelper}) => {
const touchHelper = new TouchHelper(view.parentNode.parentNode);
var touchHelper = new TouchHelper(view.parentNode.parentNode);
events.on(touchHelper, 'swipeleft', onSwipeLeft); events.on(touchHelper, 'swipeleft', onSwipeLeft);
events.on(touchHelper, 'swiperight', onSwipeRight); events.on(touchHelper, 'swiperight', onSwipeRight);
@ -96,29 +77,20 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
}); });
} }
function setTabs(view, selectedIndex, getTabsFn, getTabContainersFn, onBeforeTabChange, onTabChange, setSelectedIndex) { export function setTabs(view, selectedIndex, getTabsFn, getTabContainersFn, onBeforeTabChange, onTabChange, setSelectedIndex) {
var enableInFooter = enableTabsInFooter();
if (!view) { if (!view) {
if (tabOwnerView) { if (tabOwnerView) {
if (!headerTabsContainer) { if (!headerTabsContainer) {
headerTabsContainer = queryScope.querySelector('.headerTabs'); headerTabsContainer = queryScope.querySelector('.headerTabs');
} }
ensureElements(enableInFooter); ensureElements();
document.body.classList.remove('withSectionTabs'); document.body.classList.remove('withSectionTabs');
headerTabsContainer.innerHTML = ''; headerTabsContainer.innerHTML = '';
headerTabsContainer.classList.add('hide'); headerTabsContainer.classList.add('hide');
if (footerTabsContainer) {
footerTabsContainer.innerHTML = '';
footerTabsContainer.classList.add('hide');
}
tabOwnerView = null; tabOwnerView = null;
} }
return { return {
@ -127,28 +99,26 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
}; };
} }
ensureElements(enableInFooter); ensureElements();
var tabsContainerElem = enableInFooter ? footerTabsContainer : headerTabsContainer; const tabsContainerElem = headerTabsContainer;
if (!tabOwnerView) { if (!tabOwnerView) {
tabsContainerElem.classList.remove('hide'); tabsContainerElem.classList.remove('hide');
} }
if (tabOwnerView !== view) { if (tabOwnerView !== view) {
let index = 0;
var index = 0; const indexAttribute = selectedIndex == null ? '' : (' data-index="' + selectedIndex + '"');
const tabsHtml = '<div is="emby-tabs"' + indexAttribute + ' class="tabs-viewmenubar"><div class="emby-tabs-slider" style="white-space:nowrap;">' + getTabsFn().map(function (t) {
var indexAttribute = selectedIndex == null ? '' : (' data-index="' + selectedIndex + '"'); let tabClass = 'emby-tab-button';
var tabsHtml = '<div is="emby-tabs"' + indexAttribute + ' class="tabs-viewmenubar"><div class="emby-tabs-slider" style="white-space:nowrap;">' + getTabsFn().map(function (t) {
var tabClass = 'emby-tab-button';
if (t.enabled === false) { if (t.enabled === false) {
tabClass += ' hide'; tabClass += ' hide';
} }
var tabHtml; let tabHtml;
if (t.cssClass) { if (t.cssClass) {
tabClass += ' ' + t.cssClass; tabClass += ' ' + t.cssClass;
@ -162,7 +132,6 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
index++; index++;
return tabHtml; return tabHtml;
}).join('') + '</div></div>'; }).join('') + '</div></div>';
tabsContainerElem.innerHTML = tabsHtml; tabsContainerElem.innerHTML = tabsHtml;
@ -176,23 +145,15 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
configureSwipeTabs(view, tabsElem, getTabContainersFn); configureSwipeTabs(view, tabsElem, getTabContainersFn);
tabsElem.addEventListener('beforetabchange', function (e) { tabsElem.addEventListener('beforetabchange', function (e) {
const tabContainers = getTabContainersFn();
var tabContainers = getTabContainersFn();
if (e.detail.previousIndex != null) { if (e.detail.previousIndex != null) {
const previousPanel = tabContainers[e.detail.previousIndex];
var previousPanel = tabContainers[e.detail.previousIndex];
if (previousPanel) { if (previousPanel) {
previousPanel.classList.remove('is-active'); previousPanel.classList.remove('is-active');
} }
} }
var newPanel = tabContainers[e.detail.selectedTabIndex]; const newPanel = tabContainers[e.detail.selectedTabIndex];
//if (e.detail.previousIndex != null && e.detail.previousIndex != e.detail.selectedTabIndex) {
// if (newPanel.animate && (animateTabs || []).indexOf(e.detail.selectedTabIndex) != -1) {
// fadeInRight(newPanel);
// }
//}
if (newPanel) { if (newPanel) {
newPanel.classList.add('is-active'); newPanel.classList.add('is-active');
@ -210,16 +171,11 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
if (tabsElem.selectedIndex) { if (tabsElem.selectedIndex) {
tabsElem.selectedIndex(selectedIndex); tabsElem.selectedIndex(selectedIndex);
} else { } else {
tabsElem.readySelectedIndex = selectedIndex; tabsElem.readySelectedIndex = selectedIndex;
tabsElem.addEventListener('ready', onViewTabsReady); tabsElem.addEventListener('ready', onViewTabsReady);
} }
} }
//if (enableSwipe !== false) {
// libraryBrowser.configureSwipeTabs(ownerpage, tabs);
//}
return { return {
tabsContainer: tabsContainerElem, tabsContainer: tabsContainerElem,
tabs: tabsContainerElem.querySelector('[is="emby-tabs"]'), tabs: tabsContainerElem.querySelector('[is="emby-tabs"]'),
@ -241,9 +197,8 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
}; };
} }
function selectedTabIndex(index) { export function selectedTabIndex(index) {
const tabsContainerElem = headerTabsContainer;
var tabsContainerElem = headerTabsContainer;
if (!tabsElem) { if (!tabsElem) {
tabsElem = tabsContainerElem.querySelector('[is="emby-tabs"]'); tabsElem = tabsContainerElem.querySelector('[is="emby-tabs"]');
@ -256,13 +211,8 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
} }
} }
function getTabsElement() { export function getTabsElement() {
return document.querySelector('.tabs-viewmenubar'); return document.querySelector('.tabs-viewmenubar');
} }
return { /* eslint-enable indent */
setTabs: setTabs,
getTabsElement: getTabsElement,
selectedTabIndex: selectedTabIndex
};
});

View file

@ -1,5 +1,24 @@
define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionseditor/libraryoptionseditor', 'globalize', 'emby-toggle', 'emby-input', 'emby-select', 'paper-icon-button-light', 'listViewStyle', 'formDialogStyle', 'emby-button', 'flexStyles'], function (loading, dialogHelper, dom, $, libraryoptionseditor, globalize) { /* eslint-disable indent */
'use strict';
/**
* Module for media library creator.
* @module components/mediaLibraryCreator/mediaLibraryCreator
*/
import loading from 'loading';
import dialogHelper from 'dialogHelper';
import dom from 'dom';
import $ from 'jQuery';
import libraryoptionseditor from 'components/libraryoptionseditor/libraryoptionseditor';
import globalize from 'globalize';
import 'emby-toggle';
import 'emby-input';
import 'emby-select';
import 'paper-icon-button-light';
import 'listViewStyle';
import 'formDialogStyle';
import 'emby-button';
import 'flexStyles';
function onAddLibrary() { function onAddLibrary() {
if (isCreating) { if (isCreating) {
@ -7,7 +26,7 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed
} }
if (pathInfos.length == 0) { if (pathInfos.length == 0) {
require(['alert'], function (alert) { import('alert').then(({default: alert}) => {
alert({ alert({
text: globalize.translate('PleaseAddAtLeastOneFolder'), text: globalize.translate('PleaseAddAtLeastOneFolder'),
type: 'error' type: 'error'
@ -19,23 +38,23 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed
isCreating = true; isCreating = true;
loading.show(); loading.show();
var dlg = dom.parentWithClass(this, 'dlg-librarycreator'); const dlg = dom.parentWithClass(this, 'dlg-librarycreator');
var name = $('#txtValue', dlg).val(); const name = $('#txtValue', dlg).val();
var type = $('#selectCollectionType', dlg).val(); let type = $('#selectCollectionType', dlg).val();
if (type == 'mixed') { if (type == 'mixed') {
type = null; type = null;
} }
var libraryOptions = libraryoptionseditor.getLibraryOptions(dlg.querySelector('.libraryOptions')); const libraryOptions = libraryoptionseditor.getLibraryOptions(dlg.querySelector('.libraryOptions'));
libraryOptions.PathInfos = pathInfos; libraryOptions.PathInfos = pathInfos;
ApiClient.addVirtualFolder(name, type, currentOptions.refresh, libraryOptions).then(function () { ApiClient.addVirtualFolder(name, type, currentOptions.refresh, libraryOptions).then(() => {
hasChanges = true; hasChanges = true;
isCreating = false; isCreating = false;
loading.hide(); loading.hide();
dialogHelper.close(dlg); dialogHelper.close(dlg);
}, function () { }, () => {
require(['toast'], function (toast) { import('toast').then(({default: toast}) => {
toast(globalize.translate('ErrorAddingMediaPathToVirtualFolder')); toast(globalize.translate('ErrorAddingMediaPathToVirtualFolder'));
}); });
@ -46,15 +65,15 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed
} }
function getCollectionTypeOptionsHtml(collectionTypeOptions) { function getCollectionTypeOptionsHtml(collectionTypeOptions) {
return collectionTypeOptions.map(function (i) { return collectionTypeOptions.map(i => {
return '<option value="' + i.value + '">' + i.name + '</option>'; return `<option value="${i.value}">${i.name}</option>`;
}).join(''); }).join('');
} }
function initEditor(page, collectionTypeOptions) { function initEditor(page, collectionTypeOptions) {
$('#selectCollectionType', page).html(getCollectionTypeOptionsHtml(collectionTypeOptions)).val('').on('change', function () { $('#selectCollectionType', page).html(getCollectionTypeOptionsHtml(collectionTypeOptions)).val('').on('change', function () {
var value = this.value; const value = this.value;
var dlg = $(this).parents('.dialog')[0]; const dlg = $(this).parents('.dialog')[0];
libraryoptionseditor.setContentType(dlg.querySelector('.libraryOptions'), value == 'mixed' ? '' : value); libraryoptionseditor.setContentType(dlg.querySelector('.libraryOptions'), value == 'mixed' ? '' : value);
if (value) { if (value) {
@ -64,12 +83,12 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed
} }
if (value != 'mixed') { if (value != 'mixed') {
var index = this.selectedIndex; const index = this.selectedIndex;
if (index != -1) { if (index != -1) {
var name = this.options[index].innerHTML.replace('*', '').replace('&amp;', '&'); const name = this.options[index].innerHTML.replace('*', '').replace('&amp;', '&');
$('#txtValue', dlg).val(name); $('#txtValue', dlg).val(name);
var folderOption = collectionTypeOptions.filter(function (i) { const folderOption = collectionTypeOptions.filter(i => {
return i.value == value; return i.value == value;
})[0]; })[0];
$('.collectionTypeFieldDescription', dlg).html(folderOption.message || ''); $('.collectionTypeFieldDescription', dlg).html(folderOption.message || '');
@ -83,15 +102,15 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed
} }
function onToggleAdvancedChange() { function onToggleAdvancedChange() {
var dlg = dom.parentWithClass(this, 'dlg-librarycreator'); const dlg = dom.parentWithClass(this, 'dlg-librarycreator');
libraryoptionseditor.setAdvancedVisible(dlg.querySelector('.libraryOptions'), this.checked); libraryoptionseditor.setAdvancedVisible(dlg.querySelector('.libraryOptions'), this.checked);
} }
function onAddButtonClick() { function onAddButtonClick() {
var page = dom.parentWithClass(this, 'dlg-librarycreator'); const page = dom.parentWithClass(this, 'dlg-librarycreator');
require(['directorybrowser'], function (directoryBrowser) { import('directorybrowser').then(({default: directoryBrowser}) => {
var picker = new directoryBrowser(); const picker = new directoryBrowser();
picker.show({ picker.show({
enableNetworkSharePath: true, enableNetworkSharePath: true,
callback: function (path, networkSharePath) { callback: function (path, networkSharePath) {
@ -106,24 +125,24 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed
} }
function getFolderHtml(pathInfo, index) { function getFolderHtml(pathInfo, index) {
var html = ''; let html = '';
html += '<div class="listItem listItem-border lnkPath" style="padding-left:.5em;">'; html += '<div class="listItem listItem-border lnkPath" style="padding-left:.5em;">';
html += '<div class="' + (pathInfo.NetworkPath ? 'listItemBody two-line' : 'listItemBody') + '">'; html += `<div class="${pathInfo.NetworkPath ? 'listItemBody two-line' : 'listItemBody'}">`;
html += '<div class="listItemBodyText">' + pathInfo.Path + '</div>'; html += `<div class="listItemBodyText">${pathInfo.Path}</div>`;
if (pathInfo.NetworkPath) { if (pathInfo.NetworkPath) {
html += '<div class="listItemBodyText secondary">' + pathInfo.NetworkPath + '</div>'; html += `<div class="listItemBodyText secondary">${pathInfo.NetworkPath}</div>`;
} }
html += '</div>'; html += '</div>';
html += '<button type="button" is="paper-icon-button-light"" class="listItemButton btnRemovePath" data-index="' + index + '"><span class="material-icons remove_circle"></span></button>'; html += `<button type="button" is="paper-icon-button-light"" class="listItemButton btnRemovePath" data-index="${index}"><span class="material-icons remove_circle"></span></button>`;
html += '</div>'; html += '</div>';
return html; return html;
} }
function renderPaths(page) { function renderPaths(page) {
var foldersHtml = pathInfos.map(getFolderHtml).join(''); const foldersHtml = pathInfos.map(getFolderHtml).join('');
var folderList = page.querySelector('.folderList'); const folderList = page.querySelector('.folderList');
folderList.innerHTML = foldersHtml; folderList.innerHTML = foldersHtml;
if (foldersHtml) { if (foldersHtml) {
@ -134,13 +153,13 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed
} }
function addMediaLocation(page, path, networkSharePath) { function addMediaLocation(page, path, networkSharePath) {
var pathLower = path.toLowerCase(); const pathLower = path.toLowerCase();
var pathFilter = pathInfos.filter(function (p) { const pathFilter = pathInfos.filter(p => {
return p.Path.toLowerCase() == pathLower; return p.Path.toLowerCase() == pathLower;
}); });
if (!pathFilter.length) { if (!pathFilter.length) {
var pathInfo = { const pathInfo = {
Path: path Path: path
}; };
@ -154,11 +173,11 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed
} }
function onRemoveClick(e) { function onRemoveClick(e) {
var button = dom.parentWithClass(e.target, 'btnRemovePath'); const button = dom.parentWithClass(e.target, 'btnRemovePath');
var index = parseInt(button.getAttribute('data-index')); const index = parseInt(button.getAttribute('data-index'));
var location = pathInfos[index].Path; const location = pathInfos[index].Path;
var locationLower = location.toLowerCase(); const locationLower = location.toLowerCase();
pathInfos = pathInfos.filter(function (p) { pathInfos = pathInfos.filter(p => {
return p.Path.toLowerCase() != locationLower; return p.Path.toLowerCase() != locationLower;
}); });
renderPaths(dom.parentWithClass(button, 'dlg-librarycreator')); renderPaths(dom.parentWithClass(button, 'dlg-librarycreator'));
@ -169,24 +188,20 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed
} }
function initLibraryOptions(dlg) { function initLibraryOptions(dlg) {
libraryoptionseditor.embed(dlg.querySelector('.libraryOptions')).then(function () { libraryoptionseditor.embed(dlg.querySelector('.libraryOptions')).then(() => {
$('#selectCollectionType', dlg).trigger('change'); $('#selectCollectionType', dlg).trigger('change');
onToggleAdvancedChange.call(dlg.querySelector('.chkAdvanced')); onToggleAdvancedChange.call(dlg.querySelector('.chkAdvanced'));
}); });
} }
function editor() { export class showEditor {
this.show = function (options) { constructor(options) {
return new Promise(function (resolve, reject) { return new Promise((resolve) => {
currentOptions = options; currentOptions = options;
currentResolve = resolve; currentResolve = resolve;
hasChanges = false; hasChanges = false;
var xhr = new XMLHttpRequest(); import('text!./components/mediaLibraryCreator/mediaLibraryCreator.template.html').then(({default: template}) => {
xhr.open('GET', 'components/mediaLibraryCreator/mediaLibraryCreator.template.html', true); const dlg = dialogHelper.createDialog({
xhr.onload = function (e) {
var template = this.response;
var dlg = dialogHelper.createDialog({
size: 'small', size: 'small',
modal: false, modal: false,
removeOnClose: true, removeOnClose: true,
@ -196,27 +211,26 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed
dlg.classList.add('background-theme-a'); dlg.classList.add('background-theme-a');
dlg.classList.add('dlg-librarycreator'); dlg.classList.add('dlg-librarycreator');
dlg.classList.add('formDialog'); dlg.classList.add('formDialog');
dlg.innerHTML = globalize.translateDocument(template); dlg.innerHTML = globalize.translateHtml(template);
initEditor(dlg, options.collectionTypeOptions); initEditor(dlg, options.collectionTypeOptions);
dlg.addEventListener('close', onDialogClosed); dlg.addEventListener('close', onDialogClosed);
dialogHelper.open(dlg); dialogHelper.open(dlg);
dlg.querySelector('.btnCancel').addEventListener('click', function () { dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg); dialogHelper.close(dlg);
}); });
pathInfos = []; pathInfos = [];
renderPaths(dlg); renderPaths(dlg);
initLibraryOptions(dlg); initLibraryOptions(dlg);
};
xhr.send();
}); });
}; });
} }
}
var pathInfos = []; let pathInfos = [];
var currentResolve; let currentResolve;
var currentOptions; let currentOptions;
var hasChanges = false; let hasChanges = false;
var isCreating = false; let isCreating = false;
return editor;
}); /* eslint-enable indent */
export default showEditor;

View file

@ -24,8 +24,8 @@
<div class="folders"> <div class="folders">
<div style="display: flex; align-items: center;"> <div style="display: flex; align-items: center;">
<h1 style="margin: .5em 0;">${HeadersFolders}</h1> <h1 style="margin: .5em 0;">${Folders}</h1>
<button is="emby-button" type="button" class="fab btnAddFolder submit" style="margin-left:1em;" title="${ButtonAdd}"> <button is="emby-button" type="button" class="fab btnAddFolder submit" style="margin-left:1em;" title="${Add}">
<span class="material-icons add"></span> <span class="material-icons add"></span>
</button> </button>
</div> </div>

View file

@ -1,5 +1,22 @@
define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionseditor/libraryoptionseditor', 'globalize', 'emby-button', 'listViewStyle', 'paper-icon-button-light', 'formDialogStyle', 'emby-toggle', 'flexStyles'], function (jQuery, loading, dialogHelper, dom, libraryoptionseditor, globalize) { /* eslint-disable indent */
'use strict';
/**
* Module for media library editor.
* @module components/mediaLibraryEditor/mediaLibraryEditor
*/
import jQuery from 'jQuery';
import loading from 'loading';
import dialogHelper from 'dialogHelper';
import dom from 'dom';
import libraryoptionseditor from 'components/libraryoptionseditor/libraryoptionseditor';
import globalize from 'globalize';
import 'emby-button';
import 'listViewStyle';
import 'paper-icon-button-light';
import 'formDialogStyle';
import 'emby-toggle';
import 'flexStyles';
function onEditLibrary() { function onEditLibrary() {
if (isCreating) { if (isCreating) {
@ -8,15 +25,15 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed
isCreating = true; isCreating = true;
loading.show(); loading.show();
var dlg = dom.parentWithClass(this, 'dlg-libraryeditor'); const dlg = dom.parentWithClass(this, 'dlg-libraryeditor');
var libraryOptions = libraryoptionseditor.getLibraryOptions(dlg.querySelector('.libraryOptions')); let libraryOptions = libraryoptionseditor.getLibraryOptions(dlg.querySelector('.libraryOptions'));
libraryOptions = Object.assign(currentOptions.library.LibraryOptions || {}, libraryOptions); libraryOptions = Object.assign(currentOptions.library.LibraryOptions || {}, libraryOptions);
ApiClient.updateVirtualFolderOptions(currentOptions.library.ItemId, libraryOptions).then(function () { ApiClient.updateVirtualFolderOptions(currentOptions.library.ItemId, libraryOptions).then(() => {
hasChanges = true; hasChanges = true;
isCreating = false; isCreating = false;
loading.hide(); loading.hide();
dialogHelper.close(dlg); dialogHelper.close(dlg);
}, function () { }, () => {
isCreating = false; isCreating = false;
loading.hide(); loading.hide();
}); });
@ -24,51 +41,51 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed
} }
function addMediaLocation(page, path, networkSharePath) { function addMediaLocation(page, path, networkSharePath) {
var virtualFolder = currentOptions.library; const virtualFolder = currentOptions.library;
var refreshAfterChange = currentOptions.refresh; const refreshAfterChange = currentOptions.refresh;
ApiClient.addMediaPath(virtualFolder.Name, path, networkSharePath, refreshAfterChange).then(function () { ApiClient.addMediaPath(virtualFolder.Name, path, networkSharePath, refreshAfterChange).then(() => {
hasChanges = true; hasChanges = true;
refreshLibraryFromServer(page); refreshLibraryFromServer(page);
}, function () { }, () => {
require(['toast'], function (toast) { import('toast').then(({default: toast}) => {
toast(globalize.translate('ErrorAddingMediaPathToVirtualFolder')); toast(globalize.translate('ErrorAddingMediaPathToVirtualFolder'));
}); });
}); });
} }
function updateMediaLocation(page, path, networkSharePath) { function updateMediaLocation(page, path, networkSharePath) {
var virtualFolder = currentOptions.library; const virtualFolder = currentOptions.library;
ApiClient.updateMediaPath(virtualFolder.Name, { ApiClient.updateMediaPath(virtualFolder.Name, {
Path: path, Path: path,
NetworkPath: networkSharePath NetworkPath: networkSharePath
}).then(function () { }).then(() => {
hasChanges = true; hasChanges = true;
refreshLibraryFromServer(page); refreshLibraryFromServer(page);
}, function () { }, () => {
require(['toast'], function (toast) { import('toast').then(({default: toast}) => {
toast(globalize.translate('ErrorAddingMediaPathToVirtualFolder')); toast(globalize.translate('ErrorAddingMediaPathToVirtualFolder'));
}); });
}); });
} }
function onRemoveClick(btnRemovePath, location) { function onRemoveClick(btnRemovePath, location) {
var button = btnRemovePath; const button = btnRemovePath;
var virtualFolder = currentOptions.library; const virtualFolder = currentOptions.library;
require(['confirm'], function (confirm) { import('confirm').then(({default: confirm}) => {
confirm({ confirm({
title: globalize.translate('HeaderRemoveMediaLocation'), title: globalize.translate('HeaderRemoveMediaLocation'),
text: globalize.translate('MessageConfirmRemoveMediaLocation'), text: globalize.translate('MessageConfirmRemoveMediaLocation'),
confirmText: globalize.translate('ButtonDelete'), confirmText: globalize.translate('Delete'),
primary: 'delete' primary: 'delete'
}).then(function () { }).then(() => {
var refreshAfterChange = currentOptions.refresh; const refreshAfterChange = currentOptions.refresh;
ApiClient.removeMediaPath(virtualFolder.Name, location, refreshAfterChange).then(function () { ApiClient.removeMediaPath(virtualFolder.Name, location, refreshAfterChange).then(() => {
hasChanges = true; hasChanges = true;
refreshLibraryFromServer(dom.parentWithClass(button, 'dlg-libraryeditor')); refreshLibraryFromServer(dom.parentWithClass(button, 'dlg-libraryeditor'));
}, function () { }, () => {
require(['toast'], function (toast) { import('toast').then(({default: toast}) => {
toast(globalize.translate('DefaultErrorMessage')); toast(globalize.translate('ErrorDefault'));
}); });
}); });
}); });
@ -76,14 +93,14 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed
} }
function onListItemClick(e) { function onListItemClick(e) {
var listItem = dom.parentWithClass(e.target, 'listItem'); const listItem = dom.parentWithClass(e.target, 'listItem');
if (listItem) { if (listItem) {
var index = parseInt(listItem.getAttribute('data-index')); const index = parseInt(listItem.getAttribute('data-index'));
var pathInfos = (currentOptions.library.LibraryOptions || {}).PathInfos || []; const pathInfos = (currentOptions.library.LibraryOptions || {}).PathInfos || [];
var pathInfo = null == index ? {} : pathInfos[index] || {}; const pathInfo = index == null ? {} : pathInfos[index] || {};
var originalPath = pathInfo.Path || (null == index ? null : currentOptions.library.Locations[index]); const originalPath = pathInfo.Path || (index == null ? null : currentOptions.library.Locations[index]);
var btnRemovePath = dom.parentWithClass(e.target, 'btnRemovePath'); const btnRemovePath = dom.parentWithClass(e.target, 'btnRemovePath');
if (btnRemovePath) { if (btnRemovePath) {
onRemoveClick(btnRemovePath, originalPath); onRemoveClick(btnRemovePath, originalPath);
@ -95,26 +112,26 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed
} }
function getFolderHtml(pathInfo, index) { function getFolderHtml(pathInfo, index) {
var html = ''; let html = '';
html += '<div class="listItem listItem-border lnkPath" data-index="' + index + '" style="padding-left:.5em;">'; html += `<div class="listItem listItem-border lnkPath" data-index="${index}" style="padding-left:.5em;">`;
html += '<div class="' + (pathInfo.NetworkPath ? 'listItemBody two-line' : 'listItemBody') + '">'; html += `<div class="${pathInfo.NetworkPath ? 'listItemBody two-line' : 'listItemBody'}">`;
html += '<h3 class="listItemBodyText">'; html += '<h3 class="listItemBodyText">';
html += pathInfo.Path; html += pathInfo.Path;
html += '</h3>'; html += '</h3>';
if (pathInfo.NetworkPath) { if (pathInfo.NetworkPath) {
html += '<div class="listItemBodyText secondary">' + pathInfo.NetworkPath + '</div>'; html += `<div class="listItemBodyText secondary">${pathInfo.NetworkPath}</div>`;
} }
html += '</div>'; html += '</div>';
html += '<button type="button" is="paper-icon-button-light" class="listItemButton btnRemovePath" data-index="' + index + '"><span class="material-icons remove_circle"></span></button>'; html += `<button type="button" is="paper-icon-button-light" class="listItemButton btnRemovePath" data-index="${index}"><span class="material-icons remove_circle"></span></button>`;
html += '</div>'; html += '</div>';
return html; return html;
} }
function refreshLibraryFromServer(page) { function refreshLibraryFromServer(page) {
ApiClient.getVirtualFolders().then(function (result) { ApiClient.getVirtualFolders().then(result => {
var library = result.filter(function (f) { const library = result.filter(f => {
return f.Name === currentOptions.library.Name; return f.Name === currentOptions.library.Name;
})[0]; })[0];
@ -126,10 +143,10 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed
} }
function renderLibrary(page, options) { function renderLibrary(page, options) {
var pathInfos = (options.library.LibraryOptions || {}).PathInfos || []; let pathInfos = (options.library.LibraryOptions || {}).PathInfos || [];
if (!pathInfos.length) { if (!pathInfos.length) {
pathInfos = options.library.Locations.map(function (p) { pathInfos = options.library.Locations.map(p => {
return { return {
Path: p Path: p
}; };
@ -150,11 +167,11 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed
} }
function showDirectoryBrowser(context, originalPath, networkPath) { function showDirectoryBrowser(context, originalPath, networkPath) {
require(['directorybrowser'], function (directoryBrowser) { import('directorybrowser').then(({default: directoryBrowser}) => {
var picker = new directoryBrowser(); const picker = new directoryBrowser();
picker.show({ picker.show({
enableNetworkSharePath: true, enableNetworkSharePath: true,
pathReadOnly: null != originalPath, pathReadOnly: originalPath != null,
path: originalPath, path: originalPath,
networkSharePath: networkPath, networkSharePath: networkPath,
callback: function (path, networkSharePath) { callback: function (path, networkSharePath) {
@ -173,7 +190,7 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed
} }
function onToggleAdvancedChange() { function onToggleAdvancedChange() {
var dlg = dom.parentWithClass(this, 'dlg-libraryeditor'); const dlg = dom.parentWithClass(this, 'dlg-libraryeditor');
libraryoptionseditor.setAdvancedVisible(dlg.querySelector('.libraryOptions'), this.checked); libraryoptionseditor.setAdvancedVisible(dlg.querySelector('.libraryOptions'), this.checked);
} }
@ -183,7 +200,7 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed
dlg.querySelector('.folderList').addEventListener('click', onListItemClick); dlg.querySelector('.folderList').addEventListener('click', onListItemClick);
dlg.querySelector('.chkAdvanced').addEventListener('change', onToggleAdvancedChange); dlg.querySelector('.chkAdvanced').addEventListener('change', onToggleAdvancedChange);
dlg.querySelector('.btnSubmit').addEventListener('click', onEditLibrary); dlg.querySelector('.btnSubmit').addEventListener('click', onEditLibrary);
libraryoptionseditor.embed(dlg.querySelector('.libraryOptions'), options.library.CollectionType, options.library.LibraryOptions).then(function () { libraryoptionseditor.embed(dlg.querySelector('.libraryOptions'), options.library.CollectionType, options.library.LibraryOptions).then(() => {
onToggleAdvancedChange.call(dlg.querySelector('.chkAdvanced')); onToggleAdvancedChange.call(dlg.querySelector('.chkAdvanced'));
}); });
} }
@ -192,18 +209,14 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed
currentDeferred.resolveWith(null, [hasChanges]); currentDeferred.resolveWith(null, [hasChanges]);
} }
function editor() { export class showEditor {
this.show = function (options) { constructor(options) {
var deferred = jQuery.Deferred(); const deferred = jQuery.Deferred();
currentOptions = options; currentOptions = options;
currentDeferred = deferred; currentDeferred = deferred;
hasChanges = false; hasChanges = false;
var xhr = new XMLHttpRequest(); import('text!./components/mediaLibraryEditor/mediaLibraryEditor.template.html').then(({default: template}) => {
xhr.open('GET', 'components/mediaLibraryEditor/mediaLibraryEditor.template.html', true); const dlg = dialogHelper.createDialog({
xhr.onload = function (e) {
var template = this.response;
var dlg = dialogHelper.createDialog({
size: 'small', size: 'small',
modal: false, modal: false,
removeOnClose: true, removeOnClose: true,
@ -213,25 +226,24 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed
dlg.classList.add('ui-body-a'); dlg.classList.add('ui-body-a');
dlg.classList.add('background-theme-a'); dlg.classList.add('background-theme-a');
dlg.classList.add('formDialog'); dlg.classList.add('formDialog');
dlg.innerHTML = globalize.translateDocument(template); dlg.innerHTML = globalize.translateHtml(template);
dlg.querySelector('.formDialogHeaderTitle').innerHTML = options.library.Name; dlg.querySelector('.formDialogHeaderTitle').innerHTML = options.library.Name;
initEditor(dlg, options); initEditor(dlg, options);
dlg.addEventListener('close', onDialogClosed); dlg.addEventListener('close', onDialogClosed);
dialogHelper.open(dlg); dialogHelper.open(dlg);
dlg.querySelector('.btnCancel').addEventListener('click', function () { dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg); dialogHelper.close(dlg);
}); });
refreshLibraryFromServer(dlg); refreshLibraryFromServer(dlg);
}; });
xhr.send();
return deferred.promise(); return deferred.promise();
};
} }
}
var currentDeferred; let currentDeferred;
var currentOptions; let currentOptions;
var hasChanges = false; let hasChanges = false;
var isCreating = false; let isCreating = false;
return editor;
}); /* eslint-enable indent */
export default showEditor;

View file

@ -18,8 +18,8 @@
<div class="folders hide"> <div class="folders hide">
<div style="display: flex; align-items: center;"> <div style="display: flex; align-items: center;">
<h1 style="margin: .5em 0;">${HeadersFolders}</h1> <h1 style="margin: .5em 0;">${Folders}</h1>
<button is="emby-button" type="button" class="fab btnAddFolder submit" style="margin-left:1em;" title="${ButtonAdd}"> <button is="emby-button" type="button" class="fab btnAddFolder submit" style="margin-left:1em;" title="${Add}">
<span class="material-icons add"></span> <span class="material-icons add"></span>
</button> </button>
</div> </div>

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