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

Merge remote-tracking branch 'upstream/master' into quickconnect

This commit is contained in:
Matt Montgomery 2020-07-26 16:41:26 -05:00
commit e5f0d77c30
401 changed files with 19558 additions and 12514 deletions

View file

@ -0,0 +1,63 @@
jobs:
- job: Build
displayName: 'Build'
strategy:
matrix:
Development:
BuildConfiguration: development
Production:
BuildConfiguration: production
Standalone:
BuildConfiguration: standalone
pool:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool@0
displayName: 'Install Node'
inputs:
versionSpec: '12.x'
- task: Cache@2
displayName: 'Check Cache'
inputs:
key: 'yarn | yarn.lock'
path: 'node_modules'
cacheHitVar: CACHE_RESTORED
- script: 'yarn install --frozen-lockfile'
displayName: 'Install Dependencies'
condition: ne(variables.CACHE_RESTORED, 'true')
- script: 'yarn build:development'
displayName: 'Build Development'
condition: eq(variables['BuildConfiguration'], 'development')
- script: 'yarn build:production'
displayName: 'Build Production'
condition: eq(variables['BuildConfiguration'], 'production')
- script: 'yarn build:standalone'
displayName: 'Build Standalone'
condition: eq(variables['BuildConfiguration'], 'standalone')
- script: 'test -d dist'
displayName: 'Check Build'
- script: 'mv dist jellyfin-web'
displayName: 'Rename Directory'
- task: ArchiveFiles@2
displayName: 'Archive Directory'
inputs:
rootFolderOrFile: 'jellyfin-web'
includeRootFolder: true
archiveFile: 'jellyfin-web-$(BuildConfiguration)'
- task: PublishPipelineArtifact@1
displayName: 'Publish Release'
inputs:
targetPath: '$(Build.SourcesDirectory)/jellyfin-web-$(BuildConfiguration).zip'
artifactName: 'jellyfin-web-$(BuildConfiguration)'

View file

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

View file

@ -0,0 +1,114 @@
jobs:
- job: BuildPackage
displayName: 'Build Packages'
strategy:
matrix:
CentOS:
BuildConfiguration: centos
Debian:
BuildConfiguration: debian
Fedora:
BuildConfiguration: fedora
Portable:
BuildConfiguration: portable
pool:
vmImage: 'ubuntu-latest'
steps:
- script: 'docker build -f deployment/Dockerfile.$(BuildConfiguration) -t jellyfin-web-$(BuildConfiguration) deployment'
displayName: 'Build Dockerfile'
condition: or(startsWith(variables['Build.SourceBranch'], 'refs/tags'), startsWith(variables['Build.SourceBranch'], 'refs/heads/master'))
- script: 'docker image ls -a && docker run -v $(pwd)/deployment/dist:/dist -v $(pwd):/jellyfin -e IS_UNSTABLE="yes" -e BUILD_ID=$(Build.BuildNumber) jellyfin-web-$(BuildConfiguration)'
displayName: 'Run Dockerfile (unstable)'
condition: startsWith(variables['Build.SourceBranch'], 'refs/heads/master')
- script: 'docker image ls -a && docker run -v $(pwd)/deployment/dist:/dist -v $(pwd):/jellyfin -e IS_UNSTABLE="no" -e BUILD_ID=$(Build.BuildNumber) jellyfin-web-$(BuildConfiguration)'
displayName: 'Run Dockerfile (stable)'
condition: startsWith(variables['Build.SourceBranch'], 'refs/tags')
- task: PublishPipelineArtifact@1
displayName: 'Publish Release'
condition: or(startsWith(variables['Build.SourceBranch'], 'refs/tags'), startsWith(variables['Build.SourceBranch'], 'refs/heads/master'))
inputs:
targetPath: '$(Build.SourcesDirectory)/deployment/dist'
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
displayName: 'Upload artifacts to repository server'
condition: or(startsWith(variables['Build.SourceBranch'], 'refs/tags'), startsWith(variables['Build.SourceBranch'], 'refs/heads/master'))
inputs:
sshEndpoint: repository
sourceFolder: '$(Build.SourcesDirectory)/deployment/dist'
contents: '**'
targetFolder: '/srv/repository/incoming/azure/$(Build.BuildNumber)/$(BuildConfiguration)'
- job: BuildDocker
displayName: 'Build Docker'
pool:
vmImage: 'ubuntu-latest'
steps:
- task: Docker@2
displayName: 'Push Unstable Image'
condition: startsWith(variables['Build.SourceBranch'], 'refs/heads/master')
inputs:
repository: 'jellyfin/jellyfin-web'
command: buildAndPush
buildContext: '.'
Dockerfile: 'deployment/Dockerfile.docker'
containerRegistry: Docker Hub
tags: |
unstable-$(Build.BuildNumber)
unstable
- task: Docker@2
displayName: 'Push Stable Image'
condition: startsWith(variables['Build.SourceBranch'], 'refs/tags')
inputs:
repository: 'jellyfin/jellyfin-web'
command: buildAndPush
buildContext: '.'
Dockerfile: 'deployment/Dockerfile.docker'
containerRegistry: Docker Hub
tags: |
stable-$(Build.BuildNumber)
stable
- job: CollectArtifacts
displayName: 'Collect Artifacts'
dependsOn:
- BuildPackage
- BuildDocker
condition: and(succeeded('BuildPackage'), succeeded('BuildDocker'))
pool:
vmImage: 'ubuntu-latest'
steps:
- task: SSH@0
displayName: 'Update Unstable Repository'
condition: startsWith(variables['Build.SourceBranch'], 'refs/heads/master')
inputs:
sshEndpoint: repository
runOptions: 'inline'
inline: 'sudo /srv/repository/collect-server.azure.sh /srv/repository/incoming/azure $(Build.BuildNumber) unstable'
- task: SSH@0
displayName: 'Update Stable Repository'
condition: startsWith(variables['Build.SourceBranch'], 'refs/tags')
inputs:
sshEndpoint: repository
runOptions: 'inline'
inline: 'sudo /srv/repository/collect-server.azure.sh /srv/repository/incoming/azure $(Build.BuildNumber)'

View file

@ -12,94 +12,6 @@ pr:
- '*'
jobs:
- job: Build
displayName: 'Build'
strategy:
matrix:
Development:
BuildConfiguration: development
Production:
BuildConfiguration: production
Standalone:
BuildConfiguration: standalone
pool:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool@0
displayName: 'Install Node'
inputs:
versionSpec: '12.x'
- task: Cache@2
displayName: 'Check Cache'
inputs:
key: 'yarn | yarn.lock'
path: 'node_modules'
cacheHitVar: CACHE_RESTORED
- script: 'yarn install --frozen-lockfile'
displayName: 'Install Dependencies'
condition: ne(variables.CACHE_RESTORED, 'true')
- script: 'yarn build:development'
displayName: 'Build Development'
condition: eq(variables['BuildConfiguration'], 'development')
- script: 'yarn build:production'
displayName: 'Build Bundle'
condition: eq(variables['BuildConfiguration'], 'production')
- script: 'yarn build:standalone'
displayName: 'Build Standalone'
condition: eq(variables['BuildConfiguration'], 'standalone')
- script: 'test -d dist'
displayName: 'Check Build'
- script: 'mv dist jellyfin-web'
displayName: 'Rename Directory'
- task: ArchiveFiles@2
displayName: 'Archive Directory'
inputs:
rootFolderOrFile: 'jellyfin-web'
includeRootFolder: true
archiveFile: 'jellyfin-web-$(BuildConfiguration)'
- task: PublishPipelineArtifact@1
displayName: 'Publish Release'
inputs:
targetPath: '$(Build.SourcesDirectory)/jellyfin-web-$(BuildConfiguration).zip'
artifactName: 'jellyfin-web-$(BuildConfiguration)'
- job: Lint
displayName: 'Lint'
pool:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool@0
displayName: 'Install Node'
inputs:
versionSpec: '12.x'
- task: Cache@2
displayName: 'Check Cache'
inputs:
key: 'yarn | yarn.lock'
path: 'node_modules'
cacheHitVar: CACHE_RESTORED
- script: 'yarn install --frozen-lockfile'
displayName: 'Install Dependencies'
condition: ne(variables.CACHE_RESTORED, 'true')
- script: 'yarn run lint --quiet'
displayName: 'Run ESLint'
- script: 'yarn run stylelint'
displayName: 'Run Stylelint'
- template: azure-pipelines-build.yml
- template: azure-pipelines-lint.yml
- template: azure-pipelines-package.yml

View file

@ -2,4 +2,4 @@ version: 1
update_configs:
- package_manager: "javascript"
directory: "/"
update_schedule: "weekly"
update_schedule: "live"

View file

@ -27,29 +27,30 @@ module.exports = {
'plugin:compat/recommended'
],
rules: {
'block-spacing': ["error"],
'brace-style': ["error"],
'comma-dangle': ["error", "never"],
'comma-spacing': ["error"],
'eol-last': ["error"],
'indent': ["error", 4, { "SwitchCase": 1 }],
'keyword-spacing': ["error"],
'max-statements-per-line': ["error"],
'no-floating-decimal': ["error"],
'no-multi-spaces': ["error"],
'no-multiple-empty-lines': ["error", { "max": 1 }],
'no-trailing-spaces': ["error"],
'one-var': ["error", "never"],
'quotes': ["error", "single", { "avoidEscape": true, "allowTemplateLiterals": false }],
'semi': ["error"],
'space-before-blocks': ["error"],
"space-infix-ops": "error"
'block-spacing': ['error'],
'brace-style': ['error'],
'comma-dangle': ['error', 'never'],
'comma-spacing': ['error'],
'eol-last': ['error'],
'indent': ['error', 4, { 'SwitchCase': 1 }],
'keyword-spacing': ['error'],
'max-statements-per-line': ['error'],
'no-floating-decimal': ['error'],
'no-multi-spaces': ['error'],
'no-multiple-empty-lines': ['error', { 'max': 1 }],
'no-trailing-spaces': ['error'],
'one-var': ['error', 'never'],
'quotes': ['error', 'single', { 'avoidEscape': true, 'allowTemplateLiterals': false }],
'semi': ['error'],
'space-before-blocks': ['error'],
'space-infix-ops': 'error'
},
overrides: [
{
files: [
'./src/**/*.js'
],
parser: 'babel-eslint',
env: {
node: false,
amd: true,
@ -97,11 +98,11 @@ module.exports = {
},
rules: {
// TODO: Fix warnings and remove these rules
'no-redeclare': ["warn"],
'no-unused-vars': ["warn"],
'no-useless-escape': ["warn"],
'no-redeclare': ['warn'],
'no-unused-vars': ['warn'],
'no-useless-escape': ['warn'],
// TODO: Remove after ES6 migration is complete
'import/no-unresolved': ["off"]
'import/no-unresolved': ['off']
},
settings: {
polyfills: [
@ -131,6 +132,7 @@ module.exports = {
'Object.getOwnPropertyDescriptor',
'Object.getPrototypeOf',
'Object.keys',
'Object.entries',
'Object.getOwnPropertyNames',
'Function.name',
'Function.hasInstance',
@ -191,4 +193,4 @@ module.exports = {
}
}
]
}
};

4
.github/CODEOWNERS vendored
View file

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

View file

@ -1,23 +1,20 @@
---
name: Bug report
about: Create a bug report
title: ''
name: Bug Report
about: You have noticed a general issue or regression, and would like to report it
labels: bug
assignees: ''
---
**Describe the bug**
**Describe The Bug**
<!-- A clear and concise description of what the bug is. -->
**To Reproduce**
**Steps To Reproduce**
<!-- Steps to reproduce the behavior: -->
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
**Expected Behavior**
<!-- A clear and concise description of what you expected to happen. -->
**Logs**
@ -27,9 +24,9 @@ assignees: ''
<!-- If applicable, add screenshots to help explain your problem. -->
**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]
- 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. -->

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.

5
.gitignore vendored
View file

@ -1,6 +1,3 @@
# config
config.json
# npm
dist
web
@ -10,5 +7,5 @@ node_modules
.idea
.vscode
#log
# log
yarn-error.log

View file

@ -1,7 +1,9 @@
FROM centos:7
# Docker build arguments
ARG SOURCE_DIR=/jellyfin
ARG ARTIFACT_DIR=/dist
# Docker run environment
ENV SOURCE_DIR=/jellyfin
ENV ARTIFACT_DIR=/dist
@ -18,10 +20,10 @@ RUN curl -fSsLo /etc/yum.repos.d/yarn.repo https://dl.yarnpkg.com/rpm/yarn.repo
&& yum install -y yarn
# Link to build script
RUN ln -sf ${SOURCE_DIR}/deployment/build.centos.all /build.sh
RUN ln -sf ${SOURCE_DIR}/deployment/build.centos /build.sh
VOLUME ${SOURCE_DIR}/
VOLUME ${SOURCE_DIR}
VOLUME ${ARTIFACT_DIR}/
VOLUME ${ARTIFACT_DIR}
ENTRYPOINT ["/build.sh"]

View file

@ -1,7 +1,9 @@
FROM debian:10
# Docker build arguments
ARG SOURCE_DIR=/jellyfin
ARG ARTIFACT_DIR=/dist
# Docker run environment
ENV SOURCE_DIR=/jellyfin
ENV ARTIFACT_DIR=/dist
@ -16,10 +18,10 @@ RUN apt-get update \
RUN npm install -g yarn
# Link to build script
RUN ln -sf ${SOURCE_DIR}/deployment/build.debian.all /build.sh
RUN ln -sf ${SOURCE_DIR}/deployment/build.debian /build.sh
VOLUME ${SOURCE_DIR}/
VOLUME ${SOURCE_DIR}
VOLUME ${ARTIFACT_DIR}/
VOLUME ${ARTIFACT_DIR}
ENTRYPOINT ["/build.sh"]

View file

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

View file

@ -1,7 +1,9 @@
FROM fedora:31
# Docker build arguments
ARG SOURCE_DIR=/jellyfin
ARG ARTIFACT_DIR=/dist
# Docker run environment
ENV SOURCE_DIR=/jellyfin
ENV ARTIFACT_DIR=/dist
@ -12,10 +14,10 @@ RUN dnf update -y \
&& dnf install -y @buildsys-build rpmdevtools git dnf-plugins-core nodejs-yarn autoconf automake glibc-devel
# Link to build script
RUN ln -sf ${SOURCE_DIR}/deployment/build.fedora.all /build.sh
RUN ln -sf ${SOURCE_DIR}/deployment/build.fedora /build.sh
VOLUME ${SOURCE_DIR}/
VOLUME ${SOURCE_DIR}
VOLUME ${ARTIFACT_DIR}/
VOLUME ${ARTIFACT_DIR}
ENTRYPOINT ["/build.sh"]

View file

@ -1,11 +1,12 @@
FROM debian:10
# Docker build arguments
ARG SOURCE_DIR=/jellyfin
ARG ARTIFACT_DIR=/dist
# Docker run environment
ENV SOURCE_DIR=/jellyfin
ENV ARTIFACT_DIR=/dist
ENV DEB_BUILD_OPTIONS=noddebs
ENV IS_DOCKER=YES
# Prepare Debian build environment
@ -18,8 +19,8 @@ RUN npm install -g yarn
# Link to build script
RUN ln -sf ${SOURCE_DIR}/deployment/build.portable /build.sh
VOLUME ${SOURCE_DIR}/
VOLUME ${SOURCE_DIR}
VOLUME ${ARTIFACT_DIR}/
VOLUME ${ARTIFACT_DIR}
ENTRYPOINT ["/build.sh"]

41
deployment/build.centos Executable file
View file

@ -0,0 +1,41 @@
#!/bin/bash
set -o errexit
set -o xtrace
# move to source directory
pushd ${SOURCE_DIR}
cp -a yarn.lock /tmp/yarn.lock
# modify changelog to unstable configuration if IS_UNSTABLE
if [[ ${IS_UNSTABLE} == 'yes' ]]; then
pushd fedora
PR_ID=$( git log --grep 'Merge pull request' --oneline --single-worktree --first-parent | head -1 | grep --color=none -Eo '#[0-9]+' | tr -d '#' )
sed -i "s/Version:.*/Version: ${BUILD_ID}/" jellyfin-web.spec
sed -i "/%changelog/q" jellyfin-web.spec
cat <<EOF >>jellyfin-web.spec
* $( LANG=C date '+%a %b %d %Y' ) Jellyfin Packaging Team <packaging@jellyfin.org>
- Jellyfin Web unstable build ${BUILD_ID} for merged PR #${PR_ID}
EOF
popd
fi
# build rpm
make -f fedora/Makefile srpm outdir=/root/rpmbuild/SRPMS
rpmbuild --rebuild -bb /root/rpmbuild/SRPMS/jellyfin-*.src.rpm
# move the artifacts
mv /root/rpmbuild/RPMS/noarch/jellyfin-*.rpm /root/rpmbuild/SRPMS/jellyfin-*.src.rpm ${ARTIFACT_DIR}/
if [[ ${IS_DOCKER} == YES ]]; then
chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
fi
rm -f fedora/jellyfin*.tar.gz
cp -a /tmp/yarn.lock yarn.lock
popd

View file

@ -1,27 +0,0 @@
#!/bin/bash
#= CentOS 7 all .rpm
set -o errexit
set -o xtrace
# Move to source directory
pushd ${SOURCE_DIR}
cp -a yarn.lock /tmp/yarn.lock
# Build RPM
make -f fedora/Makefile srpm outdir=/root/rpmbuild/SRPMS
rpmbuild --rebuild -bb /root/rpmbuild/SRPMS/jellyfin-*.src.rpm
# Move the artifacts out
mv /root/rpmbuild/RPMS/noarch/jellyfin-*.rpm /root/rpmbuild/SRPMS/jellyfin-*.src.rpm ${ARTIFACT_DIR}/
if [[ ${IS_DOCKER} == YES ]]; then
chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
fi
rm -f fedora/jellyfin*.tar.gz
cp -a /tmp/yarn.lock yarn.lock
popd

39
deployment/build.debian Executable file
View file

@ -0,0 +1,39 @@
#!/bin/bash
set -o errexit
set -o xtrace
# move to source directory
pushd ${SOURCE_DIR}
cp -a yarn.lock /tmp/yarn.lock
# modify changelog to unstable configuration if IS_UNSTABLE
if [[ ${IS_UNSTABLE} == 'yes' ]]; then
pushd debian
PR_ID=$( git log --grep 'Merge pull request' --oneline --single-worktree --first-parent | head -1 | grep --color=none -Eo '#[0-9]+' | tr -d '#' )
cat <<EOF >changelog
jellyfin-web (${BUILD_ID}-unstable) unstable; urgency=medium
* Jellyfin Web unstable build ${BUILD_ID} for merged PR #${PR_ID}
-- Jellyfin Packaging Team <packaging@jellyfin.org> $( date --rfc-2822 )
EOF
popd
fi
# build deb
dpkg-buildpackage -us -uc --pre-clean --post-clean
mkdir -p ${ARTIFACT_DIR}
mv ../jellyfin*.{deb,dsc,tar.gz,buildinfo,changes} ${ARTIFACT_DIR}
cp -a /tmp/yarn.lock yarn.lock
if [[ ${IS_DOCKER} == YES ]]; then
chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
fi
popd

View file

@ -1,25 +0,0 @@
#!/bin/bash
#= Debian/Ubuntu all .deb
set -o errexit
set -o xtrace
# Move to source directory
pushd ${SOURCE_DIR}
cp -a yarn.lock /tmp/yarn.lock
# Build DEB
dpkg-buildpackage -us -uc --pre-clean --post-clean
mkdir -p ${ARTIFACT_DIR}/
mv ../jellyfin*.{deb,dsc,tar.gz,buildinfo,changes} ${ARTIFACT_DIR}/
cp -a /tmp/yarn.lock yarn.lock
if [[ ${IS_DOCKER} == YES ]]; then
chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
fi
popd

41
deployment/build.fedora Executable file
View file

@ -0,0 +1,41 @@
#!/bin/bash
set -o errexit
set -o xtrace
# move to source directory
pushd ${SOURCE_DIR}
cp -a yarn.lock /tmp/yarn.lock
# modify changelog to unstable configuration if IS_UNSTABLE
if [[ ${IS_UNSTABLE} == 'yes' ]]; then
pushd fedora
PR_ID=$( git log --grep 'Merge pull request' --oneline --single-worktree --first-parent | head -1 | grep --color=none -Eo '#[0-9]+' | tr -d '#' )
sed -i "s/Version:.*/Version: ${BUILD_ID}/" jellyfin-web.spec
sed -i "/%changelog/q" jellyfin-web.spec
cat <<EOF >>jellyfin-web.spec
* $( LANG=C date '+%a %b %d %Y' ) Jellyfin Packaging Team <packaging@jellyfin.org>
- Jellyfin Web unstable build ${BUILD_ID} for merged PR #${PR_ID}
EOF
popd
fi
# build rpm
make -f fedora/Makefile srpm outdir=/root/rpmbuild/SRPMS
rpmbuild -rb /root/rpmbuild/SRPMS/jellyfin-*.src.rpm
# move the artifacts
mv /root/rpmbuild/RPMS/noarch/jellyfin-*.rpm /root/rpmbuild/SRPMS/jellyfin-*.src.rpm ${ARTIFACT_DIR}
if [[ ${IS_DOCKER} == YES ]]; then
chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
fi
rm -f fedora/jellyfin*.tar.gz
cp -a /tmp/yarn.lock yarn.lock
popd

View file

@ -1,27 +0,0 @@
#!/bin/bash
#= Fedora 29+ all .rpm
set -o errexit
set -o xtrace
# Move to source directory
pushd ${SOURCE_DIR}
cp -a yarn.lock /tmp/yarn.lock
# Build RPM
make -f fedora/Makefile srpm outdir=/root/rpmbuild/SRPMS
rpmbuild -rb /root/rpmbuild/SRPMS/jellyfin-*.src.rpm
# Move the artifacts out
mv /root/rpmbuild/RPMS/noarch/jellyfin-*.rpm /root/rpmbuild/SRPMS/jellyfin-*.src.rpm ${ARTIFACT_DIR}/
if [[ ${IS_DOCKER} == YES ]]; then
chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
fi
rm -f fedora/jellyfin*.tar.gz
cp -a /tmp/yarn.lock yarn.lock
popd

View file

@ -1,25 +1,27 @@
#!/bin/bash
#= Portable .NET DLL .tar.gz
set -o errexit
set -o xtrace
# Move to source directory
# move to source directory
pushd ${SOURCE_DIR}
# Get version
version="$( grep "version:" ./build.yaml | sed -E 's/version: "([0-9\.]+.*)"/\1/' )"
# get version
if [[ ${IS_UNSTABLE} == 'yes' ]]; then
version="${BUILD_ID}"
else
version="$( grep "version:" ./build.yaml | sed -E 's/version: "([0-9\.]+.*)"/\1/' )"
fi
# Build archives
# build archives
npx yarn install
mv dist/ jellyfin-web_${version}
mv dist jellyfin-web_${version}
tar -czf jellyfin-web_${version}_portable.tar.gz jellyfin-web_${version}
rm -rf dist/
rm -rf dist
# Move the artifacts out
mkdir -p ${ARTIFACT_DIR}/
mv jellyfin[-_]*.tar.gz ${ARTIFACT_DIR}/
# move the artifacts
mkdir -p ${ARTIFACT_DIR}
mv jellyfin[-_]*.tar.gz ${ARTIFACT_DIR}
if [[ ${IS_DOCKER} == YES ]]; then
chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}

View file

@ -12,7 +12,7 @@ Source0: jellyfin-web-%{version}.tar.gz
%if 0%{?centos}
BuildRequires: yarn
%else
BuildRequires nodejs-yarn
BuildRequires: nodejs-yarn
%endif
BuildArch: noarch

View file

@ -181,16 +181,15 @@ function copy(query) {
.pipe(browserSync.stream());
}
function copyIndex() {
return src(options.injectBundle.query, { base: './src/' })
.pipe(dest('dist/'))
.pipe(browserSync.stream());
}
function injectBundle() {
return src(options.injectBundle.query, { base: './src/' })
.pipe(inject(
src(['src/scripts/apploader.js'], { read: false }, { base: './src/' }), { relative: true }
src(['src/scripts/apploader.js'], { read: false }, { base: './src/' }), {
relative: true,
transform: function (filepath) {
return `<script src="${filepath}" defer></script>`;
}
}
))
.pipe(dest('dist/'))
.pipe(browserSync.stream());
@ -200,6 +199,6 @@ function build(standalone) {
return series(clean, parallel(javascript, apploader(standalone), webpack, css, html, images, copy));
}
exports.default = series(build(false), copyIndex);
exports.default = series(build(false), injectBundle);
exports.standalone = series(build(true), injectBundle);
exports.serve = series(exports.standalone, serve);

View file

@ -5,27 +5,29 @@
"repository": "https://github.com/jellyfin/jellyfin-web",
"license": "GPL-2.0-or-later",
"devDependencies": {
"@babel/core": "^7.9.6",
"@babel/plugin-transform-modules-amd": "^7.9.6",
"@babel/core": "^7.10.5",
"@babel/plugin-proposal-class-properties": "^7.10.1",
"@babel/plugin-proposal-private-methods": "^7.10.1",
"@babel/plugin-transform-modules-amd": "^7.10.5",
"@babel/polyfill": "^7.8.7",
"@babel/preset-env": "^7.8.6",
"autoprefixer": "^9.8.0",
"@babel/preset-env": "^7.10.3",
"autoprefixer": "^9.8.5",
"babel-eslint": "^11.0.0-beta.2",
"babel-loader": "^8.0.6",
"browser-sync": "^2.26.7",
"clean-webpack-plugin": "^3.0.0",
"browser-sync": "^2.26.10",
"copy-webpack-plugin": "^5.1.1",
"css-loader": "^3.4.2",
"css-loader": "^4.0.0",
"cssnano": "^4.1.10",
"del": "^5.1.0",
"eslint": "^6.8.0",
"eslint-plugin-compat": "^3.5.1",
"eslint-plugin-eslint-comments": "^3.1.2",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-import": "^2.21.2",
"eslint-plugin-promise": "^4.2.1",
"file-loader": "^6.0.0",
"gulp": "^4.0.2",
"gulp-babel": "^8.0.0",
"gulp-cli": "^2.2.1",
"gulp-cli": "^2.3.0",
"gulp-concat": "^2.6.1",
"gulp-htmlmin": "^5.0.1",
"gulp-if": "^3.0.0",
@ -35,52 +37,50 @@
"gulp-postcss": "^8.0.0",
"gulp-sass": "^4.0.2",
"gulp-sourcemaps": "^2.6.5",
"gulp-terser": "^1.2.0",
"gulp-terser": "^1.2.1",
"html-webpack-plugin": "^4.3.0",
"lazypipe": "^1.0.2",
"node-sass": "^4.13.1",
"postcss-loader": "^3.0.0",
"postcss-preset-env": "^6.7.0",
"style-loader": "^1.1.3",
"stylelint": "^13.5.0",
"stylelint": "^13.6.1",
"stylelint-config-rational-order": "^0.1.2",
"stylelint-no-browser-hacks": "^1.2.1",
"stylelint-order": "^4.0.0",
"webpack": "^4.41.5",
"webpack-cli": "^3.3.10",
"webpack-concat-plugin": "^3.0.0",
"webpack-dev-server": "^3.11.0",
"stylelint-order": "^4.1.0",
"webpack": "^4.44.0",
"webpack-merge": "^4.2.2",
"webpack-stream": "^5.2.1"
},
"dependencies": {
"alameda": "^1.4.0",
"blurhash": "^1.1.3",
"classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz",
"core-js": "^3.6.5",
"date-fns": "^2.14.0",
"document-register-element": "^1.14.3",
"fast-text-encoding": "^1.0.1",
"date-fns": "^2.15.0",
"epubjs": "^0.3.85",
"fast-text-encoding": "^1.0.3",
"flv.js": "^1.5.0",
"headroom.js": "^0.11.0",
"hls.js": "^0.13.1",
"hls.js": "^0.14.5",
"howler": "^2.2.0",
"intersection-observer": "^0.10.0",
"jellyfin-apiclient": "^1.2.0",
"intersection-observer": "^0.11.0",
"jellyfin-apiclient": "^1.4.1",
"jellyfin-noto": "https://github.com/jellyfin/jellyfin-noto",
"jquery": "^3.5.1",
"jstree": "^3.3.7",
"jstree": "^3.3.10",
"libass-wasm": "https://github.com/jellyfin/JavascriptSubtitlesOctopus#4.0.0-jf-smarttv",
"material-design-icons-iconfont": "^5.0.1",
"native-promise-only": "^0.8.0-a",
"page": "^1.11.6",
"query-string": "^6.11.1",
"query-string": "^6.13.1",
"resize-observer-polyfill": "^1.5.1",
"screenfull": "^5.0.2",
"shaka-player": "^2.5.11",
"shaka-player": "^2.5.13",
"sortablejs": "^1.10.2",
"swiper": "^5.4.1",
"swiper": "^5.4.5",
"webcomponents.js": "^0.7.24",
"whatwg-fetch": "^3.0.0"
"whatwg-fetch": "^3.2.0"
},
"babel": {
"presets": [
@ -89,34 +89,178 @@
"overrides": [
{
"test": [
"src/components/accessSchedule/accessSchedule.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/autoFocuser.js",
"src/components/backdrop/backdrop.js",
"src/components/cardbuilder/cardBuilder.js",
"src/scripts/fileDownloader.js",
"src/components/cardbuilder/chaptercardbuilder.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/fetchhelper.js",
"src/components/filterdialog/filterdialog.js",
"src/components/groupedcards.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/imageUploader/imageUploader.js",
"src/components/indicators/indicators.js",
"src/components/itemContextMenu.js",
"src/components/itemidentifier/itemidentifier.js",
"src/components/itemMediaInfo/itemMediaInfo.js",
"src/components/lazyLoader/lazyLoaderIntersectionObserver.js",
"src/components/libraryoptionseditor/libraryoptionseditor.js",
"src/components/listview/listview.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/nowPlayingBar/nowPlayingBar.js",
"src/components/playback/brightnessosd.js",
"src/components/playback/mediasession.js",
"src/components/playback/nowplayinghelper.js",
"src/components/playback/playbackorientation.js",
"src/components/playback/playerSelectionMenu.js",
"src/components/playback/playersettingsmenu.js",
"src/components/playback/playmethodhelper.js",
"src/components/playback/remotecontrolautoplay.js",
"src/components/playback/volumeosd.js",
"src/components/playbackSettings/playbackSettings.js",
"src/components/playerstats/playerstats.js",
"src/components/playlisteditor/playlisteditor.js",
"src/components/playmenu.js",
"src/components/prompt/prompt.js",
"src/components/sanatizefilename.js",
"src/components/scrollManager.js",
"src/components/syncplay/playbackPermissionManager.js",
"src/components/syncplay/groupSelectionMenu.js",
"src/components/syncplay/timeSyncManager.js",
"src/components/syncplay/syncPlayManager.js",
"src/components/search/searchfields.js",
"src/components/search/searchresults.js",
"src/components/settingshelper.js",
"src/components/shortcuts.js",
"src/components/subtitlesettings/subtitleappearancehelper.js",
"src/components/subtitlesettings/subtitlesettings.js",
"src/components/syncPlay/groupSelectionMenu.js",
"src/components/syncPlay/playbackPermissionManager.js",
"src/components/syncPlay/syncPlayManager.js",
"src/components/syncPlay/timeSyncManager.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/sessopm/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/mediaLibrary.js",
"src/controllers/dashboard/metadataImages.js",
"src/controllers/dashboard/metadatanfo.js",
"src/controllers/dashboard/networking.js",
"src/controllers/dashboard/playback.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/playback/queue/index.js",
"src/controllers/playback/video/index.js",
"src/controllers/searchpage.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/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/plugins/backdropScreensaver/plugin.js",
"src/plugins/bookPlayer/plugin.js",
"src/plugins/bookPlayer/tableOfContents.js",
"src/plugins/photoPlayer/plugin.js",
"src/plugins/youtubePlayer/plugin.js",
"src/scripts/alphanumericshortcuts.js",
"src/scripts/autoBackdrops.js",
"src/scripts/datetime.js",
"src/scripts/deleteHelper.js",
"src/scripts/dfnshelper.js",
"src/scripts/dom.js",
"src/scripts/editorsidebar.js",
"src/scripts/fileDownloader.js",
"src/scripts/filesystem.js",
"src/scripts/globalize.js",
"src/scripts/imagehelper.js",
"src/scripts/inputManager.js",
"src/scripts/deleteHelper.js",
"src/components/actionSheet/actionSheet.js",
"src/components/playmenu.js",
"src/components/indicators/indicators.js",
"src/scripts/keyboardNavigation.js",
"src/scripts/playlists.js",
"src/scripts/settings/appSettings.js",
"src/scripts/settings/userSettings.js",
"src/scripts/settings/webSettings.js"
"src/scripts/settings/webSettings.js",
"src/scripts/taskbutton.js",
"src/scripts/themeLoader.js",
"src/scripts/touchHelper.js"
],
"plugins": [
"@babel/plugin-transform-modules-amd"
"@babel/plugin-transform-modules-amd",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-private-methods"
]
}
]

View file

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

View file

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

View file

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

View file

@ -24,10 +24,6 @@
padding-top: 7em !important;
}
.layout-mobile .libraryPage {
padding-top: 4em !important;
}
.itemDetailPage {
padding-top: 0 !important;
}
@ -164,6 +160,7 @@
display: flex;
flex-direction: column;
contain: layout style paint;
transition: background ease-in-out 0.5s;
}
.hiddenViewMenuBar .skinHeader {
@ -178,6 +175,10 @@
width: 100%;
}
.layout-tv .sectionTabs {
width: 55%;
}
.selectedMediaFolder {
background-color: #f2f2f2 !important;
}
@ -272,7 +273,7 @@
}
}
@media all and (max-width: 84em) {
@media all and (max-width: 100em) {
.withSectionTabs .headerTop {
padding-bottom: 0.55em;
}
@ -280,9 +281,13 @@
.sectionTabs {
font-size: 83.5%;
}
.layout-tv .sectionTabs {
width: 100%;
}
}
@media all and (min-width: 84em) {
@media all and (min-width: 100em) {
.headerTop {
padding: 0.8em 0.8em;
}
@ -438,12 +443,14 @@
background-repeat: no-repeat;
background-position: center;
background-attachment: fixed;
height: 50vh;
height: 40vh;
position: relative;
animation: backdrop-fadein 800ms ease-in normal both;
}
.layout-mobile .itemBackdrop {
background-attachment: scroll;
height: 26.5vh;
}
.layout-desktop .itemBackdrop::after,
@ -463,10 +470,20 @@
.detailPageContent {
display: flex;
flex-direction: column;
padding-left: 2%;
padding-left: 32.45vw;
padding-right: 2%;
}
.layout-mobile .detailPageContent {
padding-left: 5%;
padding-right: 5%;
}
.layout-desktop .detailPageContent .emby-scroller,
.layout-tv .detailPageContent .emby-scroller {
margin-left: 0;
}
.layout-desktop .noBackdrop .detailPageContent,
.layout-tv .noBackdrop .detailPageContent {
margin-top: 2.5em;
@ -477,6 +494,10 @@
margin-top: 0;
}
.detailSectionContent a {
color: inherit;
}
.personBackdrop {
background-size: contain;
}
@ -495,7 +516,23 @@
.parentName {
display: block;
margin-bottom: 0.5em;
margin: 0 0 0;
}
.layout-mobile .parentName {
margin: 0.6em 0 0;
}
.musicParentName {
margin: 0.15em 0 0.2em;
}
.layout-mobile .musicParentName {
margin: -0.25em 0 0.25em;
}
.layout-mobile .itemExternalLinks {
display: none;
}
.mainDetailButtons {
@ -503,8 +540,6 @@
-webkit-box-align: center;
-webkit-align-items: center;
align-items: center;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
margin: 1em 0;
}
@ -520,6 +555,35 @@
font-weight: 600;
}
.itemName.originalTitle {
margin: 0.2em 0 0.2em;
}
.itemName.parentNameLast {
margin: 0 0 0;
}
.layout-mobile .itemName.parentNameLast {
margin: 0.4em 0 0.4em;
}
.layout-mobile h1.itemName,
.layout-mobile h1.parentName {
font-size: 1.6em;
}
.itemName.parentNameLast.withOriginalTitle {
margin: 0 0 0;
}
.layout-mobile .itemName.parentNameLast.withOriginalTitle {
margin: 0.6em 0 0;
}
.layout-mobile .itemName.originalTitle {
margin: 0.5em 0 0.5em;
}
.nameContainer {
display: flex;
flex-direction: column;
@ -546,6 +610,19 @@
text-align: center;
}
.layout-mobile .mainDetailButtons {
margin-top: 1em;
margin-bottom: 0.5em;
}
.subtitle {
margin: 0.15em 0 0.2em;
}
.layout-mobile .subtitle {
margin: 0.2em 0 0.2em;
}
.detailPagePrimaryContainer {
display: flex;
align-items: center;
@ -556,7 +633,7 @@
.layout-mobile .detailPagePrimaryContainer {
display: block;
position: relative;
top: 0;
padding: 0.5em 3.3% 0.5em;
}
.layout-tv #itemDetailPage:not(.noBackdrop) .detailPagePrimaryContainer,
@ -566,13 +643,14 @@
padding-left: 32.45vw;
}
.layout-desktop .detailSticky,
.layout-tv .detailSticky {
.layout-desktop .detailRibbon,
.layout-tv .detailRibbon {
margin-top: -7.2em;
height: 7.18em;
}
.layout-desktop .noBackdrop .detailSticky,
.layout-tv .noBackdrop .detailSticky {
.layout-desktop .noBackdrop .detailRibbon,
.layout-tv .noBackdrop .detailRibbon {
margin-top: 0;
}
@ -584,6 +662,9 @@
white-space: nowrap;
text-overflow: ellipsis;
text-align: left;
min-width: 0;
max-width: 100%;
overflow: hidden;
}
.layout-mobile .infoText {
@ -594,12 +675,29 @@
margin: 1.25em 0;
}
.detailImageContainer {
position: relative;
margin-top: -25vh;
.layout-mobile .detailPageSecondaryContainer {
margin: 1em 0;
}
.layout-mobile .detailImageContainer {
display: none;
}
.detailImageContainer .card {
position: absolute;
top: 50%;
float: left;
width: 25vw;
z-index: 3;
transform: translateY(-50%);
}
.detailImageContainer .card.backdropCard {
top: 35%;
}
.detailImageContainer .card.squareCard {
top: 40%;
}
.layout-desktop .noBackdrop .detailImageContainer,
@ -612,11 +710,11 @@
}
.detailLogo {
width: 30vw;
height: 25vh;
width: 25vw;
height: 16vh;
position: absolute;
top: 10vh;
right: 20vw;
right: 25vw;
background-size: contain;
}
@ -641,7 +739,8 @@ div.itemDetailGalleryLink.defaultCardBackground {
}
.itemDetailGalleryLink.defaultCardBackground {
height: 23vw; /* Dirty hack to get it to look somewhat square. Less than ideal. */
/* Dirty hack to get it to look somewhat square. Less than ideal. */
height: 23vw;
}
.itemDetailGalleryLink.defaultCardBackground > .material-icons {
@ -655,14 +754,19 @@ div.itemDetailGalleryLink.defaultCardBackground {
position: relative;
}
.layout-desktop .detailPageWrapperContainer,
.layout-tv .detailPageWrapperContainer {
margin-top: 7.2em;
.layout-desktop .itemBackdrop,
.layout-tv .itemBackdrop {
height: 40vh;
}
.layout-tv #itemDetailPage:not(.noBackdrop) .detailPagePrimaryContainer,
.layout-desktop #itemDetailPage:not(.noBackdrop) .detailPagePrimaryContainer {
padding-left: 3.3%;
.layout-desktop .detailPageWrapperContainer,
.layout-tv .detailPageWrapperContainer {
margin-top: 0.1em;
}
.layout-desktop .detailImageContainer .card,
.layout-tv .detailImageContainer .card {
top: 10%;
}
.btnPlaySimple {
@ -678,12 +782,12 @@ div.itemDetailGalleryLink.defaultCardBackground {
.emby-button.detailFloatingButton {
position: absolute;
background-color: rgba(0, 0, 0, 0.5) !important;
z-index: 1;
top: 50%;
left: 50%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 3;
top: 100%;
left: 90%;
margin: -2.2em 0 0 -2.2em;
padding: 0.4em !important;
padding: 0.4em;
color: rgba(255, 255, 255, 0.76);
}
@ -693,16 +797,12 @@ div.itemDetailGalleryLink.defaultCardBackground {
@media all and (max-width: 62.5em) {
.parentName {
margin-bottom: 1em;
margin-bottom: 0;
}
.itemDetailPage {
padding-top: 0 !important;
}
.detailimg-hidemobile {
display: none;
}
}
@media all and (min-width: 31.25em) {
@ -797,9 +897,9 @@ div.itemDetailGalleryLink.defaultCardBackground {
}
.detailImageProgressContainer {
position: absolute;
bottom: 0;
width: 22.786458333333332vw;
margin-top: -0.4vw;
width: 100%;
}
.detailButton-text {
@ -818,21 +918,7 @@ div.itemDetailGalleryLink.defaultCardBackground {
}
}
@media all and (min-width: 62.5em) {
.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;
}
@media all and (min-width: 100em) {
.detailFloatingButton {
display: none !important;
}
@ -866,6 +952,10 @@ div.itemDetailGalleryLink.defaultCardBackground {
}
}
.detailVerticalSection .emby-scrollbuttons {
padding-top: 0.4em;
}
.layout-tv .detailVerticalSection {
margin-bottom: 3.4em !important;
}
@ -954,6 +1044,10 @@ div.itemDetailGalleryLink.defaultCardBackground {
margin-bottom: 2.7em;
}
.layout-mobile .verticalSection-extrabottompadding {
margin-bottom: 1em;
}
.sectionTitleButton,
.sectionTitleIconButton {
margin-right: 0 !important;
@ -979,7 +1073,13 @@ div.itemDetailGalleryLink.defaultCardBackground {
div:not(.sectionTitleContainer-cards) > .sectionTitle-cards {
margin: 0;
padding-top: 1.25em;
padding-top: 0.5em;
padding-bottom: 0.2em;
}
.layout-mobile :not(.sectionTitleContainer-cards) > .sectionTitle-cards {
margin: 0;
padding-top: 0.5em;
}
.sectionTitleButton {
@ -1132,6 +1232,12 @@ div:not(.sectionTitleContainer-cards) > .sectionTitle-cards {
.trackSelections .selectContainer .selectLabel {
margin: 0 0.2em 0 0;
line-height: 1.75;
}
.layout-mobile .detailsGroupItem .label,
.layout-mobile .trackSelections .selectContainer .selectLabel {
flex-basis: 4.5em;
}
.trackSelections .selectContainer .detailTrackSelect {
@ -1144,3 +1250,21 @@ div:not(.sectionTitleContainer-cards) > .sectionTitle-cards {
margin-top: 0;
font-size: 1.4em;
}
.overview-controls {
display: flex;
justify-content: flex-end;
}
.detail-clamp-text {
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 12;
-webkit-box-orient: vertical;
}
@media all and (min-width: 40em) {
.detail-clamp-text {
-webkit-line-clamp: 6;
}
}

View file

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

View file

@ -5,6 +5,12 @@ html {
height: 100%;
}
.layout-mobile,
.layout-tv {
-webkit-touch-callout: none;
user-select: none;
}
.clipForScreenReader {
clip: rect(1px, 1px, 1px, 1px);
clip-path: inset(50%);
@ -18,7 +24,7 @@ html {
.material-icons {
/* Fix font ligatures on older WebOS versions */
-webkit-font-feature-settings: "liga";
font-feature-settings: "liga";
}
.backgroundContainer {
@ -34,16 +40,6 @@ html {
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 {
overflow-x: hidden;
background-color: transparent !important;
@ -121,6 +117,11 @@ div[data-role=page] {
transform: translateY(-100%);
}
.drawerContent {
/* make sure the bottom of the drawer is visible when music is playing */
padding-bottom: 4em;
}
.force-scroll {
overflow-y: scroll;
}
@ -128,3 +129,17 @@ div[data-role=page] {
.hide-scroll {
overflow-y: hidden;
}
.w-100 {
width: 100%;
}
.margin-auto-x {
margin-left: auto;
margin-right: auto;
}
.margin-auto-y {
margin-top: auto;
margin-bottom: auto;
}

View file

@ -4,18 +4,18 @@
// Use define from require.js not webpack's define
var _define = window.define;
// document-register-element
var docRegister = require('document-register-element');
_define('document-register-element', function() {
return docRegister;
});
// fetch
var fetch = require('whatwg-fetch');
_define('fetch', function() {
return fetch;
});
// Blurhash
var blurhash = require('blurhash');
_define('blurhash', function() {
return blurhash;
});
// query-string
var query = require('query-string');
_define('queryString', function() {
@ -59,12 +59,6 @@ _define('resize-observer-polyfill', function() {
return resize;
});
// shaka
var shaka = require('shaka-player');
_define('shaka', function() {
return shaka;
});
// swiper
var swiper = require('swiper/js/swiper');
require('swiper/css/swiper.min.css');
@ -84,6 +78,12 @@ _define('webcomponents', function() {
return webcomponents;
});
// shaka
var shaka = require('shaka-player');
_define('shaka', function() {
return shaka;
});
// libass-wasm
var libassWasm = require('libass-wasm');
_define('JavascriptSubtitlesOctopus', function() {
@ -102,6 +102,11 @@ _define('jellyfin-noto', function () {
return noto;
});
var epubjs = require('epubjs');
_define('epubjs', function () {
return epubjs;
});
// page.js
var page = require('page');
_define('page', function() {

View file

@ -1,9 +1,20 @@
define(['dialogHelper', 'datetime', 'globalize', 'emby-select', 'paper-icon-button-light', 'formDialogStyle'], function (dialogHelper, datetime, globalize) {
'use strict';
/* eslint-disable indent */
/**
* Module for controlling user parental control from.
* @module components/accessSchedule/accessSchedule
*/
import dialogHelper from 'dialogHelper';
import datetime from 'datetime';
import globalize from 'globalize';
import 'emby-select';
import 'paper-icon-button-light';
import 'formDialogStyle';
function getDisplayTime(hours) {
var minutes = 0;
var pct = hours % 1;
let minutes = 0;
const pct = hours % 1;
if (pct) {
minutes = parseInt(60 * pct);
@ -13,25 +24,25 @@ define(['dialogHelper', 'datetime', 'globalize', 'emby-select', 'paper-icon-butt
}
function populateHours(context) {
var html = '';
let html = '';
for (var i = 0; i < 24; i++) {
html += '<option value="' + i + '">' + getDisplayTime(i) + '</option>';
for (let i = 0; i < 24; i++) {
html += `<option value="${i}">${getDisplayTime(i)}</option>`;
}
html += '<option value="24">' + getDisplayTime(0) + '</option>';
html += `<option value="24">${getDisplayTime(0)}</option>`;
context.querySelector('#selectStart').innerHTML = html;
context.querySelector('#selectEnd').innerHTML = html;
}
function loadSchedule(context, schedule) {
context.querySelector('#selectDay').value = schedule.DayOfWeek || 'Sunday';
context.querySelector('#selectStart').value = schedule.StartHour || 0;
context.querySelector('#selectEnd').value = schedule.EndHour || 0;
function loadSchedule(context, {DayOfWeek, StartHour, EndHour}) {
context.querySelector('#selectDay').value = DayOfWeek || 'Sunday';
context.querySelector('#selectStart').value = StartHour || 0;
context.querySelector('#selectEnd').value = EndHour || 0;
}
function submitSchedule(context, options) {
var updatedSchedule = {
const updatedSchedule = {
DayOfWeek: context.querySelector('#selectDay').value,
StartHour: context.querySelector('#selectStart').value,
EndHour: context.querySelector('#selectEnd').value
@ -46,44 +57,41 @@ define(['dialogHelper', 'datetime', 'globalize', 'emby-select', 'paper-icon-butt
dialogHelper.close(context);
}
return {
show: function (options) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'components/accessSchedule/accessSchedule.template.html', true);
xhr.onload = function (e) {
var template = this.response;
var dlg = dialogHelper.createDialog({
export function show(options) {
return new Promise((resolve, reject) => {
import('text!./accessSchedule.template.html').then(({default: template}) => {
const dlg = dialogHelper.createDialog({
removeOnClose: true,
size: 'small'
});
dlg.classList.add('formDialog');
var html = '';
html += globalize.translateDocument(template);
let html = '';
html += globalize.translateHtml(template);
dlg.innerHTML = html;
populateHours(dlg);
loadSchedule(dlg, options.schedule);
dialogHelper.open(dlg);
dlg.addEventListener('close', function () {
dlg.addEventListener('close', () => {
if (dlg.submitted) {
resolve(options.schedule);
} else {
reject();
}
});
dlg.querySelector('.btnCancel').addEventListener('click', function (e) {
dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg);
});
dlg.querySelector('form').addEventListener('submit', function (e) {
dlg.querySelector('form').addEventListener('submit', event => {
submitSchedule(dlg, options);
e.preventDefault();
event.preventDefault();
return false;
});
};
xhr.send();
});
});
}
};
});
/* eslint-enable indent */
export default {
show: show
};

View file

@ -16,15 +16,8 @@ function getOffsets(elems) {
return results;
}
let box;
for (let elem of elems) {
// Support: BlackBerry 5, iOS 3 (original iPhone)
// If we don't have gBCR, just use 0,0 rather than error
if (elem.getBoundingClientRect) {
box = elem.getBoundingClientRect();
} else {
box = { top: 0, left: 0 };
}
for (const elem of elems) {
let box = elem.getBoundingClientRect();
results.push({
top: box.top,
@ -80,7 +73,7 @@ function getPosition(options, dlg) {
}
function centerFocus(elem, horiz, on) {
require(['scrollHelper'], function (scrollHelper) {
import('scrollHelper').then(({default: scrollHelper}) => {
const fn = on ? 'on' : 'off';
scrollHelper.centerFocus[fn](elem, horiz);
});
@ -142,7 +135,7 @@ export function show(options) {
let renderIcon = false;
let icons = [];
let itemIcon;
for (let item of options.items) {
for (const item of options.items) {
itemIcon = item.icon || (item.selected ? 'check' : null);
@ -153,7 +146,9 @@ export function show(options) {
}
if (layoutManager.tv) {
html += '<button is="paper-icon-button-light" class="btnCloseActionSheet hide-mouse-idle-tv" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
html += `<button is="paper-icon-button-light" class="btnCloseActionSheet hide-mouse-idle-tv" tabindex="-1">
<span class="material-icons arrow_back"></span>
</button>`;
}
// If any items have an icon, give them all an icon just to make sure they're all lined up evenly
@ -216,7 +211,7 @@ export function show(options) {
itemIcon = icons[i];
if (itemIcon) {
html += '<span class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons ' + itemIcon + '"></span>';
html += `<span class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons ${itemIcon}"></span>`;
} else if (renderIcon && !center) {
html += '<span class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons check" style="visibility:hidden;"></span>';
}
@ -228,13 +223,13 @@ export function show(options) {
html += '</div>';
if (item.secondaryText) {
html += '<div class="listItemBodyText secondary">' + item.secondaryText + '</div>';
html += `<div class="listItemBodyText secondary">${item.secondaryText}</div>`;
}
html += '</div>';
if (item.asideText) {
html += '<div class="listItemAside actionSheetItemAsideText">' + item.asideText + '</div>';
html += `<div class="listItemAside actionSheetItemAsideText">${item.asideText}</div>`;
}
html += '</button>';
@ -242,7 +237,7 @@ export function show(options) {
if (options.showCancel) {
html += '<div class="buttons">';
html += '<button is="emby-button" type="button" class="btnCloseActionSheet">' + globalize.translate('ButtonCancel') + '</button>';
html += `<button is="emby-button" type="button" class="btnCloseActionSheet">${globalize.translate('ButtonCancel')}</button>`;
html += '</div>';
}
html += '</div>';

View file

@ -1,11 +1,21 @@
define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings', 'serverNotifications', 'connectionManager', 'emby-button', 'listViewStyle'], function (events, globalize, dom, datefns, dfnshelper, userSettings, serverNotifications, connectionManager) {
'use strict';
import events from 'events';
import globalize from 'globalize';
import dom from 'dom';
import * as datefns from 'date-fns';
import dfnshelper from 'dfnshelper';
import userSettings from 'userSettings';
import serverNotifications from 'serverNotifications';
import connectionManager from 'connectionManager';
import 'emby-button';
import 'listViewStyle';
/* eslint-disable indent */
function getEntryHtml(entry, apiClient) {
var html = '';
let html = '';
html += '<div class="listItem listItem-border">';
var color = '#00a4dc';
var icon = 'notifications';
let color = '#00a4dc';
let icon = 'notifications';
if ('Error' == entry.Severity || 'Fatal' == entry.Severity || 'Warn' == entry.Severity) {
color = '#cc0000';
@ -34,10 +44,14 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings',
html += '</div>';
if (entry.Overview) {
html += '<button type="button" is="paper-icon-button-light" class="btnEntryInfo" data-id="' + entry.Id + '" title="' + globalize.translate('Info') + '"><span class="material-icons info"></span></button>';
html += `<button type="button" is="paper-icon-button-light" class="btnEntryInfo" data-id="${entry.Id}" title="${globalize.translate('Info')}">
<span class="material-icons info"></span>
</button>`;
}
return html += '</div>';
html += '</div>';
return html;
}
function renderList(elem, apiClient, result, startIndex, limit) {
@ -52,8 +66,8 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings',
}
limit = limit || parseInt(elem.getAttribute('data-activitylimit') || '7');
var minDate = new Date();
var hasUserId = 'false' !== elem.getAttribute('data-useractivity');
const minDate = new Date();
const hasUserId = 'false' !== elem.getAttribute('data-useractivity');
if (hasUserId) {
minDate.setTime(minDate.getTime() - 24 * 60 * 60 * 1000); // one day back
@ -70,7 +84,7 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings',
elem.setAttribute('data-activitystartindex', startIndex);
elem.setAttribute('data-activitylimit', limit);
if (!startIndex) {
var activityContainer = dom.parentWithClass(elem, 'activityContainer');
const activityContainer = dom.parentWithClass(elem, 'activityContainer');
if (activityContainer) {
if (result.Items.length) {
@ -87,7 +101,7 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings',
}
function onActivityLogUpdate(e, apiClient, data) {
var options = this.options;
const options = this.options;
if (options && options.serverId === apiClient.serverId()) {
reloadData(this, options.element, apiClient);
@ -95,14 +109,14 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings',
}
function onListClick(e) {
var btnEntryInfo = dom.parentWithClass(e.target, 'btnEntryInfo');
const btnEntryInfo = dom.parentWithClass(e.target, 'btnEntryInfo');
if (btnEntryInfo) {
var id = btnEntryInfo.getAttribute('data-id');
var items = this.items;
const id = btnEntryInfo.getAttribute('data-id');
const items = this.items;
if (items) {
var item = items.filter(function (i) {
const item = items.filter(function (i) {
return i.Id.toString() === id;
})[0];
@ -114,35 +128,35 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings',
}
function showItemOverview(item) {
require(['alert'], function (alert) {
import('alert').then(({default: alert}) => {
alert({
text: item.Overview
});
});
}
function ActivityLog(options) {
class ActivityLog {
constructor(options) {
this.options = options;
var element = options.element;
const element = options.element;
element.classList.add('activityLogListWidget');
element.addEventListener('click', onListClick.bind(this));
var apiClient = connectionManager.getApiClient(options.serverId);
const apiClient = connectionManager.getApiClient(options.serverId);
reloadData(this, element, apiClient);
var onUpdate = onActivityLogUpdate.bind(this);
const onUpdate = onActivityLogUpdate.bind(this);
this.updateFn = onUpdate;
events.on(serverNotifications, 'ActivityLogEntry', onUpdate);
apiClient.sendMessage('ActivityLogEntryStart', '0,1500');
}
ActivityLog.prototype.destroy = function () {
var options = this.options;
destroy() {
const options = this.options;
if (options) {
options.element.classList.remove('activityLogListWidget');
connectionManager.getApiClient(options.serverId).sendMessage('ActivityLogEntryStop', '0,1500');
}
var onUpdate = this.updateFn;
const onUpdate = this.updateFn;
if (onUpdate) {
events.off(serverNotifications, 'ActivityLogEntry', onUpdate);
@ -150,7 +164,9 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings',
this.items = null;
this.options = null;
};
}
}
return ActivityLog;
});
export default ActivityLog;
/* eslint-enable indent */

View file

@ -1,14 +1,17 @@
define(['browser', 'dialog', 'globalize'], function (browser, dialog, globalize) {
'use strict';
import browser from 'browser';
import dialog from 'dialog';
import globalize from 'globalize';
/* eslint-disable indent */
function replaceAll(originalString, strReplace, strWith) {
var reg = new RegExp(strReplace, 'ig');
const reg = new RegExp(strReplace, 'ig');
return originalString.replace(reg, strWith);
}
return function (text, title) {
export default function (text, title) {
var options;
let options;
if (typeof text === 'string') {
options = {
title: title,
@ -21,7 +24,7 @@ define(['browser', 'dialog', 'globalize'], function (browser, dialog, globalize)
if (browser.tv && window.alert) {
alert(replaceAll(options.text || '', '<br/>', '\n'));
} else {
var items = [];
const items = [];
items.push({
name: globalize.translate('ButtonGotIt'),
@ -31,7 +34,7 @@ define(['browser', 'dialog', 'globalize'], function (browser, dialog, globalize)
options.buttons = items;
return dialog(options).then(function (result) {
return dialog.show(options).then(function (result) {
if (result === 'ok') {
return Promise.resolve();
}
@ -41,5 +44,6 @@ define(['browser', 'dialog', 'globalize'], function (browser, dialog, globalize)
}
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) {
'use strict';
/* eslint-disable indent */
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() {
var scope = this;
var selected = scope.querySelector('.' + selectedButtonClass);
const scope = this;
const selected = scope.querySelector(`.${selectedButtonClass}`);
if (selected) {
focusManager.focus(selected);
@ -16,7 +27,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
function getAlphaPickerButtonClassName(vertical) {
var alphaPickerButtonClassName = 'alphaPickerButton';
let alphaPickerButtonClassName = 'alphaPickerButton';
if (layoutManager.tv) {
alphaPickerButtonClassName += ' alphaPickerButton-tv';
@ -30,12 +41,12 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
}
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) {
return letters.map(function (l) {
return letters.map(l => {
return getLetterButton(l, vertical);
});
}
@ -48,26 +59,26 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
element.classList.add('alphaPicker-tv');
}
var vertical = element.classList.contains('alphaPicker-vertical');
const vertical = element.classList.contains('alphaPicker-vertical');
if (!vertical) {
element.classList.add('focuscontainer-x');
}
var html = '';
var letters;
let html = '';
let letters;
var alphaPickerButtonClassName = getAlphaPickerButtonClassName(vertical);
const alphaPickerButtonClassName = getAlphaPickerButtonClassName(vertical);
var rowClassName = 'alphaPickerRow';
let rowClassName = 'alphaPickerRow';
if (vertical) {
rowClassName += ' alphaPickerRow-vertical';
}
html += '<div class="' + rowClassName + '">';
html += `<div class="${rowClassName}">`;
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 {
letters = ['#'];
html += mapLetters(letters, vertical).join('');
@ -77,11 +88,11 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
html += mapLetters(letters, vertical).join('');
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>';
letters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
html += '<div class="' + rowClassName + '">';
html += `<div class="${rowClassName}">`;
html += '<br/>';
html += mapLetters(letters, vertical).join('');
html += '</div>';
@ -95,47 +106,47 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
element.focus = focus;
}
function AlphaPicker(options) {
export class AlphaPicker {
constructor(options) {
const self = this;
var self = this;
this.options = options;
var element = options.element;
var itemsContainer = options.itemsContainer;
var itemClass = options.itemClass;
const element = options.element;
const itemsContainer = options.itemsContainer;
const itemClass = options.itemClass;
var itemFocusValue;
var itemFocusTimeout;
let itemFocusValue;
let itemFocusTimeout;
function onItemFocusTimeout() {
itemFocusTimeout = null;
self.value(itemFocusValue);
}
var alphaFocusedElement;
var alphaFocusTimeout;
let alphaFocusedElement;
let alphaFocusTimeout;
function onAlphaFocusTimeout() {
alphaFocusTimeout = null;
if (document.activeElement === alphaFocusedElement) {
var value = alphaFocusedElement.getAttribute('data-value');
const value = alphaFocusedElement.getAttribute('data-value');
self.value(value, true);
}
}
function onAlphaPickerInKeyboardModeClick(e) {
var alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton');
const alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton');
if (alphaPickerButton) {
var value = alphaPickerButton.getAttribute('data-value');
const value = alphaPickerButton.getAttribute('data-value');
element.dispatchEvent(new CustomEvent('alphavalueclicked', {
cancelable: false,
detail: {
value: value
value
}
}));
}
@ -143,14 +154,14 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
function onAlphaPickerClick(e) {
var alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton');
const alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton');
if (alphaPickerButton) {
var value = alphaPickerButton.getAttribute('data-value');
const value = alphaPickerButton.getAttribute('data-value');
if ((this._currentValue || '').toUpperCase() === value.toUpperCase()) {
self.value(null, true);
this.value(null, true);
} else {
self.value(value, true);
this.value(value, true);
}
}
}
@ -162,7 +173,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
alphaFocusTimeout = null;
}
var alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton');
const alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton');
if (alphaPickerButton) {
alphaFocusedElement = alphaPickerButton;
@ -172,10 +183,10 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
function onItemsFocusIn(e) {
var item = dom.parentWithClass(e.target, itemClass);
const item = dom.parentWithClass(e.target, itemClass);
if (item) {
var prefix = item.getAttribute('data-prefix');
const prefix = item.getAttribute('data-prefix');
if (prefix && prefix.length) {
itemFocusValue = prefix[0];
@ -187,7 +198,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
}
}
self.enabled = function (enabled) {
this.enabled = function (enabled) {
if (enabled) {
@ -223,11 +234,11 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
this.visible(true);
}
AlphaPicker.prototype.value = function (value, applyValue) {
value(value, applyValue) {
var element = this.options.element;
var btn;
var selected;
const element = this.options.element;
let btn;
let selected;
if (value !== undefined) {
if (value != null) {
@ -236,12 +247,12 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
this._currentValue = value;
if (this.options.mode !== 'keyboard') {
selected = element.querySelector('.' + selectedButtonClass);
selected = element.querySelector(`.${selectedButtonClass}`);
try {
btn = element.querySelector('.alphaPickerButton[data-value=\'' + value + '\']');
btn = element.querySelector(`.alphaPickerButton[data-value='${value}']`);
} catch (err) {
console.error('error in querySelector: ' + err);
console.error('error in querySelector:', err);
}
if (btn && btn !== selected) {
@ -254,7 +265,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
} else {
this._currentValue = value;
selected = element.querySelector('.' + selectedButtonClass);
selected = element.querySelector(`.${selectedButtonClass}`);
if (selected) {
selected.classList.remove(selectedButtonClass);
}
@ -265,57 +276,58 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
element.dispatchEvent(new CustomEvent('alphavaluechanged', {
cancelable: false,
detail: {
value: value
value
}
}));
}
return this._currentValue;
};
}
AlphaPicker.prototype.on = function (name, fn) {
var element = this.options.element;
on(name, fn) {
const element = this.options.element;
element.addEventListener(name, fn);
};
}
AlphaPicker.prototype.off = function (name, fn) {
var element = this.options.element;
off(name, fn) {
const element = this.options.element;
element.removeEventListener(name, fn);
};
}
AlphaPicker.prototype.visible = function (visible) {
visible(visible) {
var element = this.options.element;
const element = this.options.element;
element.style.visibility = visible ? 'visible' : 'hidden';
};
}
AlphaPicker.prototype.values = function () {
values() {
var element = this.options.element;
var elems = element.querySelectorAll('.alphaPickerButton');
var values = [];
for (var i = 0, length = elems.length; i < length; i++) {
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'));
}
return values;
};
}
AlphaPicker.prototype.focus = function () {
focus() {
var element = this.options.element;
const element = this.options.element;
focusManager.autoFocus(element, true);
};
}
AlphaPicker.prototype.destroy = function () {
destroy() {
var element = this.options.element;
const element = this.options.element;
this.enabled(false);
element.classList.remove('focuscontainer-x');
this.options = null;
};
}
}
return AlphaPicker;
});
/* eslint-enable indent */
export default AlphaPicker;

View file

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

View file

@ -16,21 +16,21 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
show('/settings/settings.html');
},
showNowPlaying: function () {
show('/nowplaying.html');
show('queue');
}
};
function beginConnectionWizard() {
backdrop.clear();
backdrop.clearBackdrop();
loading.show();
connectionManager.connect({
enableAutoLogin: appSettings.enableAutoLogin()
}).then(function (result) {
handleConnectionResult(result, loading);
handleConnectionResult(result);
});
}
function handleConnectionResult(result, loading) {
function handleConnectionResult(result) {
switch (result.State) {
case 'SignedIn':
loading.hide();
@ -53,7 +53,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
break;
case 'ServerUpdateNeeded':
require(['alert'], function (alert) {
alert({
alert.default({
text: globalize.translate('ServerUpdateNeeded', 'https://github.com/jellyfin/jellyfin'),
html: globalize.translate('ServerUpdateNeeded', '<a href="https://github.com/jellyfin/jellyfin">https://github.com/jellyfin/jellyfin</a>')
}).then(function () {
@ -222,48 +222,13 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
}
function normalizeImageOptions(options) {
var scaleFactor = browser.tv ? 0.8 : 1;
var setQuality;
if (options.maxWidth) {
options.maxWidth = Math.round(options.maxWidth * scaleFactor);
if (options.maxWidth || options.width || options.maxHeight || options.height) {
setQuality = true;
}
if (options.width) {
options.width = Math.round(options.width * scaleFactor);
setQuality = true;
}
if (options.maxHeight) {
options.maxHeight = Math.round(options.maxHeight * scaleFactor);
setQuality = true;
}
if (options.height) {
options.height = Math.round(options.height * scaleFactor);
setQuality = true;
}
if (setQuality) {
var quality = 100;
var type = options.type || 'Primary';
if (browser.tv || browser.slow) {
if (browser.chrome) {
// webp support
quality = type === 'Primary' ? 40 : 50;
} else {
quality = type === 'Backdrop' ? 60 : 50;
}
} else {
quality = type === 'Backdrop' ? 70 : 90;
}
options.quality = quality;
if (setQuality && !options.quality) {
options.quality = 90;
}
}
@ -384,7 +349,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
if (firstResult.State !== 'SignedIn' && !route.anonymous) {
handleConnectionResult(firstResult, loading);
handleConnectionResult(firstResult);
return;
}
}
@ -463,12 +428,11 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
return Promise.resolve();
}
var isHandlingBackToDefault;
var isDummyBackToHome;
function loadContent(ctx, route, html, request) {
html = globalize.translateDocument(html, route.dictionary);
html = globalize.translateHtml(html, route.dictionary);
request.view = html;
viewManager.loadView(request);
@ -589,8 +553,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
path = '/' + path;
}
var baseRoute = baseUrl();
path = path.replace(baseRoute, '');
path = path.replace(baseUrl(), '');
if (currentRouteInfo && currentRouteInfo.path === path) {
// can't use this with home right now due to the back menu
@ -621,10 +584,11 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
}
function showItem(item, serverId, options) {
// TODO: Refactor this so it only gets items, not strings.
if (typeof (item) === 'string') {
var apiClient = serverId ? connectionManager.getApiClient(serverId) : connectionManager.currentApiClient();
apiClient.getItem(apiClient.getCurrentUserId(), item).then(function (item) {
appRouter.showItem(item, options);
apiClient.getItem(apiClient.getCurrentUserId(), item).then(function (itemObject) {
appRouter.showItem(itemObject, options);
});
} else {
if (arguments.length === 2) {
@ -660,7 +624,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
}
if (level === 'full' || level === 2) {
backdrop.clear(true);
backdrop.clearBackdrop(true);
document.documentElement.classList.add('transparentDocument');
backgroundContainer.classList.add('backgroundContainer-transparent');
backdropContainer.classList.add('hide');

View file

@ -5,7 +5,7 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
var disableHlsVideoAudioCodecs = [];
if (item && htmlMediaHelper.enableHlsJsPlayer(item.RunTimeTicks, item.MediaType)) {
if (browser.edge || browser.msie) {
if (browser.edge) {
disableHlsVideoAudioCodecs.push('mp3');
}
@ -93,19 +93,37 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
function getDeviceName() {
var deviceName;
deviceName = browser.tizen ? 'Samsung Smart TV' : browser.web0s ? 'LG Smart TV' : browser.operaTv ? 'Opera TV' : browser.xboxOne ? 'Xbox One' : browser.ps4 ? 'Sony PS4' : browser.chrome ? 'Chrome' : browser.edge ? 'Edge' : browser.firefox ? 'Firefox' : browser.msie ? 'Internet Explorer' : browser.opera ? 'Opera' : browser.safari ? 'Safari' : 'Web Browser';
if (browser.tizen) {
deviceName = 'Samsung Smart TV';
} else if (browser.web0s) {
deviceName = 'LG Smart TV';
} else if (browser.operaTv) {
deviceName = 'Opera TV';
} else if (browser.xboxOne) {
deviceName = 'Xbox One';
} else if (browser.ps4) {
deviceName = 'Sony PS4';
} else if (browser.chrome) {
deviceName = 'Chrome';
} else if (browser.edge) {
deviceName = 'Edge';
} else if (browser.firefox) {
deviceName = 'Firefox';
} else if (browser.opera) {
deviceName = 'Opera';
} else if (browser.safari) {
deviceName = 'Safari';
} else {
deviceName = 'Web Browser';
}
if (browser.ipad) {
deviceName += ' iPad';
} else {
if (browser.iphone) {
} else if (browser.iphone) {
deviceName += ' iPhone';
} else {
if (browser.android) {
} else if (browser.android) {
deviceName += ' Android';
}
}
}
return deviceName;
}
@ -267,7 +285,7 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
if (enabled) features.push('multiserver');
});
if (!browser.orsay && !browser.msie && (browser.firefox || browser.ps4 || browser.edge || supportsCue())) {
if (!browser.orsay && (browser.firefox || browser.ps4 || browser.edge || supportsCue())) {
features.push('subtitleappearancesettings');
}

View file

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

View file

@ -1,56 +0,0 @@
define(['connectionManager'], function (connectionManager) {
return function () {
var self = this;
self.name = 'Backdrop ScreenSaver';
self.type = 'screensaver';
self.id = 'backdropscreensaver';
self.supportsAnonymous = false;
var currentSlideshow;
self.show = function () {
var query = {
ImageTypes: 'Backdrop',
EnableImageTypes: 'Backdrop',
IncludeItemTypes: 'Movie,Series,MusicArtist',
SortBy: 'Random',
Recursive: true,
Fields: 'Taglines',
ImageTypeLimit: 1,
StartIndex: 0,
Limit: 200
};
var apiClient = connectionManager.currentApiClient();
apiClient.getItems(apiClient.getCurrentUserId(), query).then(function (result) {
if (result.Items.length) {
require(['slideshow'], function (slideshow) {
var newSlideShow = new slideshow({
showTitle: true,
cover: true,
items: result.Items
});
newSlideShow.show();
currentSlideshow = newSlideShow;
});
}
});
};
self.hide = function () {
if (currentSlideshow) {
currentSlideshow.hide();
currentSlideshow = null;
}
};
};
});

View file

@ -167,8 +167,9 @@ button::-moz-focus-inner {
position: relative;
background-clip: content-box !important;
color: inherit;
}
/* This is only needed for scalable cards */
.cardScalable .cardImageContainer {
height: 100%;
contain: strict;
}
@ -192,9 +193,14 @@ button::-moz-focus-inner {
/* Needed in case this is a button */
display: block;
/* Needed in case this is a button */
margin: 0 !important;
border: 0 !important;
padding: 0 !important;
cursor: pointer;
color: inherit;
width: 100%;
font-family: inherit;
font-size: inherit;
/* Needed in safari */
height: 100%;
@ -203,19 +209,12 @@ button::-moz-focus-inner {
contain: strict;
}
.cardContent-button {
border: 0 !important;
padding: 0 !important;
cursor: pointer;
color: inherit;
width: 100%;
vertical-align: middle;
font-family: inherit;
font-size: inherit;
.cardContent:not(.defaultCardBackground) {
background-color: transparent;
}
.cardContent-button:not(.defaultCardBackground) {
background-color: transparent;
.cardBox:not(.visualCardBox) .cardPadder {
background-color: #242424;
}
.visualCardBox .cardContent {
@ -223,7 +222,8 @@ button::-moz-focus-inner {
border-bottom-right-radius: 0;
}
.cardContent-shadow {
.cardContent-shadow,
.cardBox:not(.visualCardBox) .cardPadder {
box-shadow: 0 0.0725em 0.29em 0 rgba(0, 0, 0, 0.37);
}

View file

@ -368,9 +368,7 @@ import 'programStyles';
let apiClient;
let lastServerId;
for (let i = 0; i < items.length; i++) {
let item = items[i];
for (const [i, item] of items.entries()) {
let serverId = item.ServerId || options.serverId;
if (serverId !== lastServerId) {
@ -503,94 +501,49 @@ import 'programStyles';
const primaryImageAspectRatio = item.PrimaryImageAspectRatio;
let forceName = false;
let imgUrl = null;
let imgTag = null;
let coverImage = false;
let uiAspect = null;
let imgType = null;
let itemId = null;
if (options.preferThumb && item.ImageTags && item.ImageTags.Thumb) {
imgUrl = apiClient.getScaledImageUrl(item.Id, {
type: 'Thumb',
maxWidth: width,
tag: item.ImageTags.Thumb
});
imgType = 'Thumb';
imgTag = item.ImageTags.Thumb;
} else if ((options.preferBanner || shape === 'banner') && item.ImageTags && item.ImageTags.Banner) {
imgUrl = apiClient.getScaledImageUrl(item.Id, {
type: 'Banner',
maxWidth: width,
tag: item.ImageTags.Banner
});
imgType = 'Banner';
imgTag = item.ImageTags.Banner;
} else if (options.preferDisc && item.ImageTags && item.ImageTags.Disc) {
imgUrl = apiClient.getScaledImageUrl(item.Id, {
type: 'Disc',
maxWidth: width,
tag: item.ImageTags.Disc
});
imgType = 'Disc';
imgTag = item.ImageTags.Disc;
} else if (options.preferLogo && item.ImageTags && item.ImageTags.Logo) {
imgUrl = apiClient.getScaledImageUrl(item.Id, {
type: 'Logo',
maxWidth: width,
tag: item.ImageTags.Logo
});
imgType = 'Logo';
imgTag = item.ImageTags.Logo;
} else if (options.preferLogo && item.ParentLogoImageTag && item.ParentLogoItemId) {
imgUrl = apiClient.getScaledImageUrl(item.ParentLogoItemId, {
type: 'Logo',
maxWidth: width,
tag: item.ParentLogoImageTag
});
imgType = 'Logo';
imgTag = item.ParentLogoImageTag;
itemId = item.ParentLogoItemId;
} else if (options.preferThumb && item.SeriesThumbImageTag && options.inheritThumb !== false) {
imgUrl = apiClient.getScaledImageUrl(item.SeriesId, {
type: 'Thumb',
maxWidth: width,
tag: item.SeriesThumbImageTag
});
imgType = 'Thumb';
imgTag = item.SeriesThumbImageTag;
itemId = item.SeriesId;
} else if (options.preferThumb && item.ParentThumbItemId && options.inheritThumb !== false && item.MediaType !== 'Photo') {
imgUrl = apiClient.getScaledImageUrl(item.ParentThumbItemId, {
type: 'Thumb',
maxWidth: width,
tag: item.ParentThumbImageTag
});
imgType = 'Thumb';
imgTag = item.ParentThumbImageTag;
itemId = item.ParentThumbItemId;
} else if (options.preferThumb && item.BackdropImageTags && item.BackdropImageTags.length) {
imgUrl = apiClient.getScaledImageUrl(item.Id, {
type: 'Backdrop',
maxWidth: width,
tag: item.BackdropImageTags[0]
});
imgType = 'Backdrop';
imgTag = item.BackdropImageTags[0];
forceName = true;
} else if (options.preferThumb && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length && options.inheritThumb !== false && item.Type === 'Episode') {
imgUrl = apiClient.getScaledImageUrl(item.ParentBackdropItemId, {
type: 'Backdrop',
maxWidth: width,
tag: item.ParentBackdropImageTags[0]
});
} else if (item.ImageTags && item.ImageTags.Primary) {
imgType = 'Backdrop';
imgTag = item.ParentBackdropImageTags[0];
itemId = item.ParentBackdropItemId;
} else if (item.ImageTags && item.ImageTags.Primary && (item.Type !== 'Episode' || item.ChildCount !== 0)) {
imgType = 'Primary';
imgTag = item.ImageTags.Primary;
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
imgUrl = apiClient.getScaledImageUrl(item.Id, {
type: 'Primary',
maxHeight: height,
maxWidth: width,
tag: item.ImageTags.Primary
});
if (options.preferThumb && options.showTitle !== false) {
forceName = true;
}
@ -601,18 +554,16 @@ import 'programStyles';
coverImage = (Math.abs(primaryImageAspectRatio - uiAspect) / uiAspect) <= 0.2;
}
}
} else if (item.SeriesPrimaryImageTag) {
imgType = 'Primary';
imgTag = item.SeriesPrimaryImageTag;
itemId = item.SeriesId;
} else if (item.PrimaryImageTag) {
imgType = 'Primary';
imgTag = item.PrimaryImageTag;
itemId = item.PrimaryImageItemId;
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
imgUrl = apiClient.getScaledImageUrl(item.PrimaryImageItemId || item.Id || item.ItemId, {
type: 'Primary',
maxHeight: height,
maxWidth: width,
tag: item.PrimaryImageTag
});
if (options.preferThumb && options.showTitle !== false) {
forceName = true;
}
@ -624,30 +575,15 @@ import 'programStyles';
}
}
} else if (item.ParentPrimaryImageTag) {
imgUrl = apiClient.getScaledImageUrl(item.ParentPrimaryImageItemId, {
type: 'Primary',
maxWidth: width,
tag: item.ParentPrimaryImageTag
});
} else if (item.SeriesPrimaryImageTag) {
imgUrl = apiClient.getScaledImageUrl(item.SeriesId, {
type: 'Primary',
maxWidth: width,
tag: item.SeriesPrimaryImageTag
});
imgType = 'Primary';
imgTag = item.ParentPrimaryImageTag;
itemId = item.ParentPrimaryImageItemId;
} else if (item.AlbumId && item.AlbumPrimaryImageTag) {
imgType = 'Primary';
imgTag = item.AlbumPrimaryImageTag;
itemId = item.AlbumId;
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
imgUrl = apiClient.getScaledImageUrl(item.AlbumId, {
type: 'Primary',
maxHeight: height,
maxWidth: width,
tag: item.AlbumPrimaryImageTag
});
if (primaryImageAspectRatio) {
uiAspect = getDesiredAspect(shape);
if (uiAspect) {
@ -655,57 +591,46 @@ import 'programStyles';
}
}
} else if (item.Type === 'Season' && item.ImageTags && item.ImageTags.Thumb) {
imgUrl = apiClient.getScaledImageUrl(item.Id, {
type: 'Thumb',
maxWidth: width,
tag: item.ImageTags.Thumb
});
imgType = 'Thumb';
imgTag = item.ImageTags.Thumb;
} else if (item.BackdropImageTags && item.BackdropImageTags.length) {
imgUrl = apiClient.getScaledImageUrl(item.Id, {
type: 'Backdrop',
maxWidth: width,
tag: item.BackdropImageTags[0]
});
imgType = 'Backdrop';
imgTag = item.BackdropImageTags[0];
} else if (item.ImageTags && item.ImageTags.Thumb) {
imgUrl = apiClient.getScaledImageUrl(item.Id, {
type: 'Thumb',
maxWidth: width,
tag: item.ImageTags.Thumb
});
imgType = 'Thumb';
imgTag = item.ImageTags.Thumb;
} else if (item.SeriesThumbImageTag && options.inheritThumb !== false) {
imgUrl = apiClient.getScaledImageUrl(item.SeriesId, {
type: 'Thumb',
maxWidth: width,
tag: item.SeriesThumbImageTag
});
imgType = 'Thumb';
imgTag = item.SeriesThumbImageTag;
itemId = item.SeriesId;
} else if (item.ParentThumbItemId && options.inheritThumb !== false) {
imgUrl = apiClient.getScaledImageUrl(item.ParentThumbItemId, {
type: 'Thumb',
maxWidth: width,
tag: item.ParentThumbImageTag
});
imgType = 'Thumb';
imgTag = item.ParentThumbImageTag;
itemId = item.ParentThumbItemId;
} else if (item.ParentBackdropImageTags && item.ParentBackdropImageTags.length && options.inheritThumb !== false) {
imgUrl = apiClient.getScaledImageUrl(item.ParentBackdropItemId, {
type: 'Backdrop',
maxWidth: width,
tag: item.ParentBackdropImageTags[0]
});
imgType = 'Backdrop';
imgTag = item.ParentBackdropImageTags[0];
itemId = item.ParentBackdropItemId;
}
if (!itemId) {
itemId = item.Id;
}
if (imgTag && imgType) {
imgUrl = apiClient.getScaledImageUrl(itemId, {
type: imgType,
maxHeight: height,
maxWidth: width,
tag: imgTag
});
}
let blurHashes = options.imageBlurhashes || item.ImageBlurHashes || {};
return {
imgUrl: imgUrl,
blurhash: (blurHashes[imgType] || {})[imgTag],
forceName: forceName,
coverImage: coverImage
};
@ -1235,10 +1160,10 @@ import 'programStyles';
/**
* Imports the refresh indicator element.
*/
function requireRefreshIndicator() {
function importRefreshIndicator() {
if (!refreshIndicatorLoaded) {
refreshIndicatorLoaded = true;
require(['emby-itemrefreshindicator']);
import('emby-itemrefreshindicator');
}
}
@ -1321,6 +1246,7 @@ import 'programStyles';
const imgInfo = getCardImageUrl(item, apiClient, options, shape);
const imgUrl = imgInfo.imgUrl;
const blurhash = imgInfo.blurhash;
const forceName = imgInfo.forceName;
@ -1384,7 +1310,7 @@ import 'programStyles';
}
const mediaSourceCount = item.MediaSourceCount || 1;
if (mediaSourceCount > 1) {
if (mediaSourceCount > 1 && options.disableIndicators !== true) {
innerCardFooter += '<div class="mediaSourceIndicator">' + mediaSourceCount + '</div>';
}
@ -1441,29 +1367,31 @@ import 'programStyles';
let cardScalableClose = '';
let cardContentClass = 'cardContent';
if (!options.cardLayout) {
cardContentClass += ' cardContent-shadow';
let blurhashAttrib = '';
if (blurhash && blurhash.length > 0) {
blurhashAttrib = 'data-blurhash="' + blurhash + '"';
}
if (layoutManager.tv) {
// Don't use the IMG tag with safari because it puts a white border around it
cardImageContainerOpen = imgUrl ? ('<div class="' + cardImageContainerClass + ' ' + cardContentClass + ' lazy" data-src="' + imgUrl + '">') : ('<div class="' + cardImageContainerClass + ' ' + cardContentClass + '">');
cardImageContainerOpen = imgUrl ? ('<div class="' + cardImageContainerClass + ' ' + cardContentClass + ' lazy" data-src="' + imgUrl + '" ' + blurhashAttrib + '>') : ('<div class="' + cardImageContainerClass + ' ' + cardContentClass + '">');
cardImageContainerClose = '</div>';
} else {
// Don't use the IMG tag with safari because it puts a white border around it
cardImageContainerOpen = imgUrl ? ('<button data-action="' + action + '" class="cardContent-button ' + cardImageContainerClass + ' ' + cardContentClass + ' itemAction lazy" data-src="' + imgUrl + '">') : ('<button data-action="' + action + '" class="cardContent-button ' + cardImageContainerClass + ' ' + cardContentClass + ' itemAction">');
cardImageContainerOpen = imgUrl ? ('<button data-action="' + action + '" class="' + cardImageContainerClass + ' ' + cardContentClass + ' itemAction lazy" data-src="' + imgUrl + '" ' + blurhashAttrib + '>') : ('<button data-action="' + action + '" class="' + cardImageContainerClass + ' ' + cardContentClass + ' itemAction">');
cardImageContainerClose = '</button>';
}
let cardScalableClass = 'cardScalable';
cardImageContainerOpen = '<div class="' + cardBoxClass + '"><div class="' + cardScalableClass + '"><div class="cardPadder-' + shape + '"></div>' + cardImageContainerOpen;
cardImageContainerOpen = '<div class="' + cardBoxClass + '"><div class="' + cardScalableClass + '"><div class="cardPadder cardPadder-' + shape + '"></div>' + cardImageContainerOpen;
cardBoxClose = '</div>';
cardScalableClose = '</div>';
if (options.disableIndicators !== true) {
let indicatorsHtml = '';
if (options.missingIndicator !== false) {
@ -1487,12 +1415,13 @@ import 'programStyles';
if (item.Type === 'CollectionFolder' || item.CollectionType) {
const refreshClass = item.RefreshProgress ? '' : ' class="hide"';
indicatorsHtml += '<div is="emby-itemrefreshindicator"' + refreshClass + ' data-progress="' + (item.RefreshProgress || 0) + '" data-status="' + item.RefreshStatus + '"></div>';
requireRefreshIndicator();
importRefreshIndicator();
}
if (indicatorsHtml) {
cardImageContainerOpen += '<div class="cardIndicators">' + indicatorsHtml + '</div>';
}
}
if (!imgUrl) {
cardImageContainerOpen += getDefaultText(item, options);
@ -1539,8 +1468,8 @@ import 'programStyles';
let additionalCardContent = '';
if (layoutManager.desktop) {
additionalCardContent += getHoverMenuHtml(item, action);
if (layoutManager.desktop && !options.disableHoverMenu) {
additionalCardContent += getHoverMenuHtml(item, action, options);
}
return '<' + tagName + ' data-index="' + index + '"' + timerAttributes + actionAttribute + ' data-isfolder="' + (item.IsFolder || false) + '" data-serverid="' + (item.ServerId || options.serverId) + '" data-id="' + (item.Id || item.ItemId) + '" data-type="' + item.Type + '"' + mediaTypeData + collectionTypeData + channelIdData + positionTicksData + collectionIdData + playlistIdData + contextData + parentIdData + ' data-prefix="' + prefix + '" class="' + className + '">' + cardImageContainerOpen + innerCardFooter + cardImageContainerClose + overlayButtons + additionalCardContent + cardScalableClose + outerCardFooter + cardBoxClose + '</' + tagName + '>';
@ -1550,9 +1479,10 @@ import 'programStyles';
* Generates HTML markup for the card overlay.
* @param {object} item - Item used to generate the card overlay.
* @param {string} action - Action assigned to the overlay.
* @param {Array} options - Card builder options.
* @returns {string} HTML markup of the card overlay.
*/
function getHoverMenuHtml(item, action) {
function getHoverMenuHtml(item, action, options) {
let html = '';
html += '<div class="cardOverlayContainer itemAction" data-action="' + action + '">';
@ -1568,7 +1498,7 @@ import 'programStyles';
const userData = item.UserData || {};
if (itemHelper.canMarkPlayed(item)) {
require(['emby-playstatebutton']);
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>';
}
@ -1576,12 +1506,11 @@ import 'programStyles';
const likes = userData.Likes == null ? '' : userData.Likes;
require(['emby-ratingbutton']);
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="paper-icon-button-light" class="' + btnCssClass + '" data-action="menu"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover more_vert"></span></button>';
html += '</div>';
html += '</div>';
@ -1605,6 +1534,8 @@ import 'programStyles';
case 'MusicArtist':
case 'Person':
return '<span class="cardImageIcon material-icons person"></span>';
case 'Audio':
return '<span class="cardImageIcon material-icons audiotrack"></span>';
case 'Movie':
return '<span class="cardImageIcon material-icons movie"></span>';
case 'Series':
@ -1613,6 +1544,12 @@ import 'programStyles';
return '<span class="cardImageIcon material-icons book"></span>';
case 'Folder':
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) {

View file

@ -1,13 +1,23 @@
define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browser'], function (datetime, imageLoader, connectionManager, layoutManager, browser) {
'use strict';
/* eslint-disable indent */
var enableFocusTransform = !browser.slow && !browser.edge;
/**
* Module for building cards from item data.
* @module components/cardBuilder/chaptercardbuilder
*/
import datetime from 'datetime';
import imageLoader from 'imageLoader';
import connectionManager from 'connectionManager';
import layoutManager from 'layoutManager';
import browser from 'browser';
const enableFocusTransform = !browser.slow && !browser.edge;
function buildChapterCardsHtml(item, chapters, options) {
// TODO move card creation code to Card component
var className = 'card itemAction chapterCard';
let className = 'card itemAction chapterCard';
if (layoutManager.tv) {
className += ' show-focus';
@ -17,12 +27,12 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browse
}
}
var mediaStreams = ((item.MediaSources || [])[0] || {}).MediaStreams || [];
var videoStream = mediaStreams.filter(function (i) {
return i.Type === 'Video';
const mediaStreams = ((item.MediaSources || [])[0] || {}).MediaStreams || [];
const videoStream = mediaStreams.filter(({Type}) => {
return Type === 'Video';
})[0] || {};
var shape = (options.backdropShape || 'backdrop');
let shape = (options.backdropShape || 'backdrop');
if (videoStream.Width && videoStream.Height) {
@ -31,24 +41,24 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browse
}
}
className += ' ' + shape + 'Card';
className += ` ${shape}Card`;
if (options.block || options.rows) {
className += ' block';
}
var html = '';
var itemsInRow = 0;
let html = '';
let itemsInRow = 0;
var apiClient = connectionManager.getApiClient(item.ServerId);
const apiClient = connectionManager.getApiClient(item.ServerId);
for (var i = 0, length = chapters.length; i < length; i++) {
for (let i = 0, length = chapters.length; i < length; i++) {
if (options.rows && itemsInRow === 0) {
html += '<div class="cardColumn">';
}
var chapter = chapters[i];
const chapter = chapters[i];
html += buildChapterCard(item, apiClient, chapter, i, options, className, shape);
itemsInRow++;
@ -62,50 +72,50 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browse
return html;
}
function getImgUrl(item, chapter, index, maxWidth, apiClient) {
function getImgUrl({Id}, {ImageTag}, index, maxWidth, apiClient) {
if (chapter.ImageTag) {
if (ImageTag) {
return apiClient.getScaledImageUrl(item.Id, {
return apiClient.getScaledImageUrl(Id, {
maxWidth: maxWidth * 2,
tag: chapter.ImageTag,
tag: ImageTag,
type: 'Chapter',
index: index
index
});
}
return null;
}
function buildChapterCard(item, apiClient, chapter, index, options, className, shape) {
function buildChapterCard(item, apiClient, chapter, index, {width, coverImage}, className, shape) {
var imgUrl = getImgUrl(item, chapter, index, options.width || 400, apiClient);
const imgUrl = getImgUrl(item, chapter, index, width || 400, apiClient);
var cardImageContainerClass = 'cardContent cardContent-shadow cardImageContainer chapterCardImageContainer';
if (options.coverImage) {
let cardImageContainerClass = 'cardContent cardContent-shadow cardImageContainer chapterCardImageContainer';
if (coverImage) {
cardImageContainerClass += ' coveredImage';
}
var dataAttributes = ' data-action="play" data-isfolder="' + item.IsFolder + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-type="' + item.Type + '" data-mediatype="' + item.MediaType + '" data-positionticks="' + chapter.StartPositionTicks + '"';
var cardImageContainer = imgUrl ? ('<div class="' + cardImageContainerClass + ' lazy" data-src="' + imgUrl + '">') : ('<div class="' + cardImageContainerClass + '">');
const dataAttributes = ` data-action="play" data-isfolder="${item.IsFolder}" data-id="${item.Id}" data-serverid="${item.ServerId}" data-type="${item.Type}" data-mediatype="${item.MediaType}" data-positionticks="${chapter.StartPositionTicks}"`;
let cardImageContainer = imgUrl ? (`<div class="${cardImageContainerClass} lazy" data-src="${imgUrl}">`) : (`<div class="${cardImageContainerClass}">`);
if (!imgUrl) {
cardImageContainer += '<span class="material-icons cardImageIcon local_movies"></span>';
}
var nameHtml = '';
nameHtml += '<div class="cardText">' + chapter.Name + '</div>';
nameHtml += '<div class="cardText">' + datetime.getDisplayRunningTime(chapter.StartPositionTicks) + '</div>';
let nameHtml = '';
nameHtml += `<div class="cardText">${chapter.Name}</div>`;
nameHtml += `<div class="cardText">${datetime.getDisplayRunningTime(chapter.StartPositionTicks)}</div>`;
var cardBoxCssClass = 'cardBox';
var cardScalableClass = 'cardScalable';
const cardBoxCssClass = 'cardBox';
const cardScalableClass = 'cardScalable';
var 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>';
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 html;
}
function buildChapterCards(item, chapters, options) {
export function buildChapterCards(item, chapters, options) {
if (options.parentContainer) {
// Abort if the container has been disposed
@ -121,15 +131,16 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browse
}
}
var html = buildChapterCardsHtml(item, chapters, options);
const html = buildChapterCardsHtml(item, chapters, options);
options.itemsContainer.innerHTML = html;
imageLoader.lazyChildren(options.itemsContainer);
}
return {
buildChapterCards: buildChapterCards
};
/* eslint-enable indent */
export default {
buildChapterCards: buildChapterCards
};
});

View file

@ -1,7 +1,13 @@
define(['cardBuilder'], function (cardBuilder) {
'use strict';
/* eslint-disable indent */
function buildPeopleCards(items, options) {
/**
* Module for building cards from item data.
* @module components/cardBuilder/peoplecardbuilder
*/
import cardBuilder from 'cardBuilder';
export function buildPeopleCards(items, options) {
options = Object.assign(options || {}, {
cardLayout: false,
@ -15,8 +21,8 @@ define(['cardBuilder'], function (cardBuilder) {
cardBuilder.buildCards(items, options);
}
return {
buildPeopleCards: buildPeopleCards
};
/* eslint-enable indent */
});
export default {
buildPeopleCards: buildPeopleCards
};

View file

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

View file

@ -1,16 +1,32 @@
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) {
'use strict';
import dom from 'dom';
import dialogHelper from 'dialogHelper';
import loading from 'loading';
import appHost from 'apphost';
import layoutManager from 'layoutManager';
import connectionManager from 'connectionManager';
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) {
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 = connectionManager.getApiClient(currentServerId);
if (collectionId) {
addToCollection(apiClient, panel, collectionId);
@ -24,7 +40,7 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
function createCollection(apiClient, dlg) {
var url = apiClient.getUrl('Collections', {
const url = apiClient.getUrl('Collections', {
Name: dlg.querySelector('#txtNewCollectionName').value,
IsLocked: !dlg.querySelector('#chkEnableInternetMetadata').checked,
@ -36,11 +52,11 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
url: url,
dataType: 'json'
}).then(function (result) {
}).then(result => {
loading.hide();
var id = result.Id;
const id = result.Id;
dlg.submitted = true;
dialogHelper.close(dlg);
@ -56,7 +72,7 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
function addToCollection(apiClient, dlg, id) {
var url = apiClient.getUrl('Collections/' + id + '/Items', {
const url = apiClient.getUrl(`Collections/${id}/Items`, {
Ids: dlg.querySelector('.fldSelectedItemIds').value || ''
});
@ -65,14 +81,14 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
type: 'POST',
url: url
}).then(function () {
}).then(() => {
loading.hide();
dlg.submitted = true;
dialogHelper.close(dlg);
require(['toast'], function (toast) {
import('toast').then(({default: toast}) => {
toast(globalize.translate('MessageItemsAdded'));
});
});
@ -86,11 +102,11 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
loading.show();
var select = panel.querySelector('#selectCollectionToAddTo');
const select = panel.querySelector('#selectCollectionToAddTo');
panel.querySelector('.newCollectionInfo').classList.add('hide');
var options = {
const options = {
Recursive: true,
IncludeItemTypes: 'BoxSet',
@ -98,16 +114,16 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
EnableTotalRecordCount: false
};
var apiClient = connectionManager.getApiClient(currentServerId);
apiClient.getItems(apiClient.getCurrentUserId(), options).then(function (result) {
const apiClient = connectionManager.getApiClient(currentServerId);
apiClient.getItems(apiClient.getCurrentUserId(), options).then(result => {
var html = '';
let html = '';
html += '<option value="">' + globalize.translate('OptionNew') + '</option>';
html += `<option value="">${globalize.translate('OptionNew')}</option>`;
html += result.Items.map(function (i) {
html += result.Items.map(i => {
return '<option value="' + i.Id + '">' + i.Name + '</option>';
return `<option value="${i.Id}">${i.Name}</option>`;
});
select.innerHTML = html;
@ -120,7 +136,7 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
function getEditorHtml() {
var html = '';
let html = '';
html += '<div class="formDialogContent smoothScrollY" style="padding-top:2em;">';
html += '<div class="dialogContentInner dialog-content-centered">';
@ -134,27 +150,27 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
html += '<br/>';
html += '<br/>';
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 class="newCollectionInfo">';
html += '<div class="inputContainer">';
html += '<input is="emby-input" type="text" id="txtNewCollectionName" required="required" label="' + globalize.translate('LabelName') + '" />';
html += '<div class="fieldDescription">' + globalize.translate('NewCollectionNameExample') + '</div>';
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>';
html += '<label class="checkboxContainer">';
html += '<input is="emby-checkbox" type="checkbox" id="chkEnableInternetMetadata" />';
html += '<span>' + globalize.translate('SearchForCollectionInternetMetadata') + '</span>';
html += `<span>${globalize.translate('SearchForCollectionInternetMetadata')}</span>`;
html += '</label>';
// newCollectionInfo
html += '</div>';
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 += '<input type="hidden" class="fldSelectedItemIds" />';
@ -188,7 +204,7 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
} else {
content.querySelector('.fldSelectCollection').classList.add('hide');
var selectCollectionToAddTo = content.querySelector('#selectCollectionToAddTo');
const selectCollectionToAddTo = content.querySelector('#selectCollectionToAddTo');
selectCollectionToAddTo.innerHTML = '';
selectCollectionToAddTo.value = '';
triggerChange(selectCollectionToAddTo);
@ -196,22 +212,19 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
}
function centerFocus(elem, horiz, on) {
require(['scrollHelper'], function (scrollHelper) {
var fn = on ? 'on' : 'off';
import('scrollHelper').then(scrollHelper => {
const fn = on ? 'on' : 'off';
scrollHelper.centerFocus[fn](elem, horiz);
});
}
function CollectionEditor() {
export class showEditor {
constructor(options) {
}
CollectionEditor.prototype.show = function (options) {
var items = options.items || {};
const items = options.items || {};
currentServerId = options.serverId;
var dialogOptions = {
const dialogOptions = {
removeOnClose: true,
scrollY: false
};
@ -222,12 +235,12 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
dialogOptions.size = 'small';
}
var dlg = dialogHelper.createDialog(dialogOptions);
const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog');
var html = '';
var title = items.length ? globalize.translate('HeaderAddToCollection') : globalize.translate('NewCollection');
let html = '';
const title = items.length ? globalize.translate('HeaderAddToCollection') : globalize.translate('NewCollection');
html += '<div class="formDialogHeader">';
html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
@ -236,7 +249,7 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
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 += `<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>';
@ -247,7 +260,7 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
initEditor(dlg, items);
dlg.querySelector('.btnCancel').addEventListener('click', function () {
dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg);
});
@ -256,7 +269,7 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
centerFocus(dlg.querySelector('.formDialogContent'), false, true);
}
return dialogHelper.open(dlg).then(function () {
return dialogHelper.open(dlg).then(() => {
if (layoutManager.tv) {
centerFocus(dlg.querySelector('.formDialogContent'), false, false);
@ -268,7 +281,8 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
return Promise.reject();
});
};
}
}
return CollectionEditor;
});
/* eslint-enable indent */
export default showEditor;

View file

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

View file

@ -1,20 +1,31 @@
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) {
'use strict';
import dialogHelper from 'dialogHelper';
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) {
var dialogOptions = {
const dialogOptions = {
removeOnClose: true,
scrollY: false
};
var enableTvLayout = layoutManager.tv;
const enableTvLayout = layoutManager.tv;
if (enableTvLayout) {
dialogOptions.size = 'fullscreen';
}
var dlg = dialogHelper.createDialog(dialogOptions);
const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog');
@ -22,7 +33,7 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
dlg.classList.add('align-items-center');
dlg.classList.add('justify-content-center');
var formDialogContent = dlg.querySelector('.formDialogContent');
const formDialogContent = dlg.querySelector('.formDialogContent');
formDialogContent.classList.add('no-grow');
if (enableTvLayout) {
@ -30,7 +41,7 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
formDialogContent.style['max-height'] = '60%';
scrollHelper.centerFocus.on(formDialogContent, false);
} 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');
}
@ -44,27 +55,27 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
dlg.querySelector('.formDialogHeaderTitle').classList.add('hide');
}
var displayText = options.html || options.text || '';
const displayText = options.html || options.text || '';
dlg.querySelector('.text').innerHTML = displayText;
if (!displayText) {
dlg.querySelector('.dialogContentInner').classList.add('hide');
}
var i;
var length;
var html = '';
var hasDescriptions = false;
let i;
let length;
let html = '';
let hasDescriptions = false;
for (i = 0, length = options.buttons.length; i < length; i++) {
var item = options.buttons[i];
var autoFocus = i === 0 ? ' autofocus' : '';
const item = options.buttons[i];
const autoFocus = i === 0 ? ' autofocus' : '';
var buttonClass = 'btnOption raised formDialogFooterItem formDialogFooterItem-autosize';
let buttonClass = 'btnOption raised formDialogFooterItem formDialogFooterItem-autosize';
if (item.type) {
buttonClass += ' button-' + item.type;
buttonClass += ` button-${item.type}`;
}
if (item.description) {
@ -75,10 +86,10 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
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) {
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,18 +99,18 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
dlg.querySelector('.formDialogFooter').classList.add('formDialogFooter-vertical');
}
var dialogResult;
let dialogResult;
function onButtonClick() {
dialogResult = this.getAttribute('data-id');
dialogHelper.close(dlg);
}
var buttons = dlg.querySelectorAll('.btnOption');
const buttons = dlg.querySelectorAll('.btnOption');
for (i = 0, length = buttons.length; i < length; i++) {
buttons[i].addEventListener('click', onButtonClick);
}
return dialogHelper.open(dlg).then(function () {
return dialogHelper.open(dlg).then(() => {
if (enableTvLayout) {
scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false);
@ -113,9 +124,9 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
});
}
return function (text, title) {
export async function show(text, title) {
var options;
let options;
if (typeof text === 'string') {
options = {
title: title,
@ -125,10 +136,13 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
options = text;
}
return new Promise(function (resolve, reject) {
require(['text!./dialog.template.html'], function (template) {
const { default: template } = await import('text!./dialog.template.html');
return new Promise((resolve, reject) => {
showDialog(options, template).then(resolve, reject);
});
});
};
});
}
/* eslint-enable indent */
export default {
show: show
};

View file

@ -4,12 +4,8 @@
<div class="formDialogContent smoothScrollY">
<div class="dialogContentInner dialog-content-centered" style="padding-top:1em;padding-bottom: 1em; text-align: center;">
<div class="text">
</div>
<div class="text"></div>
</div>
</div>
<div class="formDialogFooter formDialogFooter-clear formDialogFooter-flex" style="padding-bottom: 1.5em;">
</div>
<div class="formDialogFooter formDialogFooter-clear formDialogFooter-flex" style="margin:1em"></div>

View file

@ -1,7 +1,15 @@
define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', 'dom', 'css!./dialoghelper.css', 'scrollStyles'], function (appRouter, focusManager, browser, layoutManager, inputManager, dom) {
'use strict';
import appRouter from 'appRouter';
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() {
@ -25,7 +33,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
}
function tryRemoveElement(elem) {
var parentNode = elem.parentNode;
const parentNode = elem.parentNode;
if (parentNode) {
// Seeing crashes in edge webview
@ -39,14 +47,14 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
function DialogHashHandler(dlg, hash, resolve) {
var self = this;
const self = this;
self.originalUrl = window.location.href;
var activeElement = document.activeElement;
var removeScrollLockOnClose = false;
const activeElement = document.activeElement;
let removeScrollLockOnClose = false;
function onHashChange(e) {
var isBack = self.originalUrl === window.location.href;
const isBack = self.originalUrl === window.location.href;
if (isBack || !isOpened(dlg)) {
window.removeEventListener('popstate', onHashChange);
@ -84,7 +92,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
}
if (!self.closedByBack && isHistoryEnabled(dlg)) {
var state = history.state || {};
const state = history.state || {};
if (state.dialogId === hash) {
history.back();
}
@ -97,7 +105,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
if (dlg.getAttribute('data-removeonclose') !== 'false') {
removeCenterFocus(dlg);
var dialogContainer = dlg.dialogContainer;
const dialogContainer = dlg.dialogContainer;
if (dialogContainer) {
tryRemoveElement(dialogContainer);
dlg.dialogContainer = null;
@ -108,7 +116,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
//resolve();
// if we just called history.back(), then use a timeout to allow the history events to fire first
setTimeout(function () {
setTimeout(() => {
resolve({
element: dlg,
closedByBack: self.closedByBack
@ -118,7 +126,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
dlg.addEventListener('close', onDialogClosed);
var center = !dlg.classList.contains('dialog-fixedSize');
const center = !dlg.classList.contains('dialog-fixedSize');
if (center) {
dlg.classList.add('centeredDialog');
}
@ -141,7 +149,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
animateDialogOpen(dlg);
if (isHistoryEnabled(dlg)) {
appRouter.pushState({ dialogId: hash }, 'Dialog', '#' + hash);
appRouter.pushState({ dialogId: hash }, 'Dialog', `#${hash}`);
window.addEventListener('popstate', onHashChange);
} else {
@ -151,10 +159,10 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
function addBackdropOverlay(dlg) {
var backdrop = document.createElement('div');
const backdrop = document.createElement('div');
backdrop.classList.add('dialogBackdrop');
var backdropParent = dlg.dialogContainer || dlg;
const backdropParent = dlg.dialogContainer || dlg;
backdropParent.parentNode.insertBefore(backdrop, backdropParent);
dlg.backdrop = backdrop;
@ -162,7 +170,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
void backdrop.offsetWidth;
backdrop.classList.add('dialogBackdropOpened');
dom.addEventListener((dlg.dialogContainer || backdrop), 'click', function (e) {
dom.addEventListener((dlg.dialogContainer || backdrop), 'click', e => {
if (e.target === dlg.dialogContainer) {
close(dlg);
}
@ -170,7 +178,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
passive: true
});
dom.addEventListener((dlg.dialogContainer || backdrop), 'contextmenu', function (e) {
dom.addEventListener((dlg.dialogContainer || backdrop), 'contextmenu', e => {
if (e.target === dlg.dialogContainer) {
// Close the application dialog menu
close(dlg);
@ -184,26 +192,26 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
return dlg.getAttribute('data-history') === 'true';
}
function open(dlg) {
export function open(dlg) {
if (globalOnOpenCallback) {
globalOnOpenCallback(dlg);
}
var parent = dlg.parentNode;
const parent = dlg.parentNode;
if (parent) {
parent.removeChild(dlg);
}
var dialogContainer = document.createElement('div');
const dialogContainer = document.createElement('div');
dialogContainer.classList.add('dialogContainer');
dialogContainer.appendChild(dlg);
dlg.dialogContainer = 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);
});
}
@ -213,7 +221,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
return !dlg.classList.contains('hide');
}
function close(dlg) {
export function close(dlg) {
if (isOpened(dlg)) {
if (isHistoryEnabled(dlg)) {
@ -233,7 +241,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
cancelable: false
}));
var onAnimationFinish = function () {
const onAnimationFinish = () => {
focusManager.popScope(dlg);
dlg.classList.add('hide');
@ -249,7 +257,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
function animateDialogOpen(dlg) {
var onAnimationFinish = function () {
const onAnimationFinish = () => {
focusManager.pushScope(dlg);
if (dlg.getAttribute('data-autofocus') === 'true') {
@ -264,7 +272,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
if (enableAnimation()) {
var onFinish = function () {
const onFinish = () => {
dom.removeEventListener(dlg, dom.whichAnimationEvent(), onFinish, {
once: true
});
@ -283,24 +291,24 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
if (enableAnimation()) {
var animated = true;
let animated = true;
switch (dlg.animationConfig.exit.name) {
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;
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;
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;
default:
animated = false;
break;
}
var onFinish = function () {
const onFinish = () => {
dom.removeEventListener(dlg, dom.whichAnimationEvent(), onFinish, {
once: true
});
@ -318,7 +326,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
onAnimationFinish();
}
var supportsOverscrollBehavior = 'overscroll-behavior-y' in document.body.style;
const supportsOverscrollBehavior = 'overscroll-behavior-y' in document.body.style;
function shouldLockDocumentScroll(options) {
@ -343,7 +351,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
function removeBackdrop(dlg) {
var backdrop = dlg.backdrop;
const backdrop = dlg.backdrop;
if (!backdrop) {
return;
@ -351,7 +359,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
dlg.backdrop = null;
var onAnimationFinish = function () {
const onAnimationFinish = () => {
tryRemoveElement(backdrop);
};
@ -368,20 +376,20 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
}
function centerFocus(elem, horiz, on) {
require(['scrollHelper'], function (scrollHelper) {
var fn = on ? 'on' : 'off';
import('scrollHelper').then(scrollHelper => {
const fn = on ? 'on' : 'off';
scrollHelper.centerFocus[fn](elem, horiz);
});
}
function createDialog(options) {
export function createDialog(options) {
options = options || {};
// If there's no native dialog support, use a plain div
// 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
var dlg = document.createElement('div');
const dlg = document.createElement('div');
dlg.classList.add('focuscontainer');
dlg.classList.add('hide');
@ -406,17 +414,17 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
dlg.setAttribute('data-autofocus', 'true');
}
var defaultEntryAnimation;
var defaultExitAnimation;
let defaultEntryAnimation;
let defaultExitAnimation;
defaultEntryAnimation = 'scaleup';
defaultExitAnimation = 'scaledown';
var entryAnimation = options.entryAnimation || defaultEntryAnimation;
var exitAnimation = options.exitAnimation || defaultExitAnimation;
const entryAnimation = options.entryAnimation || defaultEntryAnimation;
const exitAnimation = options.exitAnimation || defaultExitAnimation;
// 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);
var exitAnimationDuration = options.exitAnimationDuration || (options.size !== 'fullscreen' ? 120 : 220);
const entryAnimationDuration = options.entryAnimationDuration || (options.size !== 'fullscreen' ? 180 : 280);
const exitAnimationDuration = options.exitAnimationDuration || (options.size !== 'fullscreen' ? 120 : 220);
dlg.animationConfig = {
// scale up
@ -461,7 +469,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
if (options.size) {
dlg.classList.add('dialog-fixedSize');
dlg.classList.add('dialog-' + options.size);
dlg.classList.add(`dialog-${options.size}`);
}
if (enableAnimation()) {
@ -469,16 +477,16 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
switch (dlg.animationConfig.entry.name) {
case 'fadein':
dlg.style.animation = 'fadein ' + entryAnimationDuration + 'ms ease-out normal';
dlg.style.animation = `fadein ${entryAnimationDuration}ms ease-out normal`;
break;
case 'scaleup':
dlg.style.animation = 'scaleup ' + entryAnimationDuration + 'ms ease-out normal both';
dlg.style.animation = `scaleup ${entryAnimationDuration}ms ease-out normal both`;
break;
case 'slideup':
dlg.style.animation = 'slideup ' + entryAnimationDuration + 'ms ease-out normal';
dlg.style.animation = `slideup ${entryAnimationDuration}ms ease-out normal`;
break;
case 'slidedown':
dlg.style.animation = 'slidedown ' + entryAnimationDuration + 'ms ease-out normal';
dlg.style.animation = `slidedown ${entryAnimationDuration}ms ease-out normal`;
break;
default:
break;
@ -488,12 +496,15 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
return dlg;
}
return {
export function setOnOpen(val) {
globalOnOpenCallback = val;
}
/* eslint-enable indent */
export default {
open: open,
close: close,
createDialog: createDialog,
setOnOpen: function (val) {
globalOnOpenCallback = val;
}
};
});
setOnOpen: setOnOpen
};

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

View file

@ -1,22 +1,37 @@
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) {
'use strict';
import browser from 'browser';
import layoutManager from 'layoutManager';
import appSettings from 'appSettings';
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 connectionManager from 'connectionManager';
import skinManager from 'skinManager';
import events from 'events';
import 'emby-select';
import 'emby-checkbox';
import 'emby-button';
/* eslint-disable indent */
function fillThemes(select, isDashboard) {
select.innerHTML = skinManager.getThemes().map(function (t) {
var value = t.id;
select.innerHTML = skinManager.getThemes().map(t => {
let value = t.id;
if (t.isDefault && !isDashboard) {
value = '';
} else if (t.isDefaultServerDashboard && isDashboard) {
value = '';
}
return '<option value="' + value + '">' + t.name + '</option>';
return `<option value="${value}">${t.name}</option>`;
}).join('');
}
function loadScreensavers(context, userSettings) {
var selectScreensaver = context.querySelector('.selectScreensaver');
var options = pluginManager.ofType('screensaver').map(function (plugin) {
const selectScreensaver = context.querySelector('.selectScreensaver');
const options = pluginManager.ofType('screensaver').map(plugin => {
return {
name: plugin.name,
value: plugin.id
@ -28,8 +43,8 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
value: 'none'
});
selectScreensaver.innerHTML = options.map(function (o) {
return '<option value="' + o.value + '">' + o.name + '</option>';
selectScreensaver.innerHTML = options.map(o => {
return `<option value="${o.value}">${o.name}</option>`;
}).join('');
selectScreensaver.value = userSettings.screensaver();
@ -41,8 +56,8 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
function loadSoundEffects(context, userSettings) {
var selectSoundEffects = context.querySelector('.selectSoundEffects');
var options = pluginManager.ofType('soundeffects').map(function (plugin) {
const selectSoundEffects = context.querySelector('.selectSoundEffects');
const options = pluginManager.ofType('soundeffects').map(plugin => {
return {
name: plugin.name,
value: plugin.id
@ -54,8 +69,8 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
value: 'none'
});
selectSoundEffects.innerHTML = options.map(function (o) {
return '<option value="' + o.value + '">' + o.name + '</option>';
selectSoundEffects.innerHTML = options.map(o => {
return `<option value="${o.value}">${o.name}</option>`;
}).join('');
selectSoundEffects.value = userSettings.soundEffects();
@ -67,17 +82,17 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
function loadSkins(context, userSettings) {
var selectSkin = context.querySelector('.selectSkin');
const selectSkin = context.querySelector('.selectSkin');
var options = pluginManager.ofType('skin').map(function (plugin) {
const options = pluginManager.ofType('skin').map(plugin => {
return {
name: plugin.name,
value: plugin.id
};
});
selectSkin.innerHTML = options.map(function (o) {
return '<option value="' + o.value + '">' + o.name + '</option>';
selectSkin.innerHTML = options.map(o => {
return `<option value="${o.value}">${o.name}</option>`;
}).join('');
selectSkin.value = userSettings.skin();
@ -92,7 +107,7 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
}
}
function showOrHideMissingEpisodesField(context, user, apiClient) {
function showOrHideMissingEpisodesField(context) {
if (browser.tizen || browser.web0s) {
context.querySelector('.fldDisplayMissingEpisodes').classList.add('hide');
@ -102,10 +117,7 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
context.querySelector('.fldDisplayMissingEpisodes').classList.remove('hide');
}
function loadForm(context, user, userSettings, apiClient) {
var loggedInUserId = apiClient.getCurrentUserId();
var userId = user.Id;
function loadForm(context, user, userSettings) {
if (user.Policy.IsAdministrator) {
context.querySelector('.selectDashboardThemeContainer').classList.remove('hide');
@ -167,8 +179,8 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
context.querySelector('.chkRunAtStartup').checked = appSettings.runAtStartup();
var selectTheme = context.querySelector('#selectTheme');
var selectDashboardTheme = context.querySelector('#selectDashboardTheme');
const selectTheme = context.querySelector('#selectTheme');
const selectDashboardTheme = context.querySelector('#selectDashboardTheme');
fillThemes(selectTheme);
fillThemes(selectDashboardTheme, true);
@ -181,6 +193,7 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
context.querySelector('#chkThemeSong').checked = userSettings.enableThemeSongs();
context.querySelector('#chkThemeVideo').checked = userSettings.enableThemeVideos();
context.querySelector('#chkFadein').checked = userSettings.enableFastFadein();
context.querySelector('#chkBlurhash').checked = userSettings.enableBlurhash();
context.querySelector('#chkBackdrops').checked = userSettings.enableBackdrops();
context.querySelector('#chkDetailsBanner').checked = userSettings.detailsBanner();
@ -194,7 +207,7 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
context.querySelector('.selectLayout').value = layoutManager.getSavedLayout() || '';
showOrHideMissingEpisodesField(context, user, apiClient);
showOrHideMissingEpisodesField(context);
loading.hide();
}
@ -223,6 +236,7 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
userSettingsInstance.skin(context.querySelector('.selectSkin').value);
userSettingsInstance.enableFastFadein(context.querySelector('#chkFadein').checked);
userSettingsInstance.enableBlurhash(context.querySelector('#chkBlurhash').checked);
userSettingsInstance.enableBackdrops(context.querySelector('#chkBackdrops').checked);
userSettingsInstance.detailsBanner(context.querySelector('#chkDetailsBanner').checked);
@ -237,29 +251,29 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
function save(instance, context, userId, userSettings, apiClient, enableSaveConfirmation) {
loading.show();
apiClient.getUser(userId).then(function (user) {
saveUser(context, user, userSettings, apiClient).then(function () {
apiClient.getUser(userId).then(user => {
saveUser(context, user, userSettings, apiClient).then(() => {
loading.hide();
if (enableSaveConfirmation) {
require(['toast'], function (toast) {
import('toast').then(({default: toast}) => {
toast(globalize.translate('SettingsSaved'));
});
}
events.trigger(instance, 'saved');
}, function () {
}, () => {
loading.hide();
});
});
}
function onSubmit(e) {
var self = this;
var apiClient = connectionManager.getApiClient(self.options.serverId);
var userId = self.options.userId;
var userSettings = self.options.userSettings;
const self = this;
const apiClient = connectionManager.getApiClient(self.options.serverId);
const userId = self.options.userId;
const userSettings = self.options.userSettings;
userSettings.setUserInfo(userId, apiClient).then(function () {
var enableSaveConfirmation = self.options.enableSaveConfirmation;
userSettings.setUserInfo(userId, apiClient).then(() => {
const enableSaveConfirmation = self.options.enableSaveConfirmation;
save(self, self.options.element, userId, userSettings, apiClient, enableSaveConfirmation);
});
@ -270,50 +284,51 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
return false;
}
function embed(options, self) {
require(['text!./displaySettings.template.html'], function (template) {
options.element.innerHTML = globalize.translateDocument(template, 'core');
async function embed(options, self) {
const { default: template } = await import('text!./displaySettings.template.html');
options.element.innerHTML = globalize.translateHtml(template, 'core');
options.element.querySelector('form').addEventListener('submit', onSubmit.bind(self));
if (options.enableSaveButton) {
options.element.querySelector('.btnSave').classList.remove('hide');
}
self.loadData(options.autoFocus);
});
}
function DisplaySettings(options) {
class DisplaySettings {
constructor(options) {
this.options = options;
embed(options, this);
}
DisplaySettings.prototype.loadData = function (autoFocus) {
var self = this;
var context = self.options.element;
loadData(autoFocus) {
const self = this;
const context = self.options.element;
loading.show();
var userId = self.options.userId;
var apiClient = connectionManager.getApiClient(self.options.serverId);
var userSettings = self.options.userSettings;
const userId = self.options.userId;
const apiClient = connectionManager.getApiClient(self.options.serverId);
const userSettings = self.options.userSettings;
return apiClient.getUser(userId).then(function (user) {
return userSettings.setUserInfo(userId, apiClient).then(function () {
return apiClient.getUser(userId).then(user => {
return userSettings.setUserInfo(userId, apiClient).then(() => {
self.dataLoaded = true;
loadForm(context, user, userSettings, apiClient);
loadForm(context, user, userSettings);
if (autoFocus) {
focusManager.autoFocus(context);
}
});
});
};
}
DisplaySettings.prototype.submit = function () {
submit() {
onSubmit.call(this);
};
}
DisplaySettings.prototype.destroy = function () {
destroy() {
this.options = null;
};
}
}
return DisplaySettings;
});
/* eslint-enable indent */
export default DisplaySettings;

View file

@ -143,20 +143,28 @@
<select is="emby-select" class="selectSoundEffects" label="${LabelSoundEffects}"></select>
</div>
<div class="inputContainer inputContainer-withDescription fldFadein">
<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}" />
<div class="fieldDescription">${LabelLibraryPageSizeHelp}</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription fldFadein">
<div class="checkboxContainer checkboxContainer-withDescription">
<label>
<input type="checkbox" is="emby-checkbox" id="chkFadein" />
<span>${EnableFastImageFadeIn}</span>
<span>${EnableFasterAnimations}</span>
</label>
<div class="fieldDescription checkboxFieldDescription">${EnableFastImageFadeInHelp}</div>
<div class="fieldDescription checkboxFieldDescription">${EnableFasterAnimationsHelp}</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription fldDetailsBanner">
<div class="checkboxContainer checkboxContainer-withDescription">
<label>
<input type="checkbox" is="emby-checkbox" id="chkBlurhash" />
<span>${EnableBlurhash}</span>
</label>
<div class="fieldDescription checkboxFieldDescription">${EnableBlurhashHelp}</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label>
<input type="checkbox" is="emby-checkbox" id="chkDetailsBanner" />
<span>${EnableDetailsBanner}</span>

View file

@ -1,21 +1,19 @@
define([], function () {
'use strict';
/* eslint-disable indent */
export function getFetchPromise(request) {
function getFetchPromise(request) {
var headers = request.headers || {};
const headers = request.headers || {};
if (request.dataType === 'json') {
headers.accept = 'application/json';
}
var fetchRequest = {
const fetchRequest = {
headers: headers,
method: request.type,
credentials: 'same-origin'
};
var contentType = request.contentType;
let contentType = request.contentType;
if (request.data) {
@ -33,12 +31,12 @@ define([], function () {
headers['Content-Type'] = contentType;
}
var url = request.url;
let url = request.url;
if (request.query) {
var paramString = paramsToString(request.query);
const paramString = paramsToString(request.query);
if (paramString) {
url += '?' + paramString;
url += `?${paramString}`;
}
}
@ -51,11 +49,11 @@ define([], function () {
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) {
var timeout = setTimeout(reject, timeoutMs);
const timeout = setTimeout(reject, timeoutMs);
options = options || {};
options.credentials = 'same-origin';
@ -63,50 +61,47 @@ define([], function () {
fetch(url, options).then(function (response) {
clearTimeout(timeout);
console.debug('fetchWithTimeout: succeeded connecting to url: ' + url);
console.debug(`fetchWithTimeout: succeeded connecting to url: ${url}`);
resolve(response);
}, function (error) {
clearTimeout(timeout);
console.debug('fetchWithTimeout: timed out connecting to url: ' + url);
console.debug(`fetchWithTimeout: timed out connecting to url: ${url}`);
reject();
reject(error);
});
});
}
/**
* @param params {Record<string, string | number | boolean>}
* @returns {string} Query string
*/
function paramsToString(params) {
var values = [];
for (var key in params) {
var value = params[key];
if (value !== null && value !== undefined && value !== '') {
values.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
}
}
return values.join('&');
return Object.entries(params)
// eslint-disable-next-line no-unused-vars
.filter(([_, v]) => v !== null && v !== undefined && v !== '')
.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
.join('&');
}
function ajax(request) {
export function ajax(request) {
if (!request) {
throw new Error('Request cannot be null');
}
request.headers = request.headers || {};
console.debug('requesting url: ' + request.url);
console.debug(`requesting url: ${request.url}`);
return getFetchPromise(request).then(function (response) {
console.debug('response status: ' + response.status + ', url: ' + request.url);
console.debug(`response status: ${response.status}, url: ${request.url}`);
if (response.status < 400) {
if (request.dataType === 'json' || request.headers.accept === 'application/json') {
return response.json();
} else if (request.dataType === 'text' || (response.headers.get('Content-Type') || '').toLowerCase().indexOf('text/') === 0) {
} else if (request.dataType === 'text' || (response.headers.get('Content-Type') || '').toLowerCase().startsWith('text/')) {
return response.text();
} else {
return response;
@ -115,12 +110,8 @@ define([], function () {
return Promise.reject(response);
}
}, function (err) {
console.error('request failed to url: ' + request.url);
console.error(`request failed to url: ${request.url}`);
throw err;
});
}
return {
getFetchPromise: getFetchPromise,
ajax: ajax
};
});
/* eslint-enable indent */

View file

@ -1,21 +1,28 @@
define(['dom', 'dialogHelper', 'globalize', 'connectionManager', 'events', 'browser', 'require', 'emby-checkbox', 'emby-collapse', 'css!./style'], function (dom, dialogHelper, globalize, connectionManager, events, browser, require) {
'use strict';
import dom from 'dom';
import dialogHelper from 'dialogHelper';
import globalize from 'globalize';
import connectionManager from 'connectionManager';
import events from 'events';
import 'emby-checkbox';
import 'emby-collapse';
import 'css!./style.css';
/* eslint-disable indent */
function renderOptions(context, selector, cssClass, items, isCheckedFn) {
var elem = context.querySelector(selector);
const elem = context.querySelector(selector);
if (items.length) {
elem.classList.remove('hide');
} else {
elem.classList.add('hide');
}
var html = '';
let html = '';
html += '<div class="checkboxList">';
html += items.map(function (filter) {
var itemHtml = '';
var checkedHtml = isCheckedFn(filter) ? ' checked' : '';
let itemHtml = '';
const checkedHtml = isCheckedFn(filter) ? 'checked' : '';
itemHtml += '<label>';
itemHtml += '<input is="emby-checkbox" type="checkbox"' + checkedHtml + ' data-filter="' + filter + '" class="' + cssClass + '"/>';
itemHtml += '<span>' + filter + '</span>';
itemHtml += `<input is="emby-checkbox" type="checkbox" ${checkedHtml} data-filter="${filter}" class="${cssClass}"/>`;
itemHtml += `<span>${filter}</span>`;
itemHtml += '</label>';
return itemHtml;
}).join('');
@ -24,21 +31,24 @@ define(['dom', 'dialogHelper', 'globalize', 'connectionManager', 'events', 'brow
}
function renderFilters(context, result, query) {
if (result.Tags) {
result.Tags.length = Math.min(result.Tags.length, 50);
}
renderOptions(context, '.genreFilters', 'chkGenreFilter', result.Genres, function (i) {
var delimeter = '|';
return (delimeter + (query.Genres || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
const delimeter = '|';
return (delimeter + (query.Genres || '') + delimeter).includes(delimeter + i + delimeter);
});
renderOptions(context, '.officialRatingFilters', 'chkOfficialRatingFilter', result.OfficialRatings, function (i) {
var delimeter = '|';
return (delimeter + (query.OfficialRatings || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
const delimeter = '|';
return (delimeter + (query.OfficialRatings || '') + delimeter).includes(delimeter + i + delimeter);
});
renderOptions(context, '.tagFilters', 'chkTagFilter', result.Tags, function (i) {
var delimeter = '|';
return (delimeter + (query.Tags || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
const delimeter = '|';
return (delimeter + (query.Tags || '') + delimeter).includes(delimeter + i + delimeter);
});
renderOptions(context, '.yearFilters', 'chkYearFilter', result.Years, function (i) {
var delimeter = ',';
return (delimeter + (query.Years || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
const delimeter = ',';
return (delimeter + (query.Years || '') + delimeter).includes(delimeter + i + delimeter);
});
}
@ -52,59 +62,58 @@ define(['dom', 'dialogHelper', 'globalize', 'connectionManager', 'events', 'brow
});
}
/**
* @param context {HTMLDivElement} Dialog
* @param options {any} Options
*/
function updateFilterControls(context, options) {
var elems;
var i;
var length;
var query = options.query;
const query = options.query;
if (options.mode == 'livetvchannels') {
context.querySelector('.chkFavorite').checked = query.IsFavorite == true;
context.querySelector('.chkLikes').checked = query.IsLiked == true;
context.querySelector('.chkDislikes').checked = query.IsDisliked == true;
if (options.mode === 'livetvchannels') {
context.querySelector('.chkFavorite').checked = query.IsFavorite === true;
context.querySelector('.chkLikes').checked = query.IsLiked === true;
context.querySelector('.chkDislikes').checked = query.IsDisliked === true;
} else {
elems = context.querySelectorAll('.chkStandardFilter');
for (i = 0, length = elems.length; i < length; i++) {
var chkStandardFilter = elems[i];
var filters = ',' + (query.Filters || '');
var filterName = chkStandardFilter.getAttribute('data-filter');
chkStandardFilter.checked = filters.indexOf(',' + filterName) != -1;
for (const elem of context.querySelectorAll('.chkStandardFilter')) {
const filters = `,${query.Filters || ''}`;
const filterName = elem.getAttribute('data-filter');
elem.checked = filters.includes(`,${filterName}`);
}
}
elems = context.querySelectorAll('.chkVideoTypeFilter');
for (i = 0, length = elems.length; i < length; i++) {
var chkVideoTypeFilter = elems[i];
var filters = ',' + (query.VideoTypes || '');
var filterName = chkVideoTypeFilter.getAttribute('data-filter');
chkVideoTypeFilter.checked = filters.indexOf(',' + filterName) != -1;
for (const elem of context.querySelectorAll('.chkVideoTypeFilter')) {
const filters = `,${query.VideoTypes || ''}`;
const filterName = elem.getAttribute('data-filter');
elem.checked = filters.includes(`,${filterName}`);
}
context.querySelector('.chk3DFilter').checked = query.Is3D == true;
context.querySelector('.chkHDFilter').checked = query.IsHD == true;
context.querySelector('.chk4KFilter').checked = query.Is4K == true;
context.querySelector('.chkSDFilter').checked = query.IsHD == true;
context.querySelector('#chkSubtitle').checked = query.HasSubtitles == true;
context.querySelector('#chkTrailer').checked = query.HasTrailer == true;
context.querySelector('#chkThemeSong').checked = query.HasThemeSong == true;
context.querySelector('#chkThemeVideo').checked = query.HasThemeVideo == true;
context.querySelector('#chkSpecialFeature').checked = query.HasSpecialFeature == true;
context.querySelector('#chkSpecialEpisode').checked = query.ParentIndexNumber == 0;
context.querySelector('#chkMissingEpisode').checked = query.IsMissing == true;
context.querySelector('#chkFutureEpisode').checked = query.IsUnaired == true;
for (i = 0, length = elems.length; i < length; i++) {
var chkStatus = elems[i];
var filters = ',' + (query.SeriesStatus || '');
var filterName = chkStatus.getAttribute('data-filter');
chkStatus.checked = filters.indexOf(',' + filterName) != -1;
context.querySelector('.chk3DFilter').checked = query.Is3D === true;
context.querySelector('.chkHDFilter').checked = query.IsHD === true;
context.querySelector('.chk4KFilter').checked = query.Is4K === true;
context.querySelector('.chkSDFilter').checked = query.IsHD === true;
context.querySelector('#chkSubtitle').checked = query.HasSubtitles === true;
context.querySelector('#chkTrailer').checked = query.HasTrailer === true;
context.querySelector('#chkThemeSong').checked = query.HasThemeSong === true;
context.querySelector('#chkThemeVideo').checked = query.HasThemeVideo === true;
context.querySelector('#chkSpecialFeature').checked = query.HasSpecialFeature === true;
context.querySelector('#chkSpecialEpisode').checked = query.ParentIndexNumber === 0;
context.querySelector('#chkMissingEpisode').checked = query.IsMissing === true;
context.querySelector('#chkFutureEpisode').checked = query.IsUnaired === true;
for (const elem of context.querySelectorAll('.chkStatus')) {
const filters = `,${query.SeriesStatus || ''}`;
const filterName = elem.getAttribute('data-filter');
elem.checked = filters.includes(`,${filterName}`);
}
}
/**
* @param instance {FilterDialog} An instance of FilterDialog
*/
function triggerChange(instance) {
events.trigger(instance, 'filterchange');
}
function setVisibility(context, options) {
if (options.mode == 'livetvchannels' || options.mode == 'albums' || options.mode == 'artists' || options.mode == 'albumartists' || options.mode == 'songs') {
if (options.mode === 'livetvchannels' || options.mode === 'albums' || options.mode === 'artists' || options.mode === 'albumartists' || options.mode === 'songs') {
hideByClass(context, 'videoStandard');
}
@ -115,263 +124,287 @@ define(['dom', 'dialogHelper', 'globalize', 'connectionManager', 'events', 'brow
context.querySelector('.yearFilters').classList.remove('hide');
}
if (options.mode == 'movies' || options.mode == 'episodes') {
if (options.mode === 'movies' || options.mode === 'episodes') {
context.querySelector('.videoTypeFilters').classList.remove('hide');
}
if (options.mode == 'movies' || options.mode == 'series' || options.mode == 'episodes') {
if (options.mode === 'movies' || options.mode === 'series' || options.mode === 'episodes') {
context.querySelector('.features').classList.remove('hide');
}
if (options.mode == 'series') {
if (options.mode === 'series') {
context.querySelector('.seriesStatus').classList.remove('hide');
}
if (options.mode == 'episodes') {
if (options.mode === 'episodes') {
showByClass(context, 'episodeFilter');
}
}
function showByClass(context, className) {
var elems = context.querySelectorAll('.' + className);
for (var i = 0, length = elems.length; i < length; i++) {
elems[i].classList.remove('hide');
for (const elem of context.querySelectorAll(`.${className}`)) {
elem.classList.remove('hide');
}
}
function hideByClass(context, className) {
var elems = context.querySelectorAll('.' + className);
for (var i = 0, length = elems.length; i < length; i++) {
elems[i].classList.add('hide');
for (const elem of context.querySelectorAll(`.${className}`)) {
elem.classList.add('hide');
}
}
function enableDynamicFilters(mode) {
return mode == 'movies' || mode == 'series' || mode == 'albums' || mode == 'albumartists' || mode == 'artists' || mode == 'songs' || mode == 'episodes';
return mode === 'movies' || mode === 'series' || mode === 'albums' || mode === 'albumartists' || mode === 'artists' || mode === 'songs' || mode === 'episodes';
}
return function (options) {
function onFavoriteChange() {
var query = options.query;
class FilterDialog {
constructor(options) {
/**
* @private
*/
this.options = options;
}
/**
* @private
*/
onFavoriteChange(elem) {
const query = this.options.query;
query.StartIndex = 0;
query.IsFavorite = !!this.checked || null;
triggerChange(self);
query.IsFavorite = !!elem.checked || null;
triggerChange(this);
}
function onStandardFilterChange() {
var query = options.query;
var filterName = this.getAttribute('data-filter');
var filters = query.Filters || '';
filters = (',' + filters).replace(',' + filterName, '').substring(1);
/**
* @private
*/
onStandardFilterChange(elem) {
const query = this.options.query;
const filterName = elem.getAttribute('data-filter');
let filters = query.Filters || '';
filters = (`,${filters}`).replace(`,${filterName}`, '').substring(1);
if (this.checked) {
filters = filters ? filters + ',' + filterName : filterName;
if (elem.checked) {
filters = filters ? `${filters},${filterName}` : filterName;
}
query.StartIndex = 0;
query.Filters = filters;
triggerChange(self);
triggerChange(this);
}
function onVideoTypeFilterChange() {
var query = options.query;
var filterName = this.getAttribute('data-filter');
var filters = query.VideoTypes || '';
filters = (',' + filters).replace(',' + filterName, '').substring(1);
/**
* @private
*/
onVideoTypeFilterChange(elem) {
const query = this.options.query;
const filterName = elem.getAttribute('data-filter');
let filters = query.VideoTypes || '';
filters = (`,${filters}`).replace(`,${filterName}`, '').substring(1);
if (this.checked) {
filters = filters ? filters + ',' + filterName : filterName;
if (elem.checked) {
filters = filters ? `${filters},${filterName}` : filterName;
}
query.StartIndex = 0;
query.VideoTypes = filters;
triggerChange(self);
triggerChange(this);
}
function onStatusChange() {
var query = options.query;
var filterName = this.getAttribute('data-filter');
var filters = query.SeriesStatus || '';
filters = (',' + filters).replace(',' + filterName, '').substring(1);
/**
* @private
*/
onStatusChange(elem) {
const query = this.options.query;
const filterName = elem.getAttribute('data-filter');
let filters = query.SeriesStatus || '';
filters = (`,${filters}`).replace(`,${filterName}`, '').substring(1);
if (this.checked) {
filters = filters ? filters + ',' + filterName : filterName;
if (elem.checked) {
filters = filters ? `${filters},${filterName}` : filterName;
}
query.SeriesStatus = filters;
query.StartIndex = 0;
triggerChange(self);
triggerChange(this);
}
function bindEvents(context) {
var elems;
var i;
var length;
var query = options.query;
/**
* @param context {HTMLDivElement} The dialog
*/
bindEvents(context) {
const query = this.options.query;
if (options.mode == 'livetvchannels') {
elems = context.querySelectorAll('.chkFavorite');
for (i = 0, length = elems.length; i < length; i++) {
elems[i].addEventListener('change', onFavoriteChange);
if (this.options.mode === 'livetvchannels') {
for (const elem of context.querySelectorAll('.chkFavorite')) {
elem.addEventListener('change', () => this.onFavoriteChange(elem));
}
context.querySelector('.chkLikes').addEventListener('change', function () {
const chkLikes = context.querySelector('.chkLikes');
chkLikes.addEventListener('change', () => {
query.StartIndex = 0;
query.IsLiked = this.checked ? true : null;
triggerChange(self);
query.IsLiked = chkLikes.checked ? true : null;
triggerChange(this);
});
context.querySelector('.chkDislikes').addEventListener('change', function () {
const chkDislikes = context.querySelector('.chkDislikes');
chkDislikes.addEventListener('change', () => {
query.StartIndex = 0;
query.IsDisliked = this.checked ? true : null;
triggerChange(self);
query.IsDisliked = chkDislikes.checked ? true : null;
triggerChange(this);
});
} else {
elems = context.querySelectorAll('.chkStandardFilter');
for (i = 0, length = elems.length; i < length; i++) {
elems[i].addEventListener('change', onStandardFilterChange);
for (const elem of context.querySelectorAll('.chkStandardFilter')) {
elem.addEventListener('change', () => this.onStandardFilterChange(elem));
}
}
elems = context.querySelectorAll('.chkVideoTypeFilter');
for (i = 0, length = elems.length; i < length; i++) {
elems[i].addEventListener('change', onVideoTypeFilterChange);
for (const elem of context.querySelectorAll('.chkVideoTypeFilter')) {
elem.addEventListener('change', () => this.onVideoTypeFilterChange(elem));
}
context.querySelector('.chk3DFilter').addEventListener('change', function () {
const chk3DFilter = context.querySelector('.chk3DFilter');
chk3DFilter.addEventListener('change', () => {
query.StartIndex = 0;
query.Is3D = this.checked ? true : null;
triggerChange(self);
query.Is3D = chk3DFilter.checked ? true : null;
triggerChange(this);
});
context.querySelector('.chk4KFilter').addEventListener('change', function () {
const chk4KFilter = context.querySelector('.chk4KFilter');
chk4KFilter.addEventListener('change', () => {
query.StartIndex = 0;
query.Is4K = this.checked ? true : null;
triggerChange(self);
query.Is4K = chk4KFilter.checked ? true : null;
triggerChange(this);
});
context.querySelector('.chkHDFilter').addEventListener('change', function () {
const chkHDFilter = context.querySelector('.chkHDFilter');
chkHDFilter.addEventListener('change', () => {
query.StartIndex = 0;
query.IsHD = this.checked ? true : null;
triggerChange(self);
query.IsHD = chkHDFilter.checked ? true : null;
triggerChange(this);
});
context.querySelector('.chkSDFilter').addEventListener('change', function () {
const chkSDFilter = context.querySelector('.chkSDFilter');
chkSDFilter.addEventListener('change', () => {
query.StartIndex = 0;
query.IsHD = this.checked ? false : null;
triggerChange(self);
query.IsHD = chkSDFilter.checked ? false : null;
triggerChange(this);
});
elems = context.querySelectorAll('.chkStatus');
for (i = 0, length = elems.length; i < length; i++) {
elems[i].addEventListener('change', onStatusChange);
for (const elem of context.querySelectorAll('.chkStatus')) {
elem.addEventListener('change', () => this.onStatusChange(elem));
}
context.querySelector('#chkTrailer').addEventListener('change', function () {
const chkTrailer = context.querySelector('#chkTrailer');
chkTrailer.addEventListener('change', () => {
query.StartIndex = 0;
query.HasTrailer = this.checked ? true : null;
triggerChange(self);
query.HasTrailer = chkTrailer.checked ? true : null;
triggerChange(this);
});
context.querySelector('#chkThemeSong').addEventListener('change', function () {
const chkThemeSong = context.querySelector('#chkThemeSong');
chkThemeSong.addEventListener('change', () => {
query.StartIndex = 0;
query.HasThemeSong = this.checked ? true : null;
triggerChange(self);
query.HasThemeSong = chkThemeSong.checked ? true : null;
triggerChange(this);
});
context.querySelector('#chkSpecialFeature').addEventListener('change', function () {
const chkSpecialFeature = context.querySelector('#chkSpecialFeature');
chkSpecialFeature.addEventListener('change', () => {
query.StartIndex = 0;
query.HasSpecialFeature = this.checked ? true : null;
triggerChange(self);
query.HasSpecialFeature = chkSpecialFeature.checked ? true : null;
triggerChange(this);
});
context.querySelector('#chkThemeVideo').addEventListener('change', function () {
const chkThemeVideo = context.querySelector('#chkThemeVideo');
chkThemeVideo.addEventListener('change', () => {
query.StartIndex = 0;
query.HasThemeVideo = this.checked ? true : null;
triggerChange(self);
query.HasThemeVideo = chkThemeVideo.checked ? true : null;
triggerChange(this);
});
context.querySelector('#chkMissingEpisode').addEventListener('change', function () {
const chkMissingEpisode = context.querySelector('#chkMissingEpisode');
chkMissingEpisode.addEventListener('change', () => {
query.StartIndex = 0;
query.IsMissing = this.checked ? true : false;
triggerChange(self);
query.IsMissing = !!chkMissingEpisode.checked;
triggerChange(this);
});
context.querySelector('#chkSpecialEpisode').addEventListener('change', function () {
const chkSpecialEpisode = context.querySelector('#chkSpecialEpisode');
chkSpecialEpisode.addEventListener('change', () => {
query.StartIndex = 0;
query.ParentIndexNumber = this.checked ? 0 : null;
triggerChange(self);
query.ParentIndexNumber = chkSpecialEpisode.checked ? 0 : null;
triggerChange(this);
});
context.querySelector('#chkFutureEpisode').addEventListener('change', function () {
const chkFutureEpisode = context.querySelector('#chkFutureEpisode');
chkFutureEpisode.addEventListener('change', () => {
query.StartIndex = 0;
if (this.checked) {
if (chkFutureEpisode.checked) {
query.IsUnaired = true;
query.IsVirtualUnaired = null;
} else {
query.IsUnaired = null;
query.IsVirtualUnaired = false;
}
triggerChange(self);
triggerChange(this);
});
context.querySelector('#chkSubtitle').addEventListener('change', function () {
const chkSubtitle = context.querySelector('#chkSubtitle');
chkSubtitle.addEventListener('change', () => {
query.StartIndex = 0;
query.HasSubtitles = this.checked ? true : null;
triggerChange(self);
query.HasSubtitles = chkSubtitle.checked ? true : null;
triggerChange(this);
});
context.addEventListener('change', function (e) {
var chkGenreFilter = dom.parentWithClass(e.target, 'chkGenreFilter');
context.addEventListener('change', (e) => {
const chkGenreFilter = dom.parentWithClass(e.target, 'chkGenreFilter');
if (chkGenreFilter) {
var filterName = chkGenreFilter.getAttribute('data-filter');
var filters = query.Genres || '';
var delimiter = '|';
const filterName = chkGenreFilter.getAttribute('data-filter');
let filters = query.Genres || '';
const delimiter = '|';
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
if (chkGenreFilter.checked) {
filters = filters ? (filters + delimiter + filterName) : filterName;
}
query.StartIndex = 0;
query.Genres = filters;
triggerChange(self);
triggerChange(this);
return;
}
var chkTagFilter = dom.parentWithClass(e.target, 'chkTagFilter');
const chkTagFilter = dom.parentWithClass(e.target, 'chkTagFilter');
if (chkTagFilter) {
var filterName = chkTagFilter.getAttribute('data-filter');
var filters = query.Tags || '';
var delimiter = '|';
const filterName = chkTagFilter.getAttribute('data-filter');
let filters = query.Tags || '';
const delimiter = '|';
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
if (chkTagFilter.checked) {
filters = filters ? (filters + delimiter + filterName) : filterName;
}
query.StartIndex = 0;
query.Tags = filters;
triggerChange(self);
triggerChange(this);
return;
}
var chkYearFilter = dom.parentWithClass(e.target, 'chkYearFilter');
const chkYearFilter = dom.parentWithClass(e.target, 'chkYearFilter');
if (chkYearFilter) {
var filterName = chkYearFilter.getAttribute('data-filter');
var filters = query.Years || '';
var delimiter = ',';
const filterName = chkYearFilter.getAttribute('data-filter');
let filters = query.Years || '';
const delimiter = ',';
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
if (chkYearFilter.checked) {
filters = filters ? (filters + delimiter + filterName) : filterName;
}
query.StartIndex = 0;
query.Years = filters;
triggerChange(self);
triggerChange(this);
return;
}
var chkOfficialRatingFilter = dom.parentWithClass(e.target, 'chkOfficialRatingFilter');
const chkOfficialRatingFilter = dom.parentWithClass(e.target, 'chkOfficialRatingFilter');
if (chkOfficialRatingFilter) {
var filterName = chkOfficialRatingFilter.getAttribute('data-filter');
var filters = query.OfficialRatings || '';
var delimiter = '|';
const filterName = chkOfficialRatingFilter.getAttribute('data-filter');
let filters = query.OfficialRatings || '';
const delimiter = '|';
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
if (chkOfficialRatingFilter.checked) {
filters = filters ? (filters + delimiter + filterName) : filterName;
}
query.StartIndex = 0;
query.OfficialRatings = filters;
triggerChange(self);
return;
triggerChange(this);
}
});
}
var self = this;
self.show = function () {
return new Promise(function (resolve, reject) {
require(['text!./filterdialog.template.html'], function (template) {
var dlg = dialogHelper.createDialog({
show() {
return import('text!./filterdialog.template.html').then(({default: template}) => {
return new Promise((resolve) => {
const dlg = dialogHelper.createDialog({
removeOnClose: true,
modal: false
});
@ -379,19 +412,22 @@ define(['dom', 'dialogHelper', 'globalize', 'connectionManager', 'events', 'brow
dlg.classList.add('background-theme-a');
dlg.classList.add('formDialog');
dlg.classList.add('filterDialog');
dlg.innerHTML = globalize.translateDocument(template);
setVisibility(dlg, options);
dlg.innerHTML = globalize.translateHtml(template);
setVisibility(dlg, this.options);
dialogHelper.open(dlg);
dlg.addEventListener('close', resolve);
updateFilterControls(dlg, options);
bindEvents(dlg);
if (enableDynamicFilters(options.mode)) {
updateFilterControls(dlg, this.options);
this.bindEvents(dlg);
if (enableDynamicFilters(this.options.mode)) {
dlg.classList.add('dynamicFilterDialog');
var apiClient = connectionManager.getApiClient(options.serverId);
loadDynamicFilters(dlg, apiClient, apiClient.getCurrentUserId(), options.query);
const apiClient = connectionManager.getApiClient(this.options.serverId);
loadDynamicFilters(dlg, apiClient, apiClient.getCurrentUserId(), this.options.query);
}
});
});
};
};
});
}
}
/* eslint-enable indent */
export default FilterDialog;

View file

@ -286,7 +286,7 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
html += template;
dlg.innerHTML = globalize.translateDocument(html, 'core');
dlg.innerHTML = globalize.translateHtml(html, 'core');
var settingElements = dlg.querySelectorAll('.viewSetting');
for (var i = 0, length = settingElements.length; i < length; i++) {

View file

@ -55,7 +55,7 @@
/* Without this emby-checkbox is able to appear on top */
z-index: 1;
align-items: flex-end;
justify-content: flex-end;
justify-content: center;
flex-wrap: wrap;
}

View file

@ -1,5 +1,8 @@
define(['dom', 'appRouter', 'connectionManager'], function (dom, appRouter, connectionManager) {
'use strict';
/* eslint-disable indent */
import dom from 'dom';
import appRouter from 'appRouter';
import connectionManager from 'connectionManager';
function onGroupedCardClick(e, card) {
var itemId = card.getAttribute('data-id');
@ -22,7 +25,7 @@ define(['dom', 'appRouter', 'connectionManager'], function (dom, appRouter, conn
return void appRouter.showItem(items[0]);
}
var url = 'itemdetails.html?id=' + itemId + '&serverId=' + serverId;
var url = 'details?id=' + itemId + '&serverId=' + serverId;
Dashboard.navigate(url);
});
e.stopPropagation();
@ -31,7 +34,7 @@ define(['dom', 'appRouter', 'connectionManager'], function (dom, appRouter, conn
}
}
function onItemsContainerClick(e) {
export default function onItemsContainerClick(e) {
var groupedCard = dom.parentWithClass(e.target, 'groupedCard');
if (groupedCard) {
@ -39,7 +42,4 @@ define(['dom', 'appRouter', 'connectionManager'], function (dom, appRouter, conn
}
}
return {
onItemsContainerClick: onItemsContainerClick
};
});
/* eslint-enable indent */

View file

@ -114,7 +114,7 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio
var html = '';
html += globalize.translateDocument(template, 'core');
html += globalize.translateHtml(template, 'core');
dlg.innerHTML = html;

View file

@ -1,4 +1,4 @@
define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', 'scrollHelper', 'serverNotifications', 'loading', 'datetime', 'focusManager', 'playbackManager', 'userSettings', 'imageLoader', 'events', 'layoutManager', 'itemShortcuts', 'dom', 'css!./guide.css', 'programStyles', 'material-icons', 'scrollStyles', 'emby-programcell', 'emby-button', 'paper-icon-button-light', 'emby-tabs', 'emby-scroller', 'flexStyles', 'registerElement'], function (require, inputManager, browser, globalize, connectionManager, scrollHelper, serverNotifications, loading, datetime, focusManager, playbackManager, userSettings, imageLoader, events, layoutManager, itemShortcuts, dom) {
define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', 'scrollHelper', 'serverNotifications', 'loading', 'datetime', 'focusManager', 'playbackManager', 'userSettings', 'imageLoader', 'events', 'layoutManager', 'itemShortcuts', 'dom', 'css!./guide.css', 'programStyles', 'material-icons', 'scrollStyles', 'emby-programcell', 'emby-button', 'paper-icon-button-light', 'emby-tabs', 'emby-scroller', 'flexStyles', 'webcomponents'], function (require, inputManager, browser, globalize, connectionManager, scrollHelper, serverNotifications, loading, datetime, focusManager, playbackManager, userSettings, imageLoader, events, layoutManager, itemShortcuts, dom) {
'use strict';
function showViewSettings(instance) {
@ -1151,7 +1151,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
context.classList.add('tvguide');
context.innerHTML = globalize.translateDocument(template, 'core');
context.innerHTML = globalize.translateHtml(template, 'core');
programGrid = context.querySelector('.programGrid');
var timeslotHeaders = context.querySelector('.timeslotHeaders');

View file

@ -1,26 +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) {
'use strict';
import layoutManager from 'layoutManager';
import focusManager from 'focusManager';
import globalize from 'globalize';
import loading from 'loading';
import connectionManager from 'connectionManager';
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) {
var folderHtml = '';
let folderHtml = '';
folderHtml += '<div class="checkboxList">';
folderHtml += result.map(function (i) {
folderHtml += result.map(i => {
var currentHtml = '';
let currentHtml = '';
var id = 'chkGroupFolder' + i.Id;
const id = `chkGroupFolder${i.Id}`;
var isChecked = user.Configuration.GroupedFolders.indexOf(i.Id) !== -1;
const isChecked = user.Configuration.GroupedFolders.includes(i.Id);
var checkedHtml = isChecked ? ' checked="checked"' : '';
const checkedHtml = isChecked ? ' checked="checked"' : '';
currentHtml += '<label>';
currentHtml += '<input type="checkbox" is="emby-checkbox" class="chkGroupFolder" data-folderid="' + i.Id + '" id="' + id + '"' + checkedHtml + '/>';
currentHtml += '<span>' + i.Name + '</span>';
currentHtml += `<input type="checkbox" is="emby-checkbox" class="chkGroupFolder" data-folderid="${i.Id}" id="${id}"${checkedHtml}/>`;
currentHtml += `<span>${i.Name}</span>`;
currentHtml += '</label>';
return currentHtml;
@ -34,7 +45,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
function getLandingScreenOptions(type) {
var list = [];
const list = [];
if (type === 'movies') {
list.push({
@ -123,27 +134,27 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
function getLandingScreenOptionsHtml(type, userValue) {
return getLandingScreenOptions(type).map(function (o) {
return getLandingScreenOptions(type).map(o => {
var selected = userValue === o.value || (o.isDefault && !userValue);
var selectedHtml = selected ? ' selected' : '';
var optionValue = o.isDefault ? '' : o.value;
const selected = userValue === o.value || (o.isDefault && !userValue);
const selectedHtml = selected ? ' selected' : '';
const optionValue = o.isDefault ? '' : o.value;
return '<option value="' + optionValue + '"' + selectedHtml + '>' + o.name + '</option>';
return `<option value="${optionValue}"${selectedHtml}>${o.name}</option>`;
}).join('');
}
function renderViewOrder(context, user, result) {
var html = '';
let html = '';
var index = 0;
let index = 0;
html += result.Items.map(function (view) {
html += result.Items.map(view => {
var currentHtml = '';
let currentHtml = '';
currentHtml += '<div class="listItem viewItem" data-viewid="' + view.Id + '">';
currentHtml += `<div class="listItem viewItem" data-viewid="${view.Id}">`;
currentHtml += '<span class="material-icons listItemIcon folder_open"></span>';
@ -155,8 +166,8 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
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="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="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 += '</div>';
@ -170,14 +181,14 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
function updateHomeSectionValues(context, userSettings) {
for (var i = 1; i <= 7; i++) {
for (let i = 1; i <= 7; i++) {
var select = context.querySelector('#selectHomeSection' + i);
var defaultValue = homeSections.getDefaultSection(i - 1);
const select = context.querySelector(`#selectHomeSection${i}`);
const defaultValue = homeSections.getDefaultSection(i - 1);
var option = select.querySelector('option[value=' + defaultValue + ']') || select.querySelector('option[value=""]');
const option = select.querySelector(`option[value=${defaultValue}]`) || select.querySelector('option[value=""]');
var userValue = userSettings.get('homesection' + (i - 1));
const userValue = userSettings.get(`homesection${i - 1}`);
option.value = '';
@ -193,42 +204,42 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
function getPerLibrarySettingsHtml(item, user, userSettings, apiClient) {
var html = '';
let html = '';
var isChecked;
let isChecked;
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 += '<label>';
html += '<input type="checkbox" is="emby-checkbox" class="chkIncludeInMyMedia" data-folderid="' + item.Id + '"' + (isChecked ? ' checked="checked"' : '') + '/>';
html += '<span>' + globalize.translate('DisplayInMyMedia') + '</span>';
html += `<input type="checkbox" is="emby-checkbox" class="chkIncludeInMyMedia" data-folderid="${item.Id}"${isChecked ? ' checked="checked"' : ''}/>`;
html += `<span>${globalize.translate('DisplayInMyMedia')}</span>`;
html += '</label>';
html += '</div>';
}
var excludeFromLatest = ['playlists', 'livetv', 'boxsets', 'channels'];
if (excludeFromLatest.indexOf(item.CollectionType || '') === -1) {
const excludeFromLatest = ['playlists', 'livetv', 'boxsets', 'channels'];
if (!excludeFromLatest.includes(item.CollectionType || '')) {
isChecked = user.Configuration.LatestItemsExcludes.indexOf(item.Id) === -1;
isChecked = !user.Configuration.LatestItemsExcludes.includes(item.Id);
html += '<label class="fldIncludeInLatest">';
html += '<input type="checkbox" is="emby-checkbox" class="chkIncludeInLatest" data-folderid="' + item.Id + '"' + (isChecked ? ' checked="checked"' : '') + '/>';
html += '<span>' + globalize.translate('DisplayInOtherHomeScreenSections') + '</span>';
html += `<input type="checkbox" is="emby-checkbox" class="chkIncludeInLatest" data-folderid="${item.Id}"${isChecked ? ' checked="checked"' : ''}/>`;
html += `<span>${globalize.translate('DisplayInOtherHomeScreenSections')}</span>`;
html += '</label>';
}
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') {
var idForLanding = item.CollectionType === 'livetv' ? item.CollectionType : item.Id;
const idForLanding = item.CollectionType === 'livetv' ? item.CollectionType : item.Id;
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);
@ -238,7 +249,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
if (html) {
var prefix = '';
let prefix = '';
prefix += '<div class="verticalSection">';
prefix += '<h2 class="sectionTitle">';
@ -254,10 +265,10 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
function renderPerLibrarySettings(context, user, userViews, userSettings, apiClient) {
var elem = context.querySelector('.perLibrarySettings');
var html = '';
const elem = context.querySelector('.perLibrarySettings');
let html = '';
for (var i = 0, length = userViews.length; i < length; i++) {
for (let i = 0, length = userViews.length; i < length; i++) {
html += getPerLibrarySettingsHtml(userViews[i], user, userSettings, apiClient);
}
@ -271,10 +282,10 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
updateHomeSectionValues(context, userSettings);
var promise1 = apiClient.getUserViews({ IncludeHidden: true }, user.Id);
var promise2 = apiClient.getJSON(apiClient.getUrl('Users/' + user.Id + '/GroupingOptions'));
const promise1 = apiClient.getUserViews({ IncludeHidden: true }, user.Id);
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]);
@ -286,38 +297,19 @@ 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) {
var target = dom.parentWithClass(e.target, 'btnViewItemMove');
const target = dom.parentWithClass(e.target, 'btnViewItemMove');
if (target) {
var viewItem = dom.parentWithClass(target, 'viewItem');
const viewItem = dom.parentWithClass(target, 'viewItem');
if (viewItem) {
var ul = dom.parentWithClass(viewItem, 'paperList');
const ul = dom.parentWithClass(viewItem, 'paperList');
if (target.classList.contains('btnViewItemDown')) {
var next = viewItem.nextSibling;
const next = viewItem.nextSibling;
if (next) {
viewItem.parentNode.removeChild(viewItem);
@ -327,7 +319,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
} else {
var prev = viewItem.previousSibling;
const prev = viewItem.previousSibling;
if (prev) {
viewItem.parentNode.removeChild(viewItem);
@ -341,10 +333,10 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
function getCheckboxItems(selector, context, isChecked) {
var inputs = context.querySelectorAll(selector);
var list = [];
const inputs = context.querySelectorAll(selector);
const list = [];
for (var i = 0, length = inputs.length; i < length; i++) {
for (let i = 0, length = inputs.length; i < length; i++) {
if (inputs[i].checked === isChecked) {
list.push(inputs[i]);
@ -359,25 +351,25 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
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');
});
user.Configuration.MyMediaExcludes = getCheckboxItems('.chkIncludeInMyMedia', context, false).map(function (i) {
user.Configuration.MyMediaExcludes = getCheckboxItems('.chkIncludeInMyMedia', context, false).map(i => {
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');
});
var viewItems = context.querySelectorAll('.viewItem');
var orderedViews = [];
var i;
var length;
const viewItems = context.querySelectorAll('.viewItem');
const orderedViews = [];
let i;
let length;
for (i = 0, length = viewItems.length; i < length; i++) {
orderedViews.push(viewItems[i].getAttribute('data-viewid'));
}
@ -394,10 +386,10 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
userSettingsInstance.set('homesection5', context.querySelector('#selectHomeSection6').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++) {
var selectLanding = selectLandings[i];
userSettingsInstance.set('landing-' + selectLanding.getAttribute('data-folderid'), selectLanding.value);
const selectLanding = selectLandings[i];
userSettingsInstance.set(`landing-${selectLanding.getAttribute('data-folderid')}`, selectLanding.value);
}
return apiClient.updateUserConfiguration(user.Id, user.Configuration);
@ -407,20 +399,20 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
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();
if (enableSaveConfirmation) {
require(['toast'], function (toast) {
import('toast').then(({default: toast}) => {
toast(globalize.translate('SettingsSaved'));
});
}
events.trigger(instance, 'saved');
}, function () {
}, () => {
loading.hide();
});
});
@ -428,14 +420,14 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
function onSubmit(e) {
var self = this;
var apiClient = connectionManager.getApiClient(self.options.serverId);
var userId = self.options.userId;
var userSettings = self.options.userSettings;
const self = this;
const apiClient = connectionManager.getApiClient(self.options.serverId);
const userId = self.options.userId;
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);
});
@ -448,13 +440,13 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
function onChange(e) {
var chkIncludeInMyMedia = dom.parentWithClass(e.target, 'chkIncludeInMyMedia');
const chkIncludeInMyMedia = dom.parentWithClass(e.target, 'chkIncludeInMyMedia');
if (!chkIncludeInMyMedia) {
return;
}
var section = dom.parentWithClass(chkIncludeInMyMedia, 'verticalSection');
var fldIncludeInLatest = section.querySelector('.fldIncludeInLatest');
const section = dom.parentWithClass(chkIncludeInMyMedia, 'verticalSection');
const fldIncludeInLatest = section.querySelector('.fldIncludeInLatest');
if (fldIncludeInLatest) {
if (chkIncludeInMyMedia.checked) {
fldIncludeInLatest.classList.remove('hide');
@ -466,13 +458,13 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
function embed(options, self) {
require(['text!./homeScreenSettings.template.html'], function (template) {
return import('text!./homeScreenSettings.template.html').then(({default: template}) => {
for (var i = 1; i <= numConfigurableSections; i++) {
template = template.replace('{section' + i + 'label}', globalize.translate('LabelHomeScreenSectionValue', i));
for (let 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('form').addEventListener('submit', onSubmit.bind(self));
@ -492,27 +484,26 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
});
}
function HomeScreenSettings(options) {
class HomeScreenSettings {
constructor(options) {
this.options = options;
embed(options, this);
}
HomeScreenSettings.prototype.loadData = function (autoFocus) {
loadData(autoFocus) {
var self = this;
var context = self.options.element;
const self = this;
const context = self.options.element;
loading.show();
var userId = self.options.userId;
var apiClient = connectionManager.getApiClient(self.options.serverId);
var userSettings = self.options.userSettings;
const userId = self.options.userId;
const apiClient = connectionManager.getApiClient(self.options.serverId);
const userSettings = self.options.userSettings;
apiClient.getUser(userId).then(function (user) {
apiClient.getUser(userId).then(user => {
userSettings.setUserInfo(userId, apiClient).then(function () {
userSettings.setUserInfo(userId, apiClient).then(() => {
self.dataLoaded = true;
@ -523,16 +514,18 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
}
});
});
};
}
HomeScreenSettings.prototype.submit = function () {
submit() {
onSubmit.call(this);
};
}
HomeScreenSettings.prototype.destroy = function () {
destroy() {
this.options = null;
};
}
}
return HomeScreenSettings;
});
/* eslint-enable indent */
export default HomeScreenSettings;

View file

@ -1,7 +1,24 @@
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) {
'use strict';
import connectionManager from 'connectionManager';
import cardBuilder from 'cardBuilder';
import appSettings from 'appSettings';
import dom from 'dom';
import appHost from 'apphost';
import layoutManager from 'layoutManager';
import imageLoader from 'imageLoader';
import globalize from 'globalize';
import itemShortcuts from 'itemShortcuts';
import itemHelper from 'itemHelper';
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) {
case 0:
return 'smalllibrarytiles';
@ -23,9 +40,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function getAllSectionsToShow(userSettings, sectionCount) {
var sections = [];
for (var i = 0, length = sectionCount; i < length; i++) {
var section = userSettings.get('homesection' + i) || getDefaultSection(i);
const sections = [];
for (let i = 0, length = sectionCount; i < length; i++) {
let section = userSettings.get('homesection' + i) || getDefaultSection(i);
if (section === 'folders') {
section = getDefaultSection(0);
}
@ -36,22 +53,22 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
return sections;
}
function loadSections(elem, apiClient, user, userSettings) {
export function loadSections(elem, apiClient, user, userSettings) {
return getUserViews(apiClient, user.Id).then(function (userViews) {
var html = '';
let html = '';
if (userViews.length) {
var sectionCount = 7;
for (var i = 0; i < sectionCount; i++) {
const sectionCount = 7;
for (let i = 0; i < sectionCount; i++) {
html += '<div class="verticalSection section' + i + '"></div>';
}
elem.innerHTML = html;
elem.classList.add('homeSectionsContainer');
var promises = [];
var sections = getAllSectionsToShow(userSettings, sectionCount);
for (var i = 0; i < sections.length; i++) {
const promises = [];
const sections = getAllSectionsToShow(userSettings, sectionCount);
for (let i = 0; i < sections.length; i++) {
promises.push(loadSection(elem, apiClient, user, userSettings, userViews, sections, i));
}
@ -62,7 +79,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
});
});
} else {
var noLibDescription;
let noLibDescription;
if (user['Policy'] && user['Policy']['IsAdministrator']) {
noLibDescription = globalize.translate('NoCreatedLibraries', '<br><a id="button-createLibrary" class="button-link">', '</a>');
} else {
@ -75,7 +92,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
html += '</div>';
elem.innerHTML = html;
var createNowLink = elem.querySelector('#button-createLibrary');
const createNowLink = elem.querySelector('#button-createLibrary');
if (createNowLink) {
createNowLink.addEventListener('click', function () {
Dashboard.navigate('library.html');
@ -85,9 +102,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
});
}
function destroySections(elem) {
var elems = elem.querySelectorAll('.itemsContainer');
for (var i = 0; i < elems.length; i++) {
export function destroySections(elem) {
const elems = elem.querySelectorAll('.itemsContainer');
for (let i = 0; i < elems.length; i++) {
elems[i].fetchData = null;
elems[i].parentContainer = null;
elems[i].getItemsHtml = null;
@ -96,24 +113,22 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
elem.innerHTML = '';
}
function pause(elem) {
var elems = elem.querySelectorAll('.itemsContainer');
for (var i = 0; i < elems.length; i++) {
export function pause(elem) {
const elems = elem.querySelectorAll('.itemsContainer');
for (let i = 0; i < elems.length; i++) {
elems[i].pause();
}
}
function resume(elem, options) {
var elems = elem.querySelectorAll('.itemsContainer');
var i;
var length;
var promises = [];
export function resume(elem, options) {
const elems = elem.querySelectorAll('.itemsContainer');
const 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));
}
var promise = Promise.all(promises);
const promise = Promise.all(promises);
if (!options || options.returnPromise !== false) {
return promise;
}
@ -121,10 +136,10 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function loadSection(page, apiClient, user, userSettings, userViews, allSections, index) {
var section = allSections[index];
var userId = user.Id;
const section = allSections[index];
const userId = user.Id;
var elem = page.querySelector('.section' + index);
const elem = page.querySelector('.section' + index);
if (section === 'latestmedia') {
loadRecentlyAdded(elem, apiClient, user, userViews);
@ -168,11 +183,11 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function getPortraitShape() {
return enableScrollX() ? 'autooverflow' : 'auto';
return enableScrollX() ? 'overflowPortrait' : 'portrait';
}
function getLibraryButtonsHtml(items) {
var html = '';
let html = '';
html += '<div class="verticalSection verticalSection-extrabottompadding">';
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderMyMedia') + '</h2>';
@ -180,9 +195,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">';
// library card background images
for (var i = 0, length = items.length; i < length; i++) {
var item = items[i];
var icon = imageHelper.getLibraryIcon(item.CollectionType);
for (let i = 0, length = items.length; i < length; i++) {
const item = items[i];
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>';
}
@ -194,7 +209,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function loadlibraryButtons(elem, apiClient, user, userSettings, userViews) {
elem.classList.remove('verticalSection');
var html = getLibraryButtonsHtml(userViews);
const html = getLibraryButtonsHtml(userViews);
elem.innerHTML = html;
imageLoader.lazyChildren(elem);
@ -210,8 +225,8 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function getFetchLatestItemsFn(serverId, parentId, collectionType) {
return function () {
var apiClient = connectionManager.getApiClient(serverId);
var limit = 16;
const apiClient = connectionManager.getApiClient(serverId);
let limit = 16;
if (enableScrollX()) {
if (collectionType === 'music') {
@ -227,9 +242,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
}
var options = {
const options = {
Limit: limit,
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo,Path',
ImageTypeLimit: 1,
EnableImageTypes: 'Primary,Backdrop,Thumb',
ParentId: parentId
@ -241,8 +256,8 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function getLatestItemsHtmlFn(itemType, viewType) {
return function (items) {
var cardLayout = false;
var shape;
const cardLayout = false;
let shape;
if (itemType === 'Channel' || viewType === 'movies' || viewType === 'books' || viewType === 'tvshows') {
shape = getPortraitShape();
} else if (viewType === 'music' || viewType === 'homevideos') {
@ -254,7 +269,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
return cardBuilder.getCardsHtml({
items: items,
shape: shape,
preferThumb: viewType !== 'movies' && itemType !== 'Channel' && viewType !== 'music' ? 'auto' : null,
preferThumb: viewType !== 'movies' && viewType !== 'tvshows' && itemType !== 'Channel' && viewType !== 'music' ? 'auto' : null,
showUnplayedIndicator: false,
showChildCountIndicator: true,
context: 'home',
@ -272,7 +287,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function renderLatestSection(elem, apiClient, user, parent) {
var html = '';
let html = '';
html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">';
if (!layoutManager.tv) {
@ -303,7 +318,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
elem.innerHTML = html;
var itemsContainer = elem.querySelector('.itemsContainer');
const itemsContainer = elem.querySelector('.itemsContainer');
itemsContainer.fetchData = getFetchLatestItemsFn(apiClient.serverId(), parent.Id, parent.CollectionType);
itemsContainer.getItemsHtml = getLatestItemsHtmlFn(parent.Type, parent.CollectionType);
itemsContainer.parentContainer = elem;
@ -311,10 +326,10 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function loadRecentlyAdded(elem, apiClient, user, userViews) {
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++) {
var item = userViews[i];
for (let i = 0, length = userViews.length; i < length; i++) {
const item = userViews[i];
if (user.Configuration.LatestItemsExcludes.indexOf(item.Id) !== -1) {
continue;
}
@ -323,7 +338,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
continue;
}
var frag = document.createElement('div');
const frag = document.createElement('div');
frag.classList.add('verticalSection');
frag.classList.add('hide');
elem.appendChild(frag);
@ -334,12 +349,14 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function getRequirePromise(deps) {
return new Promise(function (resolve, reject) {
require(deps, resolve);
import(deps).then(() => {
return resolve;
});
});
}
function loadLibraryTiles(elem, apiClient, user, userSettings, shape, userViews, allSections) {
var html = '';
export function loadLibraryTiles(elem, apiClient, user, userSettings, shape, userViews, allSections) {
let html = '';
if (userViews.length) {
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderMyMedia') + '</h2>';
if (enableScrollX()) {
@ -372,10 +389,10 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function getContinueWatchingFetchFn(serverId) {
return function () {
var apiClient = connectionManager.getApiClient(serverId);
var screenWidth = dom.getWindowSize().innerWidth;
const apiClient = connectionManager.getApiClient(serverId);
const screenWidth = dom.getWindowSize().innerWidth;
var limit;
let limit;
if (enableScrollX()) {
limit = 12;
} else {
@ -383,7 +400,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
limit = Math.min(limit, 5);
}
var options = {
const options = {
Limit: limit,
Recursive: true,
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
@ -398,7 +415,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function getContinueWatchingItemsHtml(items) {
var cardLayout = false;
const cardLayout = false;
return cardBuilder.getCardsHtml({
items: items,
preferThumb: true,
@ -419,7 +436,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function loadResumeVideo(elem, apiClient, userId) {
var html = '';
let html = '';
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderContinueWatching') + '</h2>';
if (enableScrollX()) {
@ -437,7 +454,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
elem.classList.add('hide');
elem.innerHTML = html;
var itemsContainer = elem.querySelector('.itemsContainer');
const itemsContainer = elem.querySelector('.itemsContainer');
itemsContainer.fetchData = getContinueWatchingFetchFn(apiClient.serverId());
itemsContainer.getItemsHtml = getContinueWatchingItemsHtml;
itemsContainer.parentContainer = elem;
@ -445,10 +462,10 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function getContinueListeningFetchFn(serverId) {
return function () {
var apiClient = connectionManager.getApiClient(serverId);
var screenWidth = dom.getWindowSize().innerWidth;
const apiClient = connectionManager.getApiClient(serverId);
const screenWidth = dom.getWindowSize().innerWidth;
var limit;
let limit;
if (enableScrollX()) {
limit = 12;
} else {
@ -456,7 +473,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
limit = Math.min(limit, 5);
}
var options = {
const options = {
Limit: limit,
Recursive: true,
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
@ -471,7 +488,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function getContinueListeningItemsHtml(items) {
var cardLayout = false;
const cardLayout = false;
return cardBuilder.getCardsHtml({
items: items,
preferThumb: true,
@ -492,7 +509,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function loadResumeAudio(elem, apiClient, userId) {
var html = '';
let html = '';
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderContinueWatching') + '</h2>';
if (enableScrollX()) {
@ -510,7 +527,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
elem.classList.add('hide');
elem.innerHTML = html;
var itemsContainer = elem.querySelector('.itemsContainer');
const itemsContainer = elem.querySelector('.itemsContainer');
itemsContainer.fetchData = getContinueListeningFetchFn(apiClient.serverId());
itemsContainer.getItemsHtml = getContinueListeningItemsHtml;
itemsContainer.parentContainer = elem;
@ -518,7 +535,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function getOnNowFetchFn(serverId) {
return function () {
var apiClient = connectionManager.getApiClient(serverId);
const apiClient = connectionManager.getApiClient(serverId);
return apiClient.getLiveTvRecommendedPrograms({
userId: apiClient.getCurrentUserId(),
IsAiring: true,
@ -532,7 +549,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function getOnNowItemsHtml(items) {
var cardLayout = false;
const cardLayout = false;
return cardBuilder.getCardsHtml({
items: items,
preferThumb: 'auto',
@ -559,7 +576,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
return Promise.resolve();
}
var userId = user.Id;
const userId = user.Id;
return apiClient.getLiveTvRecommendedPrograms({
userId: apiClient.getCurrentUserId(),
IsAiring: true,
@ -569,7 +586,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
EnableTotalRecordCount: false,
Fields: 'ChannelInfo,PrimaryImageAspectRatio'
}).then(function (result) {
var html = '';
let html = '';
if (result.Items.length) {
elem.classList.remove('padded-left');
elem.classList.remove('padded-right');
@ -654,7 +671,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
elem.innerHTML = html;
var itemsContainer = elem.querySelector('.itemsContainer');
const itemsContainer = elem.querySelector('.itemsContainer');
itemsContainer.parentContainer = elem;
itemsContainer.fetchData = getOnNowFetchFn(apiClient.serverId());
itemsContainer.getItemsHtml = getOnNowItemsHtml;
@ -664,10 +681,10 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function getNextUpFetchFn(serverId) {
return function () {
var apiClient = connectionManager.getApiClient(serverId);
const apiClient = connectionManager.getApiClient(serverId);
return apiClient.getNextUpEpisodes({
Limit: enableScrollX() ? 24 : 15,
Fields: 'PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo',
Fields: 'PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo,Path',
UserId: apiClient.getCurrentUserId(),
ImageTypeLimit: 1,
EnableImageTypes: 'Primary,Backdrop,Banner,Thumb',
@ -677,7 +694,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function getNextUpItemsHtml(items) {
var cardLayout = false;
const cardLayout = false;
return cardBuilder.getCardsHtml({
items: items,
preferThumb: true,
@ -695,7 +712,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function loadNextUp(elem, apiClient, userId) {
var html = '';
let html = '';
html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">';
if (!layoutManager.tv) {
@ -727,7 +744,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
elem.classList.add('hide');
elem.innerHTML = html;
var itemsContainer = elem.querySelector('.itemsContainer');
const itemsContainer = elem.querySelector('.itemsContainer');
itemsContainer.fetchData = getNextUpFetchFn(apiClient.serverId());
itemsContainer.getItemsHtml = getNextUpItemsHtml;
itemsContainer.parentContainer = elem;
@ -735,7 +752,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function getLatestRecordingsFetchFn(serverId, activeRecordingsOnly) {
return function () {
var apiClient = connectionManager.getApiClient(serverId);
const apiClient = connectionManager.getApiClient(serverId);
return apiClient.getLiveTvRecordings({
userId: apiClient.getCurrentUserId(),
Limit: enableScrollX() ? 12 : 5,
@ -749,7 +766,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
function getLatestRecordingItemsHtml(activeRecordingsOnly) {
return function (items) {
var cardLayout = false;
const cardLayout = false;
return cardBuilder.getCardsHtml({
items: items,
shape: enableScrollX() ? 'autooverflow' : 'auto',
@ -774,11 +791,11 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function loadLatestLiveTvRecordings(elem, activeRecordingsOnly, apiClient, userId) {
var title = activeRecordingsOnly ?
const title = activeRecordingsOnly ?
globalize.translate('HeaderActiveRecordings') :
globalize.translate('HeaderLatestRecordings');
var html = '';
let html = '';
html += '<div class="sectionTitleContainer sectionTitleContainer-cards">';
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + title + '</h2>';
@ -799,18 +816,19 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
elem.classList.add('hide');
elem.innerHTML = html;
var itemsContainer = elem.querySelector('.itemsContainer');
const itemsContainer = elem.querySelector('.itemsContainer');
itemsContainer.fetchData = getLatestRecordingsFetchFn(apiClient.serverId(), activeRecordingsOnly);
itemsContainer.getItemsHtml = getLatestRecordingItemsHtml(activeRecordingsOnly);
itemsContainer.parentContainer = elem;
}
return {
export default {
loadLibraryTiles: loadLibraryTiles,
getDefaultSection: getDefaultSection,
loadSections: loadSections,
destroySections: destroySections,
pause: pause,
resume: resume
};
});
};
/* eslint-enable indent */

View file

@ -1,17 +1,20 @@
define(['appSettings', 'browser', 'events'], function (appSettings, browser, events) {
'use strict';
/* eslint-disable indent */
function getSavedVolume() {
import appSettings from 'appSettings' ;
import browser from 'browser';
import events from 'events';
export function getSavedVolume() {
return appSettings.get('volume') || 1;
}
function saveVolume(value) {
export function saveVolume(value) {
if (value) {
appSettings.set('volume', value);
}
}
function getCrossOriginValue(mediaSource) {
export function getCrossOriginValue(mediaSource) {
if (mediaSource.IsRemote) {
return null;
}
@ -30,7 +33,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
return false;
}
function enableHlsShakaPlayer(item, mediaSource, mediaType) {
export function enableHlsShakaPlayer(item, mediaSource, mediaType) {
/* eslint-disable-next-line compat/compat */
if (!!window.MediaSource && !!MediaSource.isTypeSupported) {
@ -56,7 +59,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
return false;
}
function enableHlsJsPlayer(runTimeTicks, mediaType) {
export function enableHlsJsPlayer(runTimeTicks, mediaType) {
if (window.MediaSource == null) {
return false;
@ -98,7 +101,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
var recoverDecodingErrorDate;
var recoverSwapAudioCodecDate;
function handleHlsJsMediaError(instance, reject) {
export function handleHlsJsMediaError(instance, reject) {
var hlsPlayer = instance._hlsPlayer;
@ -134,7 +137,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
}
}
function onErrorInternal(instance, type) {
export function onErrorInternal(instance, type) {
// Needed for video
if (instance.destroyCustomTrack) {
@ -148,7 +151,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) {
return true;
}
@ -162,7 +165,7 @@ 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;
@ -200,7 +203,7 @@ 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) {
@ -228,7 +231,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
elem.addEventListener('error', onErrorFn);
}
function playWithPromise(elem, onErrorFn) {
export function playWithPromise(elem, onErrorFn) {
try {
var promise = elem.play();
@ -256,7 +259,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
}
}
function destroyCastPlayer(instance) {
export function destroyCastPlayer(instance) {
var player = instance._castPlayer;
if (player) {
@ -270,7 +273,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
}
}
function destroyShakaPlayer(instance) {
export function destroyShakaPlayer(instance) {
var player = instance._shakaPlayer;
if (player) {
try {
@ -283,7 +286,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
}
}
function destroyHlsPlayer(instance) {
export function destroyHlsPlayer(instance) {
var player = instance._hlsPlayer;
if (player) {
try {
@ -296,7 +299,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
}
}
function destroyFlvPlayer(instance) {
export function destroyFlvPlayer(instance) {
var player = instance._flvPlayer;
if (player) {
try {
@ -311,7 +314,7 @@ 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 () {
playWithPromise(elem, onErrorFn).then(resolve, function () {
@ -403,7 +406,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
});
}
function onEndedInternal(instance, elem, onErrorFn) {
export function onEndedInternal(instance, elem, onErrorFn) {
elem.removeEventListener('error', onErrorFn);
@ -427,7 +430,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
instance._currentPlayOptions = null;
}
function getBufferedRanges(instance, elem) {
export function getBufferedRanges(instance, elem) {
var ranges = [];
var seekable = elem.buffered || [];
@ -462,23 +465,4 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
return ranges;
}
return {
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
};
});
/* eslint-enable indent */

View file

@ -339,7 +339,7 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
var dlg = dialogHelper.createDialog(dialogOptions);
dlg.innerHTML = globalize.translateDocument(template, 'core');
dlg.innerHTML = globalize.translateHtml(template, 'core');
if (layoutManager.tv) {
scrollHelper.centerFocus.on(dlg, false);

View file

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

View file

@ -1,10 +1,26 @@
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) {
'use strict';
/* eslint-disable indent */
var currentItemId;
var currentServerId;
var currentFile;
var hasChanges = false;
/**
* Module for imageUploader.
* @module components/imageUploader/imageUploader
*/
import dialogHelper from 'dialogHelper';
import connectionManager from 'connectionManager';
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) {
@ -12,14 +28,14 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
switch (evt.target.error.code) {
case evt.target.error.NOT_FOUND_ERR:
require(['toast'], function (toast) {
import('toast').then(({default: toast}) => {
toast(globalize.translate('MessageFileReadError'));
});
break;
case evt.target.error.ABORT_ERR:
break; // noop
default:
require(['toast'], function (toast) {
import('toast').then(({default: toast}) => {
toast(globalize.translate('MessageFileReadError'));
});
break;
@ -28,7 +44,7 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
function setFiles(page, files) {
var file = files[0];
const file = files[0];
if (!file || !file.type.match('image.*')) {
page.querySelector('#imageOutput').innerHTML = '';
@ -39,25 +55,26 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
currentFile = file;
var reader = new FileReader();
const reader = new FileReader();
reader.onerror = onFileReaderError;
reader.onloadstart = function () {
reader.onloadstart = () => {
page.querySelector('#fldUpload').classList.add('hide');
};
reader.onabort = function () {
reader.onabort = () => {
loading.hide();
console.debug('File read cancelled');
};
// Closure to capture the file information.
reader.onload = (function (theFile) {
return function (e) {
reader.onload = (theFile => {
return e => {
// 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('#dropImageText').classList.add('hide');
page.querySelector('#fldUpload').classList.remove('hide');
};
})(file);
@ -68,14 +85,14 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
function onSubmit(e) {
var file = currentFile;
const file = currentFile;
if (!file) {
return false;
}
if (!file.type.startsWith('image/')) {
require(['toast'], function (toast) {
import('toast').then(({default: toast}) => {
toast(globalize.translate('MessageImageFileTypeAllowed'));
});
e.preventDefault();
@ -84,18 +101,18 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
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') {
require(['toast'], function(toast) {
import('toast').then(({default: toast}) => {
toast(globalize.translate('MessageImageTypeNotSelected'));
});
e.preventDefault();
return false;
}
connectionManager.getApiClient(currentServerId).uploadItemImage(currentItemId, imageType, file).then(function () {
connectionManager.getApiClient(currentServerId).uploadItemImage(currentItemId, imageType, file).then(() => {
dlg.querySelector('#uploadImage').value = '';
@ -116,21 +133,21 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
setFiles(page, this.files);
});
page.querySelector('.btnBrowse').addEventListener('click', function () {
page.querySelector('.btnBrowse').addEventListener('click', () => {
page.querySelector('#uploadImage').click();
});
}
function showEditor(options, resolve, reject) {
function showEditor(options, resolve) {
options = options || {};
require(['text!./imageUploader.template.html'], function (template) {
return import('text!./imageUploader.template.html').then(({default: template}) => {
currentItemId = options.itemId;
currentServerId = options.serverId;
var dialogOptions = {
const dialogOptions = {
removeOnClose: true
};
@ -140,18 +157,18 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
dialogOptions.size = 'small';
}
var dlg = dialogHelper.createDialog(dialogOptions);
const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog');
dlg.innerHTML = globalize.translateDocument(template, 'core');
dlg.innerHTML = globalize.translateHtml(template, 'core');
if (layoutManager.tv) {
scrollHelper.centerFocus.on(dlg, false);
}
// Has to be assigned a z-index after the call to .open()
dlg.addEventListener('close', function () {
dlg.addEventListener('close', () => {
if (layoutManager.tv) {
scrollHelper.centerFocus.off(dlg, false);
@ -167,22 +184,24 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
dlg.querySelector('#selectImageType').value = options.imageType || 'Primary';
dlg.querySelector('.btnCancel').addEventListener('click', function () {
dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg);
});
});
}
return {
show: function (options) {
export function show(options) {
return new Promise(function (resolve, reject) {
return new Promise(resolve => {
hasChanges = false;
showEditor(options, resolve, reject);
showEditor(options, resolve);
});
}
};
});
/* eslint-enable indent */
export default {
show: show
};

View file

@ -20,7 +20,7 @@
</div>
<div>
<div class="imageEditor-dropZone fieldDescription">
<div>${LabelDropImageHere}</div>
<div id="dropImageText">${LabelDropImageHere}</div>
<output id="imageOutput" class="flex align-items-center justify-content-center" style="position: absolute;top:0;left:0;right:0;bottom:0;width:100%;"></output>
<input type="file" accept="image/*" id="uploadImage" name="uploadImage" style="position: absolute;top:0;left:0;right:0;bottom:0;width:100%;opacity:0;" />
</div>

View file

@ -200,7 +200,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
require(['confirm'], function (confirm) {
confirm({
confirm.default({
text: globalize.translate('ConfirmDeleteImage'),
confirmText: globalize.translate('Delete'),
@ -464,7 +464,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
dlg.classList.add('formDialog');
dlg.innerHTML = globalize.translateDocument(template, 'core');
dlg.innerHTML = globalize.translateHtml(template, 'core');
if (layoutManager.tv) {
scrollHelper.centerFocus.on(dlg, false);

View file

@ -1,5 +1,6 @@
import * as lazyLoader from 'lazyLoader';
import * as userSettings from 'userSettings';
import * as blurhash from 'blurhash';
import 'css!./style';
/* eslint-disable indent */
@ -11,47 +12,93 @@ import 'css!./style';
fillImageElement(elem, source);
}
function itemBlurhashing(target, 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,
// improving the performance and reducing the memory usage, while retaining almost full blur quality.
// Lower values had more visible pixelation
let width = 18;
let height = 18;
let pixels;
try {
pixels = blurhash.decode(blurhashstr, width, height);
} catch (err) {
console.error('Blurhash decode error: ', err);
target.classList.add('non-blurhashable');
return;
}
let canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
let ctx = canvas.getContext('2d');
let imgData = ctx.createImageData(width, height);
imgData.data.set(pixels);
ctx.putImageData(imgData, 0, 0);
requestAnimationFrame(() => {
canvas.classList.add('blurhash-canvas');
if (userSettings.enableFastFadein()) {
canvas.classList.add('lazy-blurhash-fadein-fast');
} else {
canvas.classList.add('lazy-blurhash-fadein');
}
target.parentNode.insertBefore(canvas, target);
target.classList.add('blurhashed');
target.removeAttribute('data-blurhash');
});
}
}
export function fillImage(entry) {
if (!entry) {
throw new Error('entry cannot be null');
}
let target = entry.target;
var source = undefined;
if (entry.target) {
source = entry.target.getAttribute('data-src');
if (target) {
source = target.getAttribute('data-src');
} else {
source = entry;
}
if (entry.intersectionRatio > 0) {
if (source) fillImageElement(entry.target, source);
if (source) fillImageElement(target, source);
} else if (!source) {
emptyImageElement(entry.target);
requestAnimationFrame(() => {
emptyImageElement(target);
});
}
}
function fillImageElement(elem, url) {
if (url === undefined) {
throw new Error('url cannot be undefined');
throw new TypeError('url cannot be undefined');
}
let preloaderImg = new Image();
preloaderImg.src = url;
elem.classList.add('lazy-hidden');
preloaderImg.addEventListener('load', () => {
requestAnimationFrame(() => {
if (elem.tagName !== 'IMG') {
elem.style.backgroundImage = "url('" + url + "')";
} else {
elem.setAttribute('src', url);
}
elem.removeAttribute('data-src');
elem.classList.remove('lazy-hidden');
if (userSettings.enableFastFadein()) {
elem.classList.add('lazy-image-fadein-fast');
} else {
elem.classList.add('lazy-image-fadein');
}
elem.removeAttribute('data-src');
});
});
}
@ -65,14 +112,23 @@ import 'css!./style';
url = elem.getAttribute('src');
elem.setAttribute('src', '');
}
elem.setAttribute('data-src', url);
elem.classList.remove('lazy-image-fadein-fast');
elem.classList.remove('lazy-image-fadein');
elem.classList.remove('lazy-image-fadein-fast', 'lazy-image-fadein');
elem.classList.add('lazy-hidden');
}
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);
}
@ -144,8 +200,15 @@ import 'css!./style';
}
}
export function setLazyImage(element, url) {
element.classList.add('lazy');
element.setAttribute('data-src', url);
lazyImage(element);
}
/* eslint-enable indent */
export default {
serLazyImage: setLazyImage,
fillImages: fillImages,
fillImage: fillImage,
lazyImage: lazyImage,

View file

@ -1,13 +1,42 @@
.cardImageContainer.lazy {
.lazy-image-fadein {
opacity: 1;
transition: opacity 0.5s;
}
.lazy-image-fadein-fast {
opacity: 1;
transition: opacity 0.1s;
}
.lazy-hidden {
opacity: 0;
}
.cardImageContainer.lazy.lazy-image-fadein {
@keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
transition: opacity 0.7s;
}
}
.cardImageContainer.lazy.lazy-image-fadein-fast {
opacity: 1;
transition: opacity 0.2s;
.lazy-blurhash-fadein-fast {
animation: fadein 0.1s;
}
.lazy-blurhash-fadein {
animation: fadein 0.4s;
}
.blurhash-canvas {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
}

View file

@ -1,14 +1,24 @@
define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', 'playbackManager', 'loading', 'appSettings', 'browser', 'actionsheet'], function (appHost, globalize, connectionManager, itemHelper, appRouter, playbackManager, loading, appSettings, browser, actionsheet) {
'use strict';
import appHost from 'apphost';
import globalize from 'globalize';
import connectionManager from 'connectionManager';
import itemHelper from 'itemHelper';
import appRouter from 'appRouter';
import playbackManager from 'playbackManager';
import loading from 'loading';
import appSettings from 'appSettings';
import browser from 'browser';
import actionsheet from 'actionsheet';
function getCommands(options) {
var item = options.item;
var user = options.user;
/* eslint-disable indent */
var canPlay = playbackManager.canPlay(item);
var restrictOptions = (browser.operaTv || browser.web0s) && !user.Policy.IsAdministrator;
export function getCommands(options) {
const item = options.item;
const user = options.user;
var commands = [];
const canPlay = playbackManager.canPlay(item);
const restrictOptions = (browser.operaTv || browser.web0s) && !user.Policy.IsAdministrator;
let commands = [];
if (canPlay && item.MediaType !== 'Photo') {
if (options.play !== false) {
@ -28,6 +38,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 (options.queue !== false) {
commands.push({
@ -44,13 +71,6 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
icon: 'playlist_add'
});
}
//if (options.queueAllFromHere) {
// commands.push({
// name: globalize.translate("QueueAllFromHere"),
// id: "queueallfromhere"
// });
//}
}
if (item.IsFolder || item.Type === 'MusicArtist' || item.Type === 'MusicGenre') {
@ -161,10 +181,10 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
});
}
var canEdit = itemHelper.canEdit(user, item);
const canEdit = itemHelper.canEdit(user, item);
if (canEdit) {
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({
name: text,
id: 'edit',
@ -288,10 +308,11 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
icon: 'album'
});
}
if (options.openArtist !== false && item.ArtistItems && item.ArtistItems.length) {
// Show Album Artist by default, as a song can have multiple artists, which specific one would this option refer to?
// 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({
name: globalize.translate('ViewArtist'),
name: globalize.translate('ViewAlbumArtist'),
id: 'artist',
icon: 'person'
});
@ -311,31 +332,31 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
}
function executeCommand(item, id, options) {
var itemId = item.Id;
var serverId = item.ServerId;
var apiClient = connectionManager.getApiClient(serverId);
const itemId = item.Id;
const serverId = item.ServerId;
const apiClient = connectionManager.getApiClient(serverId);
return new Promise(function (resolve, reject) {
switch (id) {
case 'addtocollection':
require(['collectionEditor'], function (collectionEditor) {
new collectionEditor().show({
import('collectionEditor').then(({default: collectionEditor}) => {
new collectionEditor({
items: [itemId],
serverId: serverId
}).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
});
break;
case 'addtoplaylist':
require(['playlistEditor'], function (playlistEditor) {
new playlistEditor().show({
import('playlistEditor').then(({default: playlistEditor}) => {
new playlistEditor({
items: [itemId],
serverId: serverId
}).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
});
break;
case 'download':
require(['fileDownloader'], function (fileDownloader) {
var downloadHref = apiClient.getItemDownloadUrl(itemId);
import('fileDownloader').then(({default: fileDownloader}) => {
const downloadHref = apiClient.getItemDownloadUrl(itemId);
fileDownloader.download([{
url: downloadHref,
itemId: itemId,
@ -346,17 +367,17 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
getResolveFunction(getResolveFunction(resolve, id), id)();
});
break;
case 'copy-stream':
var downloadHref = apiClient.getItemDownloadUrl(itemId);
var textAreaCopy = function () {
var textArea = document.createElement('textarea');
case 'copy-stream': {
const downloadHref = apiClient.getItemDownloadUrl(itemId);
const textAreaCopy = function () {
let textArea = document.createElement('textarea');
textArea.value = downloadHref;
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
if (document.execCommand('copy')) {
require(['toast'], function (toast) {
import('toast').then(({default: toast}) => {
toast(globalize.translate('CopyStreamURLSuccess'));
});
} else {
@ -371,7 +392,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
} else {
/* eslint-disable-next-line compat/compat */
navigator.clipboard.writeText(downloadHref).then(function () {
require(['toast'], function (toast) {
import('toast').then(({default: toast}) => {
toast(globalize.translate('CopyStreamURLSuccess'));
});
}).catch(function () {
@ -380,8 +401,9 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
}
getResolveFunction(resolve, id)();
break;
}
case 'editsubtitles':
require(['subtitleEditor'], function (subtitleEditor) {
import('subtitleEditor').then(({default: subtitleEditor}) => {
subtitleEditor.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
});
break;
@ -389,7 +411,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
editItem(apiClient, item).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
break;
case 'editimages':
require(['imageEditor'], function (imageEditor) {
import('imageEditor').then(({default: imageEditor}) => {
imageEditor.show({
itemId: itemId,
serverId: serverId
@ -397,13 +419,13 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
});
break;
case 'identify':
require(['itemIdentifier'], function (itemIdentifier) {
import('itemIdentifier').then(({default: itemIdentifier}) => {
itemIdentifier.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
});
break;
case 'moremediainfo':
require(['itemMediaInfo'], function (itemMediaInfo) {
itemMediaInfo.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
import('itemMediaInfo').then(({default: itemMediaInfo}) => {
itemMediaInfo.show(itemId, serverId).then(getResolveFunction(resolve, id), getResolveFunction(resolve, id));
});
break;
case 'refresh':
@ -430,8 +452,14 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
play(item, false, true, true);
getResolveFunction(resolve, id)();
break;
case 'stopPlayback':
playbackManager.stop();
break;
case 'clearQueue':
playbackManager.clearQueue();
break;
case 'record':
require(['recordingCreator'], function (recordingCreator) {
import('recordingCreator').then(({default: recordingCreator}) => {
recordingCreator.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
});
break;
@ -458,7 +486,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
getResolveFunction(resolve, id)();
break;
case 'artist':
appRouter.showItem(item.ArtistItems[0].Id, item.ServerId);
appRouter.showItem(item.AlbumArtists[0].Id, item.ServerId);
getResolveFunction(resolve, id)();
break;
case 'playallfromhere':
@ -502,8 +530,8 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
}
function deleteTimer(apiClient, item, resolve, command) {
require(['recordingHelper'], function (recordingHelper) {
var timerId = item.TimerId || item.Id;
import('recordingHelper').then(({default: recordingHelper}) => {
const timerId = item.TimerId || item.Id;
recordingHelper.cancelTimerWithConfirmation(timerId, item.ServerId).then(function () {
getResolveFunction(resolve, command, true)();
});
@ -511,7 +539,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
}
function deleteSeriesTimer(apiClient, item, resolve, command) {
require(['recordingHelper'], function (recordingHelper) {
import('recordingHelper').then(({default: recordingHelper}) => {
recordingHelper.cancelSeriesTimerWithConfirmation(item.Id, item.ServerId).then(function () {
getResolveFunction(resolve, command, true)();
});
@ -519,9 +547,9 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
}
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) {
startPosition = item.UserData.PlaybackPositionTicks;
}
@ -542,18 +570,18 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
function editItem(apiClient, item) {
return new Promise(function (resolve, reject) {
var serverId = apiClient.serverInfo().Id;
const serverId = apiClient.serverInfo().Id;
if (item.Type === 'Timer') {
require(['recordingEditor'], function (recordingEditor) {
import('recordingEditor').then(({default: recordingEditor}) => {
recordingEditor.show(item.Id, serverId).then(resolve, reject);
});
} else if (item.Type === 'SeriesTimer') {
require(['seriesRecordingEditor'], function (recordingEditor) {
import('seriesRecordingEditor').then(({default: recordingEditor}) => {
recordingEditor.show(item.Id, serverId).then(resolve, reject);
});
} else {
require(['metadataEditor'], function (metadataEditor) {
import('metadataEditor').then(({default: metadataEditor}) => {
metadataEditor.show(item.Id, serverId).then(resolve, reject);
});
}
@ -562,7 +590,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
function deleteItem(apiClient, item) {
return new Promise(function (resolve, reject) {
require(['deleteHelper'], function (deleteHelper) {
import('deleteHelper').then(({default: deleteHelper}) => {
deleteHelper.deleteItem({
item: item,
navigate: false
@ -574,7 +602,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
}
function refresh(apiClient, item) {
require(['refreshDialog'], function (refreshDialog) {
import('refreshDialog').then(({default: refreshDialog}) => {
new refreshDialog({
itemIds: [item.Id],
serverId: apiClient.serverInfo().Id,
@ -583,8 +611,8 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
});
}
function show(options) {
var commands = getCommands(options);
export function show(options) {
const commands = getCommands(options);
if (!commands.length) {
return Promise.reject();
}
@ -598,8 +626,9 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
});
}
return {
/* eslint-enable indent */
export default {
getCommands: getCommands,
show: show
};
});
};

View file

@ -1,14 +1,12 @@
define(['apphost', 'globalize'], function (appHost, globalize) {
'use strict';
function getDisplayName(item, options) {
function getDisplayName(item, options = {}) {
if (!item) {
throw new Error('null item passed into getDisplayName');
}
options = options || {};
if (item.Type === 'Timer') {
item = item.ProgramInfo || item;
}

View file

@ -1,44 +1,61 @@
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) {
'use strict';
/* eslint-disable indent */
/**
* Module for display media info.
* @module components/itemMediaInfo/itemMediaInfo
*/
import dialogHelper from 'dialogHelper';
import layoutManager from 'layoutManager';
import globalize from 'globalize';
import connectionManager from 'connectionManager';
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) {
var html = item.MediaSources.map(function (version) {
let html = item.MediaSources.map(version => {
return getMediaSourceHtml(user, item, version);
}).join('<div style="border-top:1px solid #444;margin: 1em 0;"></div>');
if (item.MediaSources.length > 1) {
html = '<br/>' + html;
html = `<br/>${html}`;
}
var mediaInfoContent = page.querySelector('#mediaInfoContent');
const mediaInfoContent = page.querySelector('#mediaInfoContent');
mediaInfoContent.innerHTML = html;
}
function getMediaSourceHtml(user, item, version) {
var html = '';
let html = '';
if (version.Name) {
html += '<div><h2 class="mediaInfoStreamType">' + version.Name + '</h2></div>';
html += `<div><h2 class="mediaInfoStreamType">${version.Name}</h2></div>`;
}
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) {
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) {
html += createAttribute(globalize.translate('MediaInfoPath'), version.Path) + '<br/>';
html += `${createAttribute(globalize.translate('MediaInfoPath'), version.Path)}<br/>`;
}
if (version.Size) {
var size = (version.Size / (1024 * 1024)).toFixed(0) + ' MB';
html += createAttribute(globalize.translate('MediaInfoSize'), size) + '<br/>';
const size = `${(version.Size / (1024 * 1024)).toFixed(0)} MB`;
html += `${createAttribute(globalize.translate('MediaInfoSize'), size)}<br/>`;
}
for (var i = 0, length = version.MediaStreams.length; i < length; i++) {
var stream = version.MediaStreams[i];
for (let i = 0, length = version.MediaStreams.length; i < length; i++) {
const stream = version.MediaStreams[i];
if (stream.Type === 'Data') {
continue;
}
html += '<div class="mediaInfoStream">';
var displayType = globalize.translate('MediaInfoStreamType' + stream.Type);
html += '<h2 class="mediaInfoStreamType">' + displayType + '</h2>';
var attributes = [];
const displayType = globalize.translate(`MediaInfoStreamType${stream.Type}`);
html += `<h2 class="mediaInfoStreamType">${displayType}</h2>`;
const attributes = [];
if (stream.DisplayTitle) {
attributes.push(createAttribute('Title', stream.DisplayTitle));
}
@ -61,7 +78,7 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings',
attributes.push(createAttribute(globalize.translate('MediaInfoLevel'), stream.Level));
}
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') {
attributes.push(createAttribute(globalize.translate('MediaInfoAspectRatio'), stream.AspectRatio));
@ -79,16 +96,16 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings',
attributes.push(createAttribute(globalize.translate('MediaInfoLayout'), stream.ChannelLayout));
}
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') {
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) {
attributes.push(createAttribute(globalize.translate('MediaInfoSampleRate'), stream.SampleRate + ' Hz'));
attributes.push(createAttribute(globalize.translate('MediaInfoSampleRate'), `${stream.SampleRate} Hz`));
}
if (stream.BitDepth) {
attributes.push(createAttribute(globalize.translate('MediaInfoBitDepth'), stream.BitDepth + ' bit'));
attributes.push(createAttribute(globalize.translate('MediaInfoBitDepth'), `${stream.BitDepth} bit`));
}
if (stream.PixelFormat) {
attributes.push(createAttribute(globalize.translate('MediaInfoPixelFormat'), stream.PixelFormat));
@ -116,13 +133,13 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings',
}
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) {
var apiClient = connectionManager.getApiClient(serverId);
return apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) {
var dialogOptions = {
function loadMediaInfo(itemId, serverId, template) {
const apiClient = connectionManager.getApiClient(serverId);
return apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(item => {
const dialogOptions = {
size: 'small',
removeOnClose: true,
scrollY: false
@ -130,35 +147,35 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings',
if (layoutManager.tv) {
dialogOptions.size = 'fullscreen';
}
var dlg = dialogHelper.createDialog(dialogOptions);
const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog');
var html = '';
html += globalize.translateDocument(template, 'core');
let html = '';
html += globalize.translateHtml(template, 'core');
dlg.innerHTML = html;
if (layoutManager.tv) {
dlg.querySelector('.formDialogContent');
}
dialogHelper.open(dlg);
dlg.querySelector('.btnCancel').addEventListener('click', function (e) {
dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg);
});
apiClient.getCurrentUser().then(function (user) {
apiClient.getCurrentUser().then(user => {
setMediaInfo(user, dlg, item);
});
loading.hide();
});
}
function showMediaInfo(itemId, serverId) {
export function show(itemId, serverId) {
loading.show();
return new Promise(function (resolve, reject) {
require(['text!./itemMediaInfo.template.html'], function (template) {
showMediaInfoMore(itemId, serverId, template).then(resolve, reject);
return import('text!./itemMediaInfo.template.html').then(({default: template}) => {
return new Promise((resolve, reject) => {
loadMediaInfo(itemId, serverId, template).then(resolve, reject);
});
});
}
return {
show: showMediaInfo
};
});
/* eslint-enable indent */
export default {
show: show
};

View file

@ -1,15 +1,34 @@
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) {
'use strict';
/* eslint-disable indent */
var enableFocusTransform = !browser.slow && !browser.edge;
/**
* Module for itemidentifier media item.
* @module components/itemidentifier/itemidentifier
*/
var currentItem;
var currentItemType;
var currentServerId;
var currentResolve;
var currentReject;
var hasChanges = false;
var currentSearchResult;
import dialogHelper from 'dialogHelper';
import loading from 'loading';
import connectionManager from 'connectionManager';
import globalize from 'globalize';
import scrollHelper from 'scrollHelper';
import layoutManager from 'layoutManager';
import focusManager from 'focusManager';
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() {
return connectionManager.getApiClient(currentServerId);
@ -17,14 +36,14 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
function searchForIdentificationResults(page) {
var lookupInfo = {
let lookupInfo = {
ProviderIds: {}
};
var i;
var length;
var identifyField = page.querySelectorAll('.identifyField');
var value;
let i;
let length;
const identifyField = page.querySelectorAll('.identifyField');
let value;
for (i = 0, length = identifyField.length; i < length; i++) {
value = identifyField[i].value;
@ -39,9 +58,9 @@ 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++) {
value = txtLookupId[i].value;
@ -53,7 +72,7 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
}
if (!hasId && !lookupInfo.Name) {
require(['toast'], function (toast) {
import('toast').then(({default: toast}) => {
toast(globalize.translate('PleaseEnterNameOrId'));
});
return;
@ -71,16 +90,16 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
loading.show();
var apiClient = getApiClient();
const apiClient = getApiClient();
apiClient.ajax({
type: 'POST',
url: apiClient.getUrl('Items/RemoteSearch/' + currentItemType),
url: apiClient.getUrl(`Items/RemoteSearch/${currentItemType}`),
data: JSON.stringify(lookupInfo),
contentType: 'application/json',
dataType: 'json'
}).then(function (results) {
}).then(results => {
loading.hide();
showIdentificationSearchResults(page, results);
@ -89,29 +108,29 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
function showIdentificationSearchResults(page, results) {
var identificationSearchResults = page.querySelector('.identificationSearchResults');
const identificationSearchResults = page.querySelector('.identificationSearchResults');
page.querySelector('.popupIdentifyForm').classList.add('hide');
identificationSearchResults.classList.remove('hide');
page.querySelector('.identifyOptionsForm').classList.add('hide');
page.querySelector('.dialogContentInner').classList.remove('dialog-content-centered');
var html = '';
var i;
var length;
let html = '';
let i;
let length;
for (i = 0, length = results.length; i < length; i++) {
var result = results[i];
const result = results[i];
html += getSearchResultHtml(result, i);
}
var elem = page.querySelector('.identificationSearchResultList');
const elem = page.querySelector('.identificationSearchResultList');
elem.innerHTML = html;
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) {
@ -122,7 +141,7 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
}
}
var searchImages = elem.querySelectorAll('.card');
const searchImages = elem.querySelectorAll('.card');
for (i = 0, length = searchImages.length; i < length; i++) {
searchImages[i].addEventListener('click', onSearchImageClick);
@ -143,7 +162,7 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
function showIdentifyOptions(page, identifyResult) {
var identifyOptionsForm = page.querySelector('.identifyOptionsForm');
const identifyOptionsForm = page.querySelector('.identifyOptionsForm');
page.querySelector('.popupIdentifyForm').classList.add('hide');
page.querySelector('.identificationSearchResults').classList.add('hide');
@ -153,19 +172,19 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
currentSearchResult = identifyResult;
var lines = [];
const lines = [];
lines.push(identifyResult.Name);
if (identifyResult.ProductionYear) {
lines.push(identifyResult.ProductionYear);
}
var resultHtml = lines.join('<br/>');
let resultHtml = lines.join('<br/>');
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;
@ -177,10 +196,10 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
// TODO move card creation code to Card component
var html = '';
var cssClass = 'card scalableCard';
var cardBoxCssClass = 'cardBox';
var padderClass;
let html = '';
let cssClass = 'card scalableCard';
let cardBoxCssClass = 'cardBox';
let padderClass;
if (currentItemType === 'Episode') {
cssClass += ' backdropCard backdropCard-scalable';
@ -203,30 +222,32 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
cardBoxCssClass += ' cardBox-bottompadded';
html += '<button type="button" class="' + cssClass + '" data-index="' + index + '">';
html += '<div class="' + cardBoxCssClass + '">';
html += `<button type="button" class="${cssClass}" data-index="${index}">`;
html += `<div class="${cardBoxCssClass}">`;
html += '<div class="cardScalable">';
html += '<div class="' + padderClass + '"></div>';
html += `<div class="${padderClass}"></div>`;
html += '<div class="cardContent searchImage">';
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 {
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>';
var numLines = 2;
let numLines = 3;
if (currentItemType === 'MusicAlbum') {
numLines++;
}
var lines = [result.Name];
const lines = [result.Name];
lines.push(result.SearchProviderName);
if (result.AlbumArtist) {
lines.push(result.AlbumArtist.Name);
@ -235,7 +256,7 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
lines.push(result.ProductionYear);
}
for (var i = 0; i < numLines; i++) {
for (let i = 0; i < numLines; i++) {
if (i === 0) {
html += '<div class="cardText cardText-first cardTextCentered">';
@ -252,7 +273,7 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
}
function getSearchImageDisplayUrl(url, provider) {
var apiClient = getApiClient();
const apiClient = getApiClient();
return apiClient.getUrl('Items/RemoteSearch/Image', { imageUrl: url, ProviderName: provider });
}
@ -261,26 +282,26 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
loading.show();
var options = {
const options = {
ReplaceAllImages: page.querySelector('#chkIdentifyReplaceImages').checked
};
var apiClient = getApiClient();
const apiClient = getApiClient();
apiClient.ajax({
type: 'POST',
url: apiClient.getUrl('Items/RemoteSearch/Apply/' + currentItem.Id, options),
url: apiClient.getUrl(`Items/RemoteSearch/Apply/${currentItem.Id}`, options),
data: JSON.stringify(currentSearchResult),
contentType: 'application/json'
}).then(function () {
}).then(() => {
hasChanges = true;
loading.hide();
dialogHelper.close(page);
}, function () {
}, () => {
loading.hide();
@ -290,28 +311,28 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
function showIdentificationForm(page, item) {
var apiClient = getApiClient();
const apiClient = getApiClient();
apiClient.getJSON(apiClient.getUrl('Items/' + item.Id + '/ExternalIdInfos')).then(function (idList) {
apiClient.getJSON(apiClient.getUrl(`Items/${item.Id}/ExternalIdInfos`)).then(idList => {
var html = '';
let html = '';
for (var i = 0, length = idList.length; i < length; i++) {
for (let i = 0, length = idList.length; i < length; i++) {
var idInfo = idList[i];
const idInfo = idList[i];
var id = 'txtLookup' + idInfo.Key;
const id = `txtLookup${idInfo.Key}`;
html += '<div class="inputContainer">';
var fullName = idInfo.Name;
let fullName = idInfo.Name;
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>';
}
@ -338,16 +359,16 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
loading.show();
require(['text!./itemidentifier.template.html'], function (template) {
return import('text!./itemidentifier.template.html').then(({default: template}) => {
var apiClient = getApiClient();
const apiClient = getApiClient();
apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) {
apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(item => {
currentItem = item;
currentItemType = currentItem.Type;
var dialogOptions = {
const dialogOptions = {
size: 'small',
removeOnClose: true,
scrollY: false
@ -357,13 +378,13 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
dialogOptions.size = 'fullscreen';
}
var dlg = dialogHelper.createDialog(dialogOptions);
const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog');
dlg.classList.add('recordingDialog');
var html = '';
html += globalize.translateDocument(template, 'core');
let html = '';
html += globalize.translateHtml(template, 'core');
dlg.innerHTML = html;
@ -384,21 +405,21 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
dialogHelper.open(dlg);
dlg.querySelector('.popupIdentifyForm').addEventListener('submit', function (e) {
dlg.querySelector('.popupIdentifyForm').addEventListener('submit', e => {
e.preventDefault();
searchForIdentificationResults(dlg);
return false;
});
dlg.querySelector('.identifyOptionsForm').addEventListener('submit', function (e) {
dlg.querySelector('.identifyOptionsForm').addEventListener('submit', e => {
e.preventDefault();
submitIdentficationResult(dlg);
return false;
});
dlg.querySelector('.btnCancel').addEventListener('click', function (e) {
dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg);
});
@ -421,14 +442,15 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
}
}
// TODO investigate where this was used
function showEditorFindNew(itemName, itemYear, itemType, resolveFunc) {
currentItem = null;
currentItemType = itemType;
require(['text!./itemidentifier.template.html'], function (template) {
return import('text!./itemidentifier.template.html').then(({default: template}) => {
var dialogOptions = {
const dialogOptions = {
size: 'small',
removeOnClose: true,
scrollY: false
@ -438,13 +460,13 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
dialogOptions.size = 'fullscreen';
}
var dlg = dialogHelper.createDialog(dialogOptions);
const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog');
dlg.classList.add('recordingDialog');
var html = '';
html += globalize.translateDocument(template, 'core');
let html = '';
html += globalize.translateHtml(template, 'core');
dlg.innerHTML = html;
@ -454,22 +476,22 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
dialogHelper.open(dlg);
dlg.querySelector('.btnCancel').addEventListener('click', function (e) {
dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg);
});
dlg.querySelector('.popupIdentifyForm').addEventListener('submit', function (e) {
dlg.querySelector('.popupIdentifyForm').addEventListener('submit', e => {
e.preventDefault();
searchForIdentificationResults(dlg);
return false;
});
dlg.addEventListener('close', function () {
dlg.addEventListener('close', () => {
loading.hide();
var foundItem = hasChanges ? currentSearchResult : null;
const foundItem = hasChanges ? currentSearchResult : null;
resolveFunc(foundItem);
});
@ -498,10 +520,9 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
dlg.querySelector('.formDialogHeaderTitle').innerHTML = globalize.translate('Search');
}
return {
show: function (itemId, serverId) {
export function show(itemId, serverId) {
return new Promise(function (resolve, reject) {
return new Promise((resolve, reject) => {
currentResolve = resolve;
currentReject = reject;
@ -510,11 +531,11 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
showEditor(itemId);
});
},
}
showFindNew: function (itemName, itemYear, itemType, serverId) {
export function showFindNew(itemName, itemYear, itemType, serverId) {
return new Promise(function (resolve, reject) {
return new Promise((resolve) => {
currentServerId = serverId;
@ -522,5 +543,9 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
showEditorFindNew(itemName, itemYear, itemType, resolve);
});
}
};
});
/* eslint-enable indent */
export default {
show: show,
showFindNew: showFindNew
};

View file

@ -11,9 +11,9 @@
(entries) => {
entries.forEach(entry => {
callback(entry);
},
{rootMargin: '50%'});
});
},
{rootMargin: '25%'});
this.observer = observer;
}

View file

@ -1,63 +1,73 @@
define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], function(globalize, dom) {
'use strict';
/* eslint-disable indent */
/**
* 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) {
return ApiClient.getCultures().then(function(languages) {
return ApiClient.getCultures().then(languages => {
populateLanguagesIntoSelect(parent.querySelector('#selectLanguage'), languages);
populateLanguagesIntoList(parent.querySelector('.subtitleDownloadLanguages'), languages);
});
}
function populateLanguagesIntoSelect(select, languages) {
var html = '';
let html = '';
html += "<option value=''></option>";
for (var i = 0; i < languages.length; i++) {
var culture = languages[i];
html += "<option value='" + culture.TwoLetterISOLanguageName + "'>" + culture.DisplayName + '</option>';
for (let i = 0; i < languages.length; i++) {
const culture = languages[i];
html += `<option value='${culture.TwoLetterISOLanguageName}'>${culture.DisplayName}</option>`;
}
select.innerHTML = html;
}
function populateLanguagesIntoList(element, languages) {
var html = '';
for (var i = 0; i < languages.length; i++) {
var culture = languages[i];
html += '<label><input type="checkbox" is="emby-checkbox" class="chkSubtitleLanguage" data-lang="' + culture.ThreeLetterISOLanguageName.toLowerCase() + '" /><span>' + culture.DisplayName + '</span></label>';
let html = '';
for (let i = 0; i < languages.length; 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>`;
}
element.innerHTML = html;
}
function populateCountries(select) {
return ApiClient.getCountries().then(function(allCountries) {
var html = '';
return ApiClient.getCountries().then(allCountries => {
let html = '';
html += "<option value=''></option>";
for (var i = 0; i < allCountries.length; i++) {
var culture = allCountries[i];
html += "<option value='" + culture.TwoLetterISORegionName + "'>" + culture.DisplayName + '</option>';
for (let i = 0; i < allCountries.length; i++) {
const culture = allCountries[i];
html += `<option value='${culture.TwoLetterISORegionName}'>${culture.DisplayName}</option>`;
}
select.innerHTML = html;
});
}
function populateRefreshInterval(select) {
var html = '';
html += "<option value='0'>" + globalize.translate('Never') + '</option>';
html += [30, 60, 90].map(function(val) {
return "<option value='" + val + "'>" + globalize.translate('EveryNDays', val) + '</option>';
let html = '';
html += `<option value='0'>${globalize.translate('Never')}</option>`;
html += [30, 60, 90].map(val => {
return `<option value='${val}'>${globalize.translate('EveryNDays', val)}</option>`;
}).join('');
select.innerHTML = html;
}
function renderMetadataReaders(page, plugins) {
var html = '';
var elem = page.querySelector('.metadataReaders');
let html = '';
const elem = page.querySelector('.metadataReaders');
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">';
for (var i = 0; i < plugins.length; i++) {
var plugin = plugins[i];
html += '<div class="listItem localReaderOption sortableOption" data-pluginname="' + plugin.Name + '">';
for (let i = 0; i < plugins.length; i++) {
const plugin = plugins[i];
html += `<div class="listItem localReaderOption sortableOption" data-pluginname="${plugin.Name}">`;
html += '<span class="listItemIcon material-icons live_tv"></span>';
html += '<div class="listItemBody">';
html += '<h3 class="listItemBodyText">';
@ -65,14 +75,14 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
html += '</h3>';
html += '</div>';
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('ButtonUp')}" class="btnSortableMoveUp btnSortable" data-pluginindex="${i}"><span class="material-icons keyboard_arrow_up"></span></button>`;
} 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('ButtonDown')}" class="btnSortableMoveDown btnSortable" data-pluginindex="${i}"><span class="material-icons keyboard_arrow_down"></span></button>`;
}
html += '</div>';
}
html += '</div>';
html += '<div class="fieldDescription">' + globalize.translate('LabelMetadataReadersHelp') + '</div>';
html += `<div class="fieldDescription">${globalize.translate('LabelMetadataReadersHelp')}</div>`;
if (plugins.length < 2) {
elem.classList.add('hide');
} else {
@ -83,25 +93,25 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
}
function renderMetadataSavers(page, metadataSavers) {
var html = '';
var elem = page.querySelector('.metadataSavers');
let html = '';
const elem = page.querySelector('.metadataSavers');
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">';
for (var i = 0; i < metadataSavers.length; i++) {
var 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>';
for (let i = 0; i < metadataSavers.length; 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 += '</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.classList.remove('hide');
return true;
}
function getMetadataFetchersForTypeHtml(availableTypeOptions, libraryOptionsForType) {
var html = '';
var plugins = availableTypeOptions.MetadataFetchers;
let html = '';
let plugins = availableTypeOptions.MetadataFetchers;
plugins = getOrderedPlugins(plugins, libraryOptionsForType.MetadataFetcherOrder || []);
if (!plugins.length) return html;
@ -112,15 +122,20 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
plugins.forEach((plugin, index) => {
html += '<div class="listItem metadataFetcherItem sortableOption" data-pluginname="' + plugin.Name + '">';
var isChecked = libraryOptionsForType.MetadataFetchers ? -1 !== libraryOptionsForType.MetadataFetchers.indexOf(plugin.Name) : plugin.DefaultEnabled;
var checkedHtml = isChecked ? ' checked="checked"' : '';
const isChecked = libraryOptionsForType.MetadataFetchers ? libraryOptionsForType.MetadataFetchers.includes(plugin.Name) : plugin.DefaultEnabled;
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 += '<div class="listItemBody">';
html += '<h3 class="listItemBodyText">';
html += plugin.Name;
html += '</h3>';
html += '</div>';
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>' : 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 += '</div>';
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>';
} 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 += '</div>';
});
html += '</div>';
@ -130,19 +145,19 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
}
function getTypeOptions(allOptions, type) {
var allTypeOptions = allOptions.TypeOptions || [];
for (var i = 0; i < allTypeOptions.length; i++) {
var typeOptions = allTypeOptions[i];
const allTypeOptions = allOptions.TypeOptions || [];
for (let i = 0; i < allTypeOptions.length; i++) {
const typeOptions = allTypeOptions[i];
if (typeOptions.Type === type) return typeOptions;
}
return null;
}
function renderMetadataFetchers(page, availableOptions, libraryOptions) {
var html = '';
var elem = page.querySelector('.metadataFetchers');
for (var i = 0; i < availableOptions.TypeOptions.length; i++) {
var availableTypeOptions = availableOptions.TypeOptions[i];
let html = '';
const elem = page.querySelector('.metadataFetchers');
for (let i = 0; i < availableOptions.TypeOptions.length; i++) {
const availableTypeOptions = availableOptions.TypeOptions[i];
html += getMetadataFetchersForTypeHtml(availableTypeOptions, getTypeOptions(libraryOptions, availableTypeOptions.Type) || {});
}
elem.innerHTML = html;
@ -161,41 +176,41 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
}
function renderSubtitleFetchers(page, availableOptions, libraryOptions) {
var html = '';
var elem = page.querySelector('.subtitleFetchers');
let html = '';
const elem = page.querySelector('.subtitleFetchers');
var plugins = availableOptions.SubtitleFetchers;
let plugins = availableOptions.SubtitleFetchers;
plugins = getOrderedPlugins(plugins, libraryOptions.SubtitleFetcherOrder || []);
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">';
for (var i = 0; i < plugins.length; i++) {
var plugin = plugins[i];
html += '<div class="listItem subtitleFetcherItem sortableOption" data-pluginname="' + plugin.Name + '">';
var isChecked = libraryOptions.DisabledSubtitleFetchers ? -1 === libraryOptions.DisabledSubtitleFetchers.indexOf(plugin.Name) : plugin.DefaultEnabled;
var checkedHtml = isChecked ? ' checked="checked"' : '';
html += '<label class="listItemCheckboxContainer"><input type="checkbox" is="emby-checkbox" class="chkSubtitleFetcher" data-pluginname="' + plugin.Name + '" ' + checkedHtml + '><span></span></label>';
for (let i = 0; i < plugins.length; i++) {
const plugin = plugins[i];
html += `<div class="listItem subtitleFetcherItem sortableOption" data-pluginname="${plugin.Name}">`;
const isChecked = libraryOptions.DisabledSubtitleFetchers ? !libraryOptions.DisabledSubtitleFetchers.includes(plugin.Name) : plugin.DefaultEnabled;
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 += '<div class="listItemBody">';
html += '<h3 class="listItemBodyText">';
html += plugin.Name;
html += '</h3>';
html += '</div>';
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('ButtonUp')}" class="btnSortableMoveUp btnSortable" data-pluginindex="${i}"><span class="material-icons keyboard_arrow_up"></span></button>`;
} 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('ButtonDown')}" class="btnSortableMoveDown btnSortable" data-pluginindex="${i}"><span class="material-icons keyboard_arrow_down"></span></button>`;
}
html += '</div>';
}
html += '</div>';
html += '<div class="fieldDescription">' + globalize.translate('SubtitleDownloadersHelp') + '</div>';
html += `<div class="fieldDescription">${globalize.translate('SubtitleDownloadersHelp')}</div>`;
elem.innerHTML = html;
}
function getImageFetchersForTypeHtml(availableTypeOptions, libraryOptionsForType) {
var html = '';
var plugins = availableTypeOptions.ImageFetchers;
let html = '';
let plugins = availableTypeOptions.ImageFetchers;
plugins = getOrderedPlugins(plugins, libraryOptionsForType.ImageFetcherOrder || []);
if (!plugins.length) return html;
@ -203,17 +218,17 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
html += '<div class="imageFetcher" data-type="' + availableTypeOptions.Type + '">';
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>';
var supportedImageTypes = availableTypeOptions.SupportedImageTypes || [];
const supportedImageTypes = availableTypeOptions.SupportedImageTypes || [];
if (supportedImageTypes.length > 1 || 1 === supportedImageTypes.length && 'Primary' !== supportedImageTypes[0]) {
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 class="checkboxList paperList checkboxList-paperList">';
for (var i = 0; i < plugins.length; i++) {
var plugin = plugins[i];
for (let i = 0; i < plugins.length; i++) {
const plugin = plugins[i];
html += '<div class="listItem imageFetcherItem sortableOption" data-pluginname="' + plugin.Name + '">';
var isChecked = libraryOptionsForType.ImageFetchers ? -1 !== libraryOptionsForType.ImageFetchers.indexOf(plugin.Name) : plugin.DefaultEnabled;
var checkedHtml = isChecked ? ' checked="checked"' : '';
const isChecked = libraryOptionsForType.ImageFetchers ? libraryOptionsForType.ImageFetchers.includes(plugin.Name) : plugin.DefaultEnabled;
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 += '<div class="listItemBody">';
html += '<h3 class="listItemBodyText">';
@ -234,10 +249,10 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
}
function renderImageFetchers(page, availableOptions, libraryOptions) {
var html = '';
var elem = page.querySelector('.imageFetchers');
for (var i = 0; i < availableOptions.TypeOptions.length; i++) {
var availableTypeOptions = availableOptions.TypeOptions[i];
let html = '';
const elem = page.querySelector('.imageFetchers');
for (let i = 0; i < availableOptions.TypeOptions.length; i++) {
const availableTypeOptions = availableOptions.TypeOptions[i];
html += getImageFetchersForTypeHtml(availableTypeOptions, getTypeOptions(libraryOptions, availableTypeOptions.Type) || {});
}
elem.innerHTML = html;
@ -253,12 +268,12 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
return true;
}
function populateMetadataSettings(parent, contentType, isNewLibrary) {
var isNewLibrary = parent.classList.contains('newlibrary');
function populateMetadataSettings(parent, contentType) {
const isNewLibrary = parent.classList.contains('newlibrary');
return ApiClient.getJSON(ApiClient.getUrl('Libraries/AvailableOptions', {
LibraryContentType: contentType,
IsNewLibrary: isNewLibrary
})).then(function(availableOptions) {
})).then(availableOptions => {
currentAvailableOptions = availableOptions;
parent.availableOptions = availableOptions;
renderMetadataSavers(parent, availableOptions.MetadataSavers);
@ -267,14 +282,14 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
renderSubtitleFetchers(parent, availableOptions, {});
renderImageFetchers(parent, availableOptions, {});
availableOptions.SubtitleFetchers.length ? parent.querySelector('.subtitleDownloadSettings').classList.remove('hide') : parent.querySelector('.subtitleDownloadSettings').classList.add('hide');
}).catch(function() {
}).catch(() => {
return Promise.resolve();
});
}
function adjustSortableListElement(elem) {
var btnSortable = elem.querySelector('.btnSortable');
var inner = btnSortable.querySelector('.material-icons');
const btnSortable = elem.querySelector('.btnSortable');
const inner = btnSortable.querySelector('.material-icons');
if (elem.previousSibling) {
btnSortable.title = globalize.translate('ButtonUp');
btnSortable.classList.add('btnSortableMoveUp');
@ -291,22 +306,22 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
}
function showImageOptionsForType(type) {
require(['imageoptionseditor'], function(ImageOptionsEditor) {
var typeOptions = getTypeOptions(currentLibraryOptions, type);
import('imageoptionseditor').then(({default: ImageOptionsEditor}) => {
let typeOptions = getTypeOptions(currentLibraryOptions, type);
if (!typeOptions) {
typeOptions = {
Type: type
};
currentLibraryOptions.TypeOptions.push(typeOptions);
}
var availableOptions = getTypeOptions(currentAvailableOptions || {}, type);
var imageOptionsEditor = new ImageOptionsEditor();
const availableOptions = getTypeOptions(currentAvailableOptions || {}, type);
const imageOptionsEditor = new ImageOptionsEditor();
imageOptionsEditor.show(type, typeOptions, availableOptions);
});
}
function onImageFetchersContainerClick(e) {
var btnImageOptionsForType = dom.parentWithClass(e.target, 'btnImageOptionsForType');
const btnImageOptionsForType = dom.parentWithClass(e.target, 'btnImageOptionsForType');
if (btnImageOptionsForType) {
return void showImageOptionsForType(dom.parentWithClass(btnImageOptionsForType, 'imageFetcher').getAttribute('data-type'));
}
@ -314,18 +329,18 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
}
function onSortableContainerClick(e) {
var btnSortable = dom.parentWithClass(e.target, 'btnSortable');
const btnSortable = dom.parentWithClass(e.target, 'btnSortable');
if (btnSortable) {
var li = dom.parentWithClass(btnSortable, 'sortableOption');
var list = dom.parentWithClass(li, 'paperList');
const li = dom.parentWithClass(btnSortable, 'sortableOption');
const list = dom.parentWithClass(li, 'paperList');
if (btnSortable.classList.contains('btnSortableMoveDown')) {
var next = li.nextSibling;
const next = li.nextSibling;
if (next) {
li.parentNode.removeChild(li);
next.parentNode.insertBefore(li, next.nextSibling);
}
} else {
var prev = li.previousSibling;
const prev = li.previousSibling;
if (prev) {
li.parentNode.removeChild(li);
prev.parentNode.insertBefore(li, prev);
@ -342,41 +357,35 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
parent.querySelector('.imageFetchers').addEventListener('click', onImageFetchersContainerClick);
}
function embed(parent, contentType, libraryOptions) {
export async function embed(parent, contentType, libraryOptions) {
currentLibraryOptions = {
TypeOptions: []
};
currentAvailableOptions = null;
var isNewLibrary = null === libraryOptions;
const isNewLibrary = null === libraryOptions;
isNewLibrary && parent.classList.add('newlibrary');
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest;
xhr.open('GET', 'components/libraryoptionseditor/libraryoptionseditor.template.html', true);
xhr.onload = function(e) {
var template = this.response;
parent.innerHTML = globalize.translateDocument(template);
const response = await fetch('components/libraryoptionseditor/libraryoptionseditor.template.html');
const template = await response.text();
parent.innerHTML = globalize.translateHtml(template);
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() {
return setContentType(parent, contentType).then(function() {
libraryOptions && setLibraryOptions(parent, libraryOptions);
bindEvents(parent);
resolve();
return;
});
});
};
xhr.send();
});
}
function setAdvancedVisible(parent, visible) {
var elems = parent.querySelectorAll('.advanced');
for (var i = 0; i < elems.length; i++) {
export function setAdvancedVisible(parent, visible) {
const elems = parent.querySelectorAll('.advanced');
for (let i = 0; i < elems.length; i++) {
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') {
parent.querySelector('.chkEnablePhotosContainer').classList.remove('hide');
} else {
@ -417,47 +426,47 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
}
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;
}), function(elem) {
}), elem => {
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');
});
}
function setMetadataFetchersIntoOptions(parent, options) {
var sections = parent.querySelectorAll('.metadataFetcher');
for (var i = 0; i < sections.length; i++) {
var section = sections[i];
var type = section.getAttribute('data-type');
var typeOptions = getTypeOptions(options, type);
const sections = parent.querySelectorAll('.metadataFetcher');
for (let i = 0; i < sections.length; i++) {
const section = sections[i];
const type = section.getAttribute('data-type');
let typeOptions = getTypeOptions(options, type);
if (!typeOptions) {
typeOptions = {
Type: type
};
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;
}), function(elem) {
}), elem => {
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');
});
}
}
function setImageFetchersIntoOptions(parent, options) {
var sections = parent.querySelectorAll('.imageFetcher');
for (var i = 0; i < sections.length; i++) {
var section = sections[i];
var type = section.getAttribute('data-type');
var typeOptions = getTypeOptions(options, type);
const sections = parent.querySelectorAll('.imageFetcher');
for (let i = 0; i < sections.length; i++) {
const section = sections[i];
const type = section.getAttribute('data-type');
let typeOptions = getTypeOptions(options, type);
if (!typeOptions) {
typeOptions = {
Type: type
@ -465,23 +474,23 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
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;
}), function(elem) {
}), elem => {
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');
});
}
}
function setImageOptionsIntoOptions(parent, options) {
var originalTypeOptions = (currentLibraryOptions || {}).TypeOptions || [];
for (var i = 0; i < originalTypeOptions.length; i++) {
var originalTypeOption = originalTypeOptions[i];
var typeOptions = getTypeOptions(options, originalTypeOption.Type);
function setImageOptionsIntoOptions(options) {
const originalTypeOptions = (currentLibraryOptions || {}).TypeOptions || [];
for (let i = 0; i < originalTypeOptions.length; i++) {
const originalTypeOption = originalTypeOptions[i];
let typeOptions = getTypeOptions(options, originalTypeOption.Type);
if (!typeOptions) {
typeOptions = {
@ -493,8 +502,8 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
}
}
function getLibraryOptions(parent) {
var options = {
export function getLibraryOptions(parent) {
const options = {
EnableArchiveMediaFiles: false,
EnablePhotos: parent.querySelector('.chkEnablePhotos').checked,
EnableRealtimeMonitor: parent.querySelector('.chkEnableRealtimeMonitor').checked,
@ -515,39 +524,39 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
SkipSubtitlesIfAudioTrackMatches: parent.querySelector('#chkSkipIfAudioTrackPresent').checked,
SaveSubtitlesWithMedia: parent.querySelector('#chkSaveSubtitlesLocally').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;
}), function(elem) {
}), elem => {
return elem.getAttribute('data-pluginname');
}),
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');
});
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;
}), function(elem) {
}), elem => {
return elem.getAttribute('data-lang');
});
setSubtitleFetchersIntoOptions(parent, options);
setMetadataFetchersIntoOptions(parent, options);
setImageFetchersIntoOptions(parent, options);
setImageOptionsIntoOptions(parent, options);
setImageOptionsIntoOptions(options);
return options;
}
function getOrderedPlugins(plugins, configuredOrder) {
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 plugins;
}
function setLibraryOptions(parent, options) {
export function setLibraryOptions(parent, options) {
currentLibraryOptions = options;
currentAvailableOptions = parent.availableOptions;
parent.querySelector('#selectLanguage').value = options.PreferredMetadataLanguage || '';
@ -568,11 +577,11 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
parent.querySelector('#chkSaveSubtitlesLocally').checked = options.SaveSubtitlesWithMedia;
parent.querySelector('#chkSkipIfAudioTrackPresent').checked = options.SkipSubtitlesIfAudioTrackMatches;
parent.querySelector('#chkRequirePerfectMatch').checked = options.RequirePerfectSubtitleMatch;
Array.prototype.forEach.call(parent.querySelectorAll('.chkMetadataSaver'), function(elem) {
elem.checked = options.MetadataSavers ? -1 !== options.MetadataSavers.indexOf(elem.getAttribute('data-pluginname')) : 'true' === elem.getAttribute('data-defaultenabled');
Array.prototype.forEach.call(parent.querySelectorAll('.chkMetadataSaver'), elem => {
elem.checked = options.MetadataSavers ? options.MetadataSavers.includes(elem.getAttribute('data-pluginname')) : 'true' === elem.getAttribute('data-defaultenabled');
});
Array.prototype.forEach.call(parent.querySelectorAll('.chkSubtitleLanguage'), function(elem) {
elem.checked = !!options.SubtitleDownloadLanguages && -1 !== options.SubtitleDownloadLanguages.indexOf(elem.getAttribute('data-lang'));
Array.prototype.forEach.call(parent.querySelectorAll('.chkSubtitleLanguage'), elem => {
elem.checked = !!options.SubtitleDownloadLanguages && options.SubtitleDownloadLanguages.includes(elem.getAttribute('data-lang'));
});
renderMetadataReaders(parent, getOrderedPlugins(parent.availableOptions.MetadataReaders, options.LocalMetadataReaderOrder || []));
renderMetadataFetchers(parent, parent.availableOptions, options);
@ -580,14 +589,14 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
renderSubtitleFetchers(parent, parent.availableOptions, options);
}
var currentLibraryOptions;
var currentAvailableOptions;
let currentLibraryOptions;
let currentAvailableOptions;
return {
/* eslint-enable indent */
export default {
embed: embed,
setContentType: setContentType,
getLibraryOptions: getLibraryOptions,
setLibraryOptions: setLibraryOptions,
setAdvancedVisible: setAdvancedVisible
};
});
};

View file

@ -79,7 +79,7 @@
<div class="checkboxContainer checkboxContainer-withDescription chkAutomaticallyGroupSeriesContainer hide advanced">
<label>
<input type="checkbox" is="emby-checkbox" class="chkAutomaticallyGroupSeries" checked />
<input type="checkbox" is="emby-checkbox" class="chkAutomaticallyGroupSeries" />
<span>${OptionAutomaticallyGroupSeries}</span>
</label>
<div class="fieldDescription checkboxFieldDescription">${OptionAutomaticallyGroupSeriesHelp}</div>

View file

@ -1,5 +1,21 @@
define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutManager', 'globalize', 'datetime', 'apphost', 'css!./listview', 'emby-ratingbutton', 'emby-playstatebutton'], function (itemHelper, mediaInfo, indicators, connectionManager, layoutManager, globalize, datetime, appHost) {
'use strict';
/* eslint-disable indent */
/**
* Module for display list view.
* @module components/listview/listview
*/
import itemHelper from 'itemHelper';
import mediaInfo from 'mediaInfo';
import indicators from 'indicators';
import connectionManager from 'connectionManager';
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) {
@ -8,9 +24,9 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
return item.ParentIndexNumber == null ? '' : globalize.translate('ValueDiscNumber', item.ParentIndexNumber);
}
var sortBy = (options.sortBy || '').toLowerCase();
var code;
var name;
const sortBy = (options.sortBy || '').toLowerCase();
let code;
let name;
if (sortBy.indexOf('sortname') === 0) {
@ -69,72 +85,64 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
function getImageUrl(item, width) {
var apiClient = connectionManager.getApiClient(item.ServerId);
const apiClient = connectionManager.getApiClient(item.ServerId);
let itemId;
var options = {
const options = {
maxWidth: width * 2,
type: 'Primary'
};
if (item.ImageTags && item.ImageTags.Primary) {
options.tag = item.ImageTags.Primary;
return apiClient.getScaledImageUrl(item.Id, options);
}
if (item.AlbumId && item.AlbumPrimaryImageTag) {
itemId = item.Id;
} else if (item.AlbumId && item.AlbumPrimaryImageTag) {
options.tag = item.AlbumPrimaryImageTag;
return apiClient.getScaledImageUrl(item.AlbumId, options);
itemId = item.AlbumId;
} else if (item.SeriesId && item.SeriesPrimaryImageTag) {
options.tag = item.SeriesPrimaryImageTag;
return apiClient.getScaledImageUrl(item.SeriesId, options);
itemId = item.SeriesId;
} else if (item.ParentPrimaryImageTag) {
options.tag = item.ParentPrimaryImageTag;
return apiClient.getScaledImageUrl(item.ParentPrimaryImageItemId, options);
itemId = item.ParentPrimaryImageItemId;
}
if (itemId) {
return apiClient.getScaledImageUrl(itemId, options);
}
return null;
}
function getChannelImageUrl(item, width) {
var apiClient = connectionManager.getApiClient(item.ServerId);
var options = {
const apiClient = connectionManager.getApiClient(item.ServerId);
const options = {
maxWidth: width * 2,
type: 'Primary'
};
if (item.ChannelId && item.ChannelPrimaryImageTag) {
options.tag = item.ChannelPrimaryImageTag;
return apiClient.getScaledImageUrl(item.ChannelId, options);
}
return null;
if (item.ChannelId) {
return apiClient.getScaledImageUrl(item.ChannelId, options);
}
}
function getTextLinesHtml(textlines, isLargeStyle) {
let html = '';
var html = '';
var largeTitleTagName = layoutManager.tv ? 'h2' : 'div';
for (var i = 0, length = textlines.length; i < length; i++) {
var text = textlines[i];
const largeTitleTagName = layoutManager.tv ? 'h2' : 'div';
for (const [i, text] of textlines.entries()) {
if (!text) {
continue;
}
if (i === 0) {
if (isLargeStyle) {
html += '<' + largeTitleTagName + ' class="listItemBodyText">';
html += `<${largeTitleTagName} class="listItemBodyText">`;
} else {
html += '<div class="listItemBodyText">';
}
@ -143,7 +151,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
}
html += (textlines[i] || '&nbsp;');
if (i === 0 && isLargeStyle) {
html += '</' + largeTitleTagName + '>';
html += `</${largeTitleTagName}>`;
} else {
html += '</div>';
}
@ -154,13 +162,13 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
function getRightButtonsHtml(options) {
var html = '';
let html = '';
for (var i = 0, length = options.rightButtons.length; i < length; i++) {
for (let i = 0, length = options.rightButtons.length; i < length; i++) {
var button = options.rightButtons[i];
const 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>';
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;
@ -170,34 +178,34 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
return item.Id;
}
function getListViewHtml(options) {
export function getListViewHtml(options) {
var items = options.items;
const items = options.items;
var groupTitle = '';
var action = options.action || 'link';
let groupTitle = '';
const action = options.action || 'link';
var isLargeStyle = options.imageSize === 'large';
var enableOverview = options.enableOverview;
const isLargeStyle = options.imageSize === 'large';
const enableOverview = options.enableOverview;
var clickEntireItem = layoutManager.tv ? true : false;
var outerTagName = clickEntireItem ? 'button' : 'div';
var enableSideMediaInfo = options.enableSideMediaInfo != null ? options.enableSideMediaInfo : true;
const clickEntireItem = layoutManager.tv ? true : false;
const outerTagName = clickEntireItem ? 'button' : 'div';
const enableSideMediaInfo = options.enableSideMediaInfo != null ? options.enableSideMediaInfo : true;
var outerHtml = '';
let outerHtml = '';
var enableContentWrapper = options.enableOverview && !layoutManager.tv;
var containerAlbumArtistIds = (options.containerAlbumArtists || []).map(getId);
const enableContentWrapper = options.enableOverview && !layoutManager.tv;
const containerAlbumArtistIds = (options.containerAlbumArtists || []).map(getId);
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 html = '';
let html = '';
if (options.showIndex) {
var itemGroupTitle = getIndex(item, options);
const itemGroupTitle = getIndex(item, options);
if (itemGroupTitle !== groupTitle) {
@ -219,7 +227,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
}
}
var cssClass = 'listItem';
let cssClass = 'listItem';
if (options.border || (options.highlight !== false && !layoutManager.tv)) {
cssClass += ' listItem-border';
@ -233,28 +241,28 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
cssClass += ' listItem-focusscale';
}
var downloadWidth = 80;
let downloadWidth = 80;
if (isLargeStyle) {
cssClass += ' listItem-largeImage';
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 + '"') : '';
var collectionIdData = options.collectionId ? (' data-collectionid="' + options.collectionId + '"') : '';
var playlistIdData = options.playlistId ? (' data-playlistid="' + options.playlistId + '"') : '';
var mediaTypeData = item.MediaType ? (' data-mediatype="' + item.MediaType + '"') : '';
var collectionTypeData = item.CollectionType ? (' data-collectiontype="' + item.CollectionType + '"') : '';
var channelIdData = item.ChannelId ? (' data-channelid="' + item.ChannelId + '"') : '';
const positionTicksData = item.UserData && item.UserData.PlaybackPositionTicks ? (` data-positionticks="${item.UserData.PlaybackPositionTicks}"`) : '';
const collectionIdData = options.collectionId ? (` data-collectionid="${options.collectionId}"`) : '';
const playlistIdData = options.playlistId ? (` data-playlistid="${options.playlistId}"`) : '';
const mediaTypeData = item.MediaType ? (` data-mediatype="${item.MediaType}"`) : '';
const collectionTypeData = item.CollectionType ? (` data-collectiontype="${item.CollectionType}"`) : '';
const channelIdData = item.ChannelId ? (` data-channelid="${item.ChannelId}"`) : '';
if (enableContentWrapper) {
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) {
@ -275,32 +283,32 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
imageClass += ' listItemImage-large-tv';
}
var playOnImageClick = options.imagePlayButton && !layoutManager.tv;
const playOnImageClick = options.imagePlayButton && !layoutManager.tv;
if (!clickEntireItem) {
imageClass += ' itemAction';
}
var imageAction = playOnImageClick ? 'resume' : action;
const imageAction = playOnImageClick ? 'link' : action;
if (imgUrl) {
html += '<div data-action="' + imageAction + '" class="' + imageClass + ' lazy" data-src="' + imgUrl + '" item-icon>';
} 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);
if (indicatorsHtml) {
html += '<div class="indicators listItemIndicators">' + indicatorsHtml + '</div>';
html += `<div class="indicators listItemIndicators">${indicatorsHtml}</div>`;
}
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>';
}
var progressHtml = indicators.getProgressBarHtml(item, {
const progressHtml = indicators.getProgressBarHtml(item, {
containerClass: 'listItemProgressBar'
});
@ -317,7 +325,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
html += '</div>';
}
var textlines = [];
const textlines = [];
if (options.showProgramDateTime) {
textlines.push(datetime.toLocaleString(datetime.parseISO8601Date(item.StartDate), {
@ -340,7 +348,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
}
}
var parentTitle = null;
let parentTitle = null;
if (options.showParentTitle) {
if (item.Type === 'Episode') {
@ -350,12 +358,12 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
}
}
var displayName = itemHelper.getDisplayName(item, {
let displayName = itemHelper.getDisplayName(item, {
includeParentInfo: options.includeParentInfoInTitle
});
if (options.showIndexNumber && item.IndexNumber != null) {
displayName = item.IndexNumber + '. ' + displayName;
displayName = `${item.IndexNumber}. ${displayName}`;
}
if (options.showParentTitle && options.parentTitleWithTitle) {
@ -386,14 +394,14 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
}
} else {
var showArtist = options.artist === true;
var artistItems = item.ArtistItems;
let showArtist = options.artist === true;
const 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) {
} else if (artistItems.length > 1 || !containerAlbumArtistIds.includes(artistItems[0].Id)) {
showArtist = true;
}
}
@ -401,7 +409,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
if (showArtist) {
if (artistItems && item.Type !== 'MusicAlbum') {
textlines.push(artistItems.map(function (a) {
textlines.push(artistItems.map(a => {
return a.Name;
}).join(', '));
}
@ -424,23 +432,23 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
cssClass += ' listItemBody-noleftpadding';
}
html += '<div class="' + cssClass + '">';
const moreIcon = 'more_vert';
html += `<div class="${cssClass}">`;
html += getTextLinesHtml(textlines, isLargeStyle);
if (options.mediaInfo !== false) {
if (!enableSideMediaInfo) {
var mediaInfoClass = 'secondary listItemMediaInfo listItemBodyText';
const mediaInfoClass = 'secondary listItemMediaInfo listItemBodyText';
html += '<div class="' + mediaInfoClass + '">' + mediaInfo.getPrimaryMediaInfoHtml(item, {
html += `<div class="${mediaInfoClass}">`;
html += mediaInfo.getPrimaryMediaInfoHtml(item, {
episodeTitle: false,
originalAirDate: false,
subtitles: false
}) + '</div>';
});
html += '</div>';
}
}
@ -454,7 +462,8 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
if (options.mediaInfo !== false) {
if (enableSideMediaInfo) {
html += '<div class="secondary listItemMediaInfo">' + mediaInfo.getPrimaryMediaInfoHtml(item, {
html += '<div class="secondary listItemMediaInfo">';
html += mediaInfo.getPrimaryMediaInfoHtml(item, {
year: false,
container: false,
@ -462,7 +471,8 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
criticRating: false,
endsAt: false
}) + '</div>';
});
html += '</div>';
}
}
@ -478,10 +488,6 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
html += '<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="addtoplaylist"><span class="material-icons playlist_add"></span></button>';
}
if (options.moreButton !== false) {
html += '<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="menu"><span class="material-icons ' + moreIcon + '"></span></button>';
}
if (options.infoButton) {
html += '<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="link"><span class="material-icons info_outline"></span></button>';
}
@ -492,17 +498,21 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
if (options.enableUserDataButtons !== false) {
var userData = item.UserData || {};
var likes = userData.Likes == null ? '' : userData.Likes;
const userData = item.UserData || {};
const likes = userData.Likes == null ? '' : userData.Likes;
if (itemHelper.canMarkPlayed(item)) {
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>';
}
if (itemHelper.canRate(item)) {
if (itemHelper.canRate(item) && options.enableRatingButton !== false) {
html += '<button is="emby-ratingbutton" type="button" class="listItemButton paper-icon-button-light" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-likes="' + likes + '" data-isfavorite="' + (userData.IsFavorite) + '"><span class="material-icons favorite"></span></button>';
}
}
if (options.moreButton !== false) {
html += '<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="menu"><span class="material-icons more_vert"></span></button>';
}
}
html += '</div>';
@ -516,7 +526,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
}
}
html += '</' + outerTagName + '>';
html += `</${outerTagName}>`;
outerHtml += html;
}
@ -524,7 +534,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
return outerHtml;
}
return {
/* eslint-enable indent */
export default {
getListViewHtml: getListViewHtml
};
});
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View file

@ -1,10 +1,6 @@
define(['components/loading/loadingLegacy', 'browser', 'css!./loading'], function (loadingLegacy, browser) {
define(['css!./loading'], function () {
'use strict';
if (browser.tizen || browser.operaTv || browser.chromecast || browser.orsay || browser.web0s || browser.ps4) {
return loadingLegacy;
}
var loadingElem;
var layer1;
var layer2;

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,92 +0,0 @@
define(['loading', 'events', 'dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 'require', 'material-icons', 'emby-button', 'paper-icon-button-light', 'emby-input', 'formDialogStyle', 'flexStyles'], function (loading, events, dialogHelper, dom, layoutManager, scrollHelper, globalize, require) {
'use strict';
function showDialog(instance, options, template) {
var dialogOptions = {
removeOnClose: true,
scrollY: false
};
var enableTvLayout = layoutManager.tv;
if (enableTvLayout) {
dialogOptions.size = 'fullscreen';
}
var dlg = dialogHelper.createDialog(dialogOptions);
var configuredButtons = [];
dlg.classList.add('formDialog');
dlg.innerHTML = globalize.translateHtml(template, 'core');
dlg.classList.add('align-items-center');
dlg.classList.add('justify-items-center');
var formDialogContent = dlg.querySelector('.formDialogContent');
formDialogContent.style['flex-grow'] = 'initial';
formDialogContent.style['max-width'] = '50%';
formDialogContent.style['max-height'] = '60%';
if (enableTvLayout) {
scrollHelper.centerFocus.on(formDialogContent, false);
dlg.querySelector('.formDialogHeader').style.marginTop = '15%';
} else {
dlg.classList.add('dialog-fullscreen-lowres');
}
//dlg.querySelector('.btnCancel').addEventListener('click', function (e) {
// dialogHelper.close(dlg);
//});
dlg.querySelector('.formDialogHeaderTitle').innerHTML = options.title;
dlg.querySelector('.text').innerHTML = options.text;
instance.dlg = dlg;
return dialogHelper.open(dlg).then(function () {
if (enableTvLayout) {
scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false);
}
loading.hide();
});
}
function LoadingDialog(options) {
this.options = options;
}
LoadingDialog.prototype.show = function () {
var instance = this;
loading.show();
return new Promise(function (resolve, reject) {
require(['text!./../dialog/dialog.template.html'], function (template) {
showDialog(instance, instance.options, template);
resolve();
});
});
};
LoadingDialog.prototype.setTitle = function (title) {
};
LoadingDialog.prototype.setText = function (text) {
};
LoadingDialog.prototype.hide = function () {
if (this.dlg) {
dialogHelper.close(this.dlg);
this.dlg = null;
}
};
LoadingDialog.prototype.destroy = function () {
this.dlg = null;
this.options = null;
};
return LoadingDialog;
});

View file

@ -1,11 +1,16 @@
define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom, browser, events) {
'use strict';
import dom from 'dom';
import browser from 'browser';
import events from 'events';
import 'emby-tabs';
import 'emby-button';
var tabOwnerView;
var queryScope = document.querySelector('.skinHeader');
var footerTabsContainer;
var headerTabsContainer;
var tabsElem;
/* eslint-disable indent */
let tabOwnerView;
const queryScope = document.querySelector('.skinHeader');
let footerTabsContainer;
let headerTabsContainer;
let tabsElem;
function enableTabsInFooter() {
return false;
@ -44,7 +49,7 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
return false;
}
var classList = elem.classList;
const classList = elem.classList;
if (classList) {
return !classList.contains('scrollX') && !classList.contains('animatedScrollX');
}
@ -52,7 +57,7 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
return true;
}
var parent = target;
let parent = target;
while (parent != null) {
if (!allowSwipeOn(parent)) {
return false;
@ -70,22 +75,22 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
}
// implement without hammer
var pageCount = getTabContainersFn().length;
var onSwipeLeft = function (e, target) {
const pageCount = getTabContainersFn().length;
const onSwipeLeft = function (e, target) {
if (allowSwipe(target) && view.contains(target)) {
tabsElem.selectNext();
}
};
var onSwipeRight = function (e, target) {
const onSwipeRight = function (e, target) {
if (allowSwipe(target) && view.contains(target)) {
tabsElem.selectPrevious();
}
};
require(['touchHelper'], function (TouchHelper) {
import('touchHelper').then(({default: TouchHelper}) => {
var touchHelper = new TouchHelper(view.parentNode.parentNode);
const touchHelper = new TouchHelper(view.parentNode.parentNode);
events.on(touchHelper, 'swipeleft', onSwipeLeft);
events.on(touchHelper, 'swiperight', onSwipeRight);
@ -96,9 +101,9 @@ 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();
const enableInFooter = enableTabsInFooter();
if (!view) {
if (tabOwnerView) {
@ -129,7 +134,7 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
ensureElements(enableInFooter);
var tabsContainerElem = enableInFooter ? footerTabsContainer : headerTabsContainer;
const tabsContainerElem = enableInFooter ? footerTabsContainer : headerTabsContainer;
if (!tabOwnerView) {
tabsContainerElem.classList.remove('hide');
@ -137,18 +142,18 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
if (tabOwnerView !== view) {
var index = 0;
let index = 0;
var indexAttribute = selectedIndex == null ? '' : (' data-index="' + selectedIndex + '"');
var tabsHtml = '<div is="emby-tabs"' + indexAttribute + ' class="tabs-viewmenubar"><div class="emby-tabs-slider" style="white-space:nowrap;">' + getTabsFn().map(function (t) {
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 tabClass = 'emby-tab-button';
let tabClass = 'emby-tab-button';
if (t.enabled === false) {
tabClass += ' hide';
}
var tabHtml;
let tabHtml;
if (t.cssClass) {
tabClass += ' ' + t.cssClass;
@ -177,16 +182,16 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
tabsElem.addEventListener('beforetabchange', function (e) {
var tabContainers = getTabContainersFn();
const tabContainers = getTabContainersFn();
if (e.detail.previousIndex != null) {
var previousPanel = tabContainers[e.detail.previousIndex];
const previousPanel = tabContainers[e.detail.previousIndex];
if (previousPanel) {
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) {
@ -241,9 +246,9 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
};
}
function selectedTabIndex(index) {
export function selectedTabIndex(index) {
var tabsContainerElem = headerTabsContainer;
const tabsContainerElem = headerTabsContainer;
if (!tabsElem) {
tabsElem = tabsContainerElem.querySelector('[is="emby-tabs"]');
@ -256,13 +261,8 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
}
}
function getTabsElement() {
export function getTabsElement() {
return document.querySelector('.tabs-viewmenubar');
}
return {
setTabs: setTabs,
getTabsElement: getTabsElement,
selectedTabIndex: selectedTabIndex
};
});
/* eslint-enable indent */

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

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

View file

@ -41,6 +41,8 @@
width: auto !important;
height: auto !important;
font-size: 1.4em;
margin-right: 0.125em;
color: #f2b01e;
}
.mediaInfoCriticRating {

View file

@ -1,9 +1,18 @@
define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'material-icons', 'css!./mediainfo.css', 'programStyles', 'emby-button'], function (datetime, globalize, appRouter, itemHelper, indicators) {
'use strict';
import datetime from 'datetime';
import globalize from 'globalize';
import appRouter from 'appRouter';
import itemHelper from 'itemHelper';
import indicators from 'indicators';
import 'material-icons';
import 'css!./mediainfo.css';
import 'programStyles';
import 'emby-button';
/* eslint-disable indent */
function getTimerIndicator(item) {
var status;
let status;
if (item.Type === 'SeriesTimer') {
return '<span class="material-icons mediaInfoItem mediaInfoIconItem mediaInfoTimerIcon fiber_smart_record"></span>';
@ -30,11 +39,11 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
}
function getProgramInfoHtml(item, options) {
var html = '';
let html = '';
var miscInfo = [];
var text;
var date;
const miscInfo = [];
let text;
let date;
if (item.StartDate && options.programTime !== false) {
@ -48,35 +57,35 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
text += datetime.toLocaleDateString(date, { weekday: 'short', month: 'short', day: 'numeric' });
}
text += ' ' + datetime.getDisplayTime(date);
text += ` ${datetime.getDisplayTime(date)}`;
if (item.EndDate) {
date = datetime.parseISO8601Date(item.EndDate);
text += ' - ' + datetime.getDisplayTime(date);
text += ` - ${datetime.getDisplayTime(date)}`;
}
miscInfo.push(text);
} catch (e) {
console.error('error parsing date: ' + item.StartDate);
console.error('error parsing date:', item.StartDate);
}
}
if (item.ChannelNumber) {
miscInfo.push('CH ' + item.ChannelNumber);
miscInfo.push(`CH ${item.ChannelNumber}`);
}
if (item.ChannelName) {
if (options.interactive && item.ChannelId) {
miscInfo.push({
html: '<a is="emby-linkbutton" class="button-flat mediaInfoItem" href="' + appRouter.getRouteUrl({
html: `<a is="emby-linkbutton" class="button-flat mediaInfoItem" href="${appRouter.getRouteUrl({
ServerId: item.ServerId,
Type: 'TvChannel',
Name: item.ChannelName,
Id: item.ChannelId
}) + '">' + item.ChannelName + '</a>'
})}">${item.ChannelName}</a>`
});
} else {
miscInfo.push(item.ChannelName);
@ -84,7 +93,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
}
if (options.timerIndicator !== false) {
var timerHtml = getTimerIndicator(item);
const timerHtml = getTimerIndicator(item);
if (timerHtml) {
miscInfo.push({
html: timerHtml
@ -92,24 +101,24 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
}
}
html += miscInfo.map(function (m) {
html += miscInfo.map(m => {
return getMediaInfoItem(m);
}).join('');
return html;
}
function getMediaInfoHtml(item, options) {
var html = '';
export function getMediaInfoHtml(item, options) {
let html = '';
var miscInfo = [];
const miscInfo = [];
options = options || {};
var text;
var date;
var minutes;
var count;
let text;
let date;
let minutes;
let count;
var showFolderRuntime = item.Type === 'MusicAlbum' || item.MediaType === 'MusicArtist' || item.MediaType === 'Playlist' || item.MediaType === 'MusicGenre';
const showFolderRuntime = item.Type === 'MusicAlbum' || item.MediaType === 'MusicArtist' || item.MediaType === 'Playlist' || item.MediaType === 'MusicGenre';
if (showFolderRuntime) {
@ -143,7 +152,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
text = datetime.toLocaleDateString(date);
miscInfo.push(text);
} catch (e) {
console.error('error parsing date: ' + item.PremiereDate);
console.error('error parsing date:', item.PremiereDate);
}
}
}
@ -176,7 +185,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
miscInfo.push(text);
}
} catch (e) {
console.error('error parsing date: ' + item.StartDate);
console.error('error parsing date:', item.StartDate);
}
}
@ -193,14 +202,14 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
try {
var endYear = datetime.parseISO8601Date(item.EndDate).getFullYear();
const endYear = datetime.parseISO8601Date(item.EndDate).getFullYear();
if (endYear !== item.ProductionYear) {
text += '-' + datetime.parseISO8601Date(item.EndDate).getFullYear();
text += `-${datetime.parseISO8601Date(item.EndDate).getFullYear()}`;
}
} catch (e) {
console.error('error parsing date: ' + item.EndDate);
console.error('error parsing date:', item.EndDate);
}
}
@ -213,19 +222,19 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
if (options.programIndicator !== false) {
if (item.IsLive) {
miscInfo.push({
html: '<div class="mediaInfoProgramAttribute mediaInfoItem liveTvProgram">' + globalize.translate('Live') + '</div>'
html: `<div class="mediaInfoProgramAttribute mediaInfoItem liveTvProgram">${globalize.translate('Live')}</div>`
});
} else if (item.IsPremiere) {
miscInfo.push({
html: '<div class="mediaInfoProgramAttribute mediaInfoItem premiereTvProgram">' + globalize.translate('Premiere') + '</div>'
html: `<div class="mediaInfoProgramAttribute mediaInfoItem premiereTvProgram">${globalize.translate('Premiere')}</div>`
});
} else if (item.IsSeries && !item.IsRepeat) {
miscInfo.push({
html: '<div class="mediaInfoProgramAttribute mediaInfoItem newTvProgram">' + globalize.translate('AttributeNew') + '</div>'
html: `<div class="mediaInfoProgramAttribute mediaInfoItem newTvProgram">${globalize.translate('AttributeNew')}</div>`
});
} else if (item.IsSeries && item.IsRepeat) {
miscInfo.push({
html: '<div class="mediaInfoProgramAttribute mediaInfoItem repeatTvProgram">' + globalize.translate('Repeat') + '</div>'
html: `<div class="mediaInfoProgramAttribute mediaInfoItem repeatTvProgram">${globalize.translate('Repeat')}</div>`
});
}
}
@ -248,7 +257,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
text = globalize.translate('OriginalAirDateValue', datetime.toLocaleDateString(date));
miscInfo.push(text);
} catch (e) {
console.error('error parsing date: ' + item.PremiereDate);
console.error('error parsing date:', item.PremiereDate);
}
} else if (item.ProductionYear) {
miscInfo.push(item.ProductionYear);
@ -267,13 +276,13 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
text = datetime.parseISO8601Date(item.PremiereDate).getFullYear();
miscInfo.push(text);
} catch (e) {
console.error('error parsing date: ' + item.PremiereDate);
console.error('error parsing date:', item.PremiereDate);
}
}
}
}
if (item.RunTimeTicks && item.Type !== 'Series' && item.Type !== 'Program' && !showFolderRuntime && options.runtime !== false) {
if (item.RunTimeTicks && item.Type !== 'Series' && item.Type !== 'Program' && item.Type !== 'Book' && !showFolderRuntime && options.runtime !== false) {
if (item.Type === 'Audio') {
@ -284,7 +293,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
minutes = minutes || 1;
miscInfo.push(Math.round(minutes) + ' mins');
miscInfo.push(`${Math.round(minutes)} mins`);
}
}
@ -300,14 +309,14 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
}
if (item.MediaType === 'Photo' && item.Width && item.Height) {
miscInfo.push(item.Width + 'x' + item.Height);
miscInfo.push(`${item.Width}x${item.Height}`);
}
if (options.container !== false && item.Type === 'Audio' && item.Container) {
miscInfo.push(item.Container);
}
html += miscInfo.map(function (m) {
html += miscInfo.map(m => {
return getMediaInfoItem(m);
}).join('');
@ -320,15 +329,15 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
if (item.CriticRating && options.criticRating !== false) {
if (item.CriticRating >= 60) {
html += '<div class="mediaInfoItem mediaInfoCriticRating mediaInfoCriticRatingFresh">' + item.CriticRating + '</div>';
html += `<div class="mediaInfoItem mediaInfoCriticRating mediaInfoCriticRatingFresh">${item.CriticRating}</div>`;
} else {
html += '<div class="mediaInfoItem mediaInfoCriticRating mediaInfoCriticRatingRotten">' + item.CriticRating + '</div>';
html += `<div class="mediaInfoItem mediaInfoCriticRating mediaInfoCriticRatingRotten">${item.CriticRating}</div>`;
}
}
if (options.endsAt !== false) {
var endsAt = getEndsAt(item);
const endsAt = getEndsAt(item);
if (endsAt) {
html += getMediaInfoItem(endsAt, 'endsAt');
}
@ -339,15 +348,15 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
return html;
}
function getEndsAt(item) {
export function getEndsAt(item) {
if (item.MediaType === 'Video' && item.RunTimeTicks) {
if (!item.StartDate) {
var endDate = new Date().getTime() + (item.RunTimeTicks / 10000);
let endDate = new Date().getTime() + (item.RunTimeTicks / 10000);
endDate = new Date(endDate);
var displayTime = datetime.getDisplayTime(endDate);
const displayTime = datetime.getDisplayTime(endDate);
return globalize.translate('EndsAtValue', displayTime);
}
}
@ -355,12 +364,12 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
return null;
}
function getEndsAtFromPosition(runtimeTicks, positionTicks, includeText) {
export function getEndsAtFromPosition(runtimeTicks, positionTicks, includeText) {
var endDate = new Date().getTime() + ((runtimeTicks - (positionTicks || 0)) / 10000);
let endDate = new Date().getTime() + ((runtimeTicks - (positionTicks || 0)) / 10000);
endDate = new Date(endDate);
var displayTime = datetime.getDisplayTime(endDate);
const displayTime = datetime.getDisplayTime(endDate);
if (includeText === false) {
return displayTime;
@ -370,8 +379,8 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
function getMediaInfoItem(m, cssClass) {
cssClass = cssClass ? (cssClass + ' mediaInfoItem') : 'mediaInfoItem';
var mediaInfoText = m;
cssClass = cssClass ? (`${cssClass} mediaInfoItem`) : 'mediaInfoItem';
let mediaInfoText = m;
if (typeof (m) !== 'string' && typeof (m) !== 'number') {
@ -379,13 +388,13 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
return m.html;
}
mediaInfoText = m.text;
cssClass += ' ' + m.cssClass;
cssClass += ` ${m.cssClass}`;
}
return '<div class="' + cssClass + '">' + mediaInfoText + '</div>';
return `<div class="${cssClass}">${mediaInfoText}</div>`;
}
function getStarIconsHtml(item) {
var html = '';
let html = '';
if (item.CommunityRating) {
html += '<div class="starRatingContainer mediaInfoItem">';
@ -400,7 +409,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
function dynamicEndTime(elem, item) {
var interval = setInterval(function () {
const interval = setInterval(() => {
if (!document.body.contains(elem)) {
@ -413,15 +422,15 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
}, 60000);
}
function fillPrimaryMediaInfo(elem, item, options) {
var html = getPrimaryMediaInfoHtml(item, options);
export function fillPrimaryMediaInfo(elem, item, options) {
const html = getPrimaryMediaInfoHtml(item, options);
elem.innerHTML = html;
afterFill(elem, item, options);
}
function fillSecondaryMediaInfo(elem, item, options) {
var html = getSecondaryMediaInfoHtml(item, options);
export function fillSecondaryMediaInfo(elem, item, options) {
const html = getSecondaryMediaInfoHtml(item, options);
elem.innerHTML = html;
afterFill(elem, item, options);
@ -430,13 +439,13 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
function afterFill(elem, item, options) {
if (options.endsAt !== false) {
var endsAtElem = elem.querySelector('.endsAt');
const endsAtElem = elem.querySelector('.endsAt');
if (endsAtElem) {
dynamicEndTime(endsAtElem, item);
}
}
var lnkChannel = elem.querySelector('.lnkChannel');
const lnkChannel = elem.querySelector('.lnkChannel');
if (lnkChannel) {
lnkChannel.addEventListener('click', onChannelLinkClick);
}
@ -444,8 +453,8 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
function onChannelLinkClick(e) {
var channelId = this.getAttribute('data-id');
var serverId = this.getAttribute('data-serverid');
const channelId = this.getAttribute('data-id');
const serverId = this.getAttribute('data-serverid');
appRouter.showItem(channelId, serverId);
@ -453,7 +462,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
return false;
}
function getPrimaryMediaInfoHtml(item, options) {
export function getPrimaryMediaInfoHtml(item, options) {
options = options || {};
if (options.interactive == null) {
@ -463,7 +472,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
return getMediaInfoHtml(item, options);
}
function getSecondaryMediaInfoHtml(item, options) {
export function getSecondaryMediaInfoHtml(item, options) {
options = options || {};
if (options.interactive == null) {
@ -476,10 +485,10 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
return '';
}
function getResolutionText(i) {
export function getResolutionText(i) {
var width = i.Width;
var height = i.Height;
const width = i.Width;
const height = i.Height;
if (width && height) {
@ -522,28 +531,28 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
return null;
}
var mediaSource = item.MediaSources[0];
const mediaSource = item.MediaSources[0];
if (!mediaSource) {
return null;
}
return (mediaSource.MediaStreams || []).filter(function (i) {
return (mediaSource.MediaStreams || []).filter(i => {
return i.Type === 'Audio' && (i.Index === mediaSource.DefaultAudioStreamIndex || mediaSource.DefaultAudioStreamIndex == null);
})[0];
}
function getMediaInfoStats(item, options) {
export function getMediaInfoStats(item, options) {
options = options || {};
var list = [];
const list = [];
var mediaSource = (item.MediaSources || [])[0] || {};
const mediaSource = (item.MediaSources || [])[0] || {};
var videoStream = (mediaSource.MediaStreams || []).filter(function (i) {
const videoStream = (mediaSource.MediaStreams || []).filter(i => {
return i.Type === 'Video';
})[0] || {};
var audioStream = getAudioStreamForDisplay(item) || {};
const audioStream = getAudioStreamForDisplay(item) || {};
if (item.VideoType === 'Dvd') {
list.push({
@ -563,7 +572,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
// html += '<div class="mediaInfoIcon mediaInfoText">' + mediaSource.Container + '</div>';
//}
var resolutionText = getResolutionText(videoStream);
const resolutionText = getResolutionText(videoStream);
if (resolutionText) {
list.push({
type: 'mediainfo',
@ -578,8 +587,8 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
});
}
var channels = audioStream.Channels;
var channelText;
const channels = audioStream.Channels;
let channelText;
if (channels === 8) {
@ -605,7 +614,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
});
}
var audioCodec = (audioStream.Codec || '').toLowerCase();
const audioCodec = (audioStream.Codec || '').toLowerCase();
if ((audioCodec === 'dca' || audioCodec === 'dts') && audioStream.Profile) {
list.push({
@ -621,20 +630,21 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
if (item.DateCreated && itemHelper.enableDateAddedDisplay(item)) {
var dateCreated = datetime.parseISO8601Date(item.DateCreated);
const dateCreated = datetime.parseISO8601Date(item.DateCreated);
list.push({
type: 'added',
text: globalize.translate('AddedOnValue', datetime.toLocaleDateString(dateCreated) + ' ' + datetime.getDisplayTime(dateCreated))
text: globalize.translate('AddedOnValue', `${datetime.toLocaleDateString(dateCreated)} ${datetime.getDisplayTime(dateCreated)}`)
});
}
return list;
}
return {
/* eslint-enable indent */
export default {
getMediaInfoHtml: getPrimaryMediaInfoHtml,
fill: fillPrimaryMediaInfo,
getEndsAt: getEndsAt,
getEndsAtFromPosition: getEndsAtFromPosition,
getPrimaryMediaInfoHtml: getPrimaryMediaInfoHtml,
@ -643,5 +653,4 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
fillSecondaryMediaInfo: fillSecondaryMediaInfo,
getMediaInfoStats: getMediaInfoStats,
getResolutionText: getResolutionText
};
});
};

View file

@ -1,9 +1,30 @@
define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loading', 'focusManager', 'connectionManager', 'globalize', 'require', 'shell', 'emby-checkbox', 'emby-input', 'emby-select', 'listViewStyle', 'emby-textarea', 'emby-button', 'paper-icon-button-light', 'css!./../formdialog', 'clearButtonStyle', 'flexStyles'], function (itemHelper, dom, layoutManager, dialogHelper, datetime, loading, focusManager, connectionManager, globalize, require, shell) {
'use strict';
import itemHelper from 'itemHelper';
import dom from 'dom';
import layoutManager from 'layoutManager';
import dialogHelper from 'dialogHelper';
import datetime from 'datetime';
import loading from 'loading';
import focusManager from 'focusManager';
import connectionManager from 'connectionManager';
import globalize from 'globalize';
import require from 'require';
import shell from 'shell';
import 'emby-checkbox';
import 'emby-input';
import 'emby-select';
import 'listViewStyle';
import 'emby-textarea';
import 'emby-button';
import 'paper-icon-button-light';
import 'css!./../formdialog';
import 'clearButtonStyle';
import 'flexStyles';
var currentContext;
var metadataEditorInfo;
var currentItem;
/* eslint-disable indent */
let currentContext;
let metadataEditorInfo;
let currentItem;
function isDialog() {
return currentContext.classList.contains('dialog');
@ -28,11 +49,11 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
closeDialog(true);
}
var apiClient = getApiClient();
const apiClient = getApiClient();
apiClient.updateItem(item).then(function () {
var newContentType = form.querySelector('#selectContentType').value || '';
const newContentType = form.querySelector('#selectContentType').value || '';
if ((metadataEditorInfo.ContentType || '') !== newContentType) {
@ -56,7 +77,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
}
function getSelectedAirDays(form) {
var checkedItems = form.querySelectorAll('.chkAirDay:checked') || [];
const checkedItems = form.querySelectorAll('.chkAirDay:checked') || [];
return Array.prototype.map.call(checkedItems, function (c) {
return c.getAttribute('data-day');
});
@ -92,7 +113,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
function getDateValue(form, element, property) {
var val = form.querySelector(element).value;
let val = form.querySelector(element).value;
if (!val) {
return null;
@ -100,14 +121,14 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
if (currentItem[property]) {
var date = datetime.parseISO8601Date(currentItem[property], true);
const date = datetime.parseISO8601Date(currentItem[property], true);
var parts = date.toISOString().split('T');
const parts = date.toISOString().split('T');
// If the date is the same, preserve the time
if (parts[0].indexOf(val) === 0) {
var iso = parts[1];
const iso = parts[1];
val += 'T' + iso;
}
@ -120,9 +141,9 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
loading.show();
var form = this;
const form = this;
var item = {
const item = {
Id: currentItem.Id,
Name: form.querySelector('#txtName').value,
OriginalTitle: form.querySelector('#txtOriginalName').value,
@ -168,9 +189,9 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
item.ProviderIds = Object.assign({}, currentItem.ProviderIds);
var idElements = form.querySelectorAll('.txtExternalId');
const idElements = form.querySelectorAll('.txtExternalId');
Array.prototype.map.call(idElements, function (idElem) {
var providerKey = idElem.getAttribute('data-providerkey');
const providerKey = idElem.getAttribute('data-providerkey');
item.ProviderIds[providerKey] = idElem.value;
});
@ -179,7 +200,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
if (currentItem.Type === 'Person') {
var placeOfBirth = form.querySelector('#txtPlaceOfBirth').value;
const placeOfBirth = form.querySelector('#txtPlaceOfBirth').value;
item.ProductionLocations = placeOfBirth ? [placeOfBirth] : [];
}
@ -187,11 +208,11 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
if (currentItem.Type === 'Series') {
// 600000000
var seriesRuntime = form.querySelector('#txtSeriesRuntime').value;
const seriesRuntime = form.querySelector('#txtSeriesRuntime').value;
item.RunTimeTicks = seriesRuntime ? (seriesRuntime * 600000000) : null;
}
var tagline = form.querySelector('#txtTagline').value;
const tagline = form.querySelector('#txtTagline').value;
item.Taglines = tagline ? [tagline] : [];
submitUpdatedItem(form, item);
@ -210,13 +231,12 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
}
function addElementToList(source, sortCallback) {
require(['prompt'], function (prompt) {
import('prompt').then(({default: prompt}) => {
prompt({
label: 'Value:'
}).then(function (text) {
var list = dom.parentWithClass(source, 'editableListviewContainer').querySelector('.paperList');
var items = getListValues(list);
const list = dom.parentWithClass(source, 'editableListviewContainer').querySelector('.paperList');
const items = getListValues(list);
items.push(text);
populateListView(list, items, sortCallback);
});
@ -224,7 +244,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
}
function removeElementFromList(source) {
var el = dom.parentWithClass(source, 'listItem');
const el = dom.parentWithClass(source, 'listItem');
el.parentNode.removeChild(el);
}
@ -234,7 +254,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
personEditor.show(person).then(function (updatedPerson) {
var isNew = index === -1;
const isNew = index === -1;
if (isNew) {
currentItem.People.push(updatedPerson);
@ -245,15 +265,52 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
});
}
function afterDeleted(context, item) {
var parentId = item.ParentId || item.SeasonId || item.SeriesId;
if (parentId) {
reload(context, parentId, item.ServerId);
} else {
require(['appRouter'], function (appRouter) {
appRouter.goHome();
});
}
}
function showMoreMenu(context, button, user) {
require(['itemContextMenu'], function (itemContextMenu) {
var item = currentItem;
itemContextMenu.show({
item: item,
positionTo: button,
edit: false,
editImages: true,
editSubtitles: true,
sync: false,
share: false,
play: false,
queue: false,
user: user
}).then(function (result) {
if (result.deleted) {
afterDeleted(context, item);
} else if (result.updated) {
reload(context, item.Id, item.ServerId);
}
});
});
}
function onEditorClick(e) {
var btnRemoveFromEditorList = dom.parentWithClass(e.target, 'btnRemoveFromEditorList');
const btnRemoveFromEditorList = dom.parentWithClass(e.target, 'btnRemoveFromEditorList');
if (btnRemoveFromEditorList) {
removeElementFromList(btnRemoveFromEditorList);
return;
}
var btnAddTextItem = dom.parentWithClass(e.target, 'btnAddTextItem');
const btnAddTextItem = dom.parentWithClass(e.target, 'btnAddTextItem');
if (btnAddTextItem) {
addElementToList(btnAddTextItem);
}
@ -264,19 +321,18 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
}
function bindAll(elems, eventName, fn) {
for (var i = 0, length = elems.length; i < length; i++) {
for (let i = 0, length = elems.length; i < length; i++) {
elems[i].addEventListener(eventName, fn);
}
}
function init(context, apiClient) {
context.querySelector('.externalIds').addEventListener('click', function (e) {
var btnOpenExternalId = dom.parentWithClass(e.target, 'btnOpenExternalId');
const btnOpenExternalId = dom.parentWithClass(e.target, 'btnOpenExternalId');
if (btnOpenExternalId) {
var field = context.querySelector('#' + btnOpenExternalId.getAttribute('data-fieldid'));
const field = context.querySelector('#' + btnOpenExternalId.getAttribute('data-fieldid'));
var formatString = field.getAttribute('data-formatstring');
const formatString = field.getAttribute('data-formatstring');
if (field.value) {
shell.openUrl(formatString.replace('{0}', field.value));
@ -294,13 +350,17 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
closeDialog(false);
});
context.querySelector('.btnHeaderSave').addEventListener('click', function (e) {
context.querySelector('.btnMore').addEventListener('click', function (e) {
getApiClient().getCurrentUser().then(function (user) {
showMoreMenu(context, e.target, user);
});
});
context.querySelector('.btnHeaderSave').addEventListener('click', function (e) {
context.querySelector('.btnSave').click();
});
context.querySelector('#chkLockData').addEventListener('click', function (e) {
if (!e.target.checked) {
showElement('.providerSettingsContainer');
} else {
@ -308,10 +368,10 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
}
});
context.removeEventListener('submit', onEditorClick);
context.addEventListener('submit', onEditorClick);
context.removeEventListener('click', onEditorClick);
context.addEventListener('click', onEditorClick);
var form = context.querySelector('form');
const form = context.querySelector('form');
form.removeEventListener('submit', onSubmit);
form.addEventListener('submit', onSubmit);
@ -322,15 +382,15 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
context.querySelector('#peopleList').addEventListener('click', function (e) {
var index;
var btnDeletePerson = dom.parentWithClass(e.target, 'btnDeletePerson');
let index;
const btnDeletePerson = dom.parentWithClass(e.target, 'btnDeletePerson');
if (btnDeletePerson) {
index = parseInt(btnDeletePerson.getAttribute('data-index'));
currentItem.People.splice(index, 1);
populatePeople(context, currentItem.People);
}
var btnEditPerson = dom.parentWithClass(e.target, 'btnEditPerson');
const btnEditPerson = dom.parentWithClass(e.target, 'btnEditPerson');
if (btnEditPerson) {
index = parseInt(btnEditPerson.getAttribute('data-index'));
editPerson(context, currentItem.People[index], index);
@ -340,7 +400,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
function getItem(itemId, serverId) {
var apiClient = connectionManager.getApiClient(serverId);
const apiClient = connectionManager.getApiClient(serverId);
if (itemId) {
return apiClient.getItem(apiClient.getCurrentUserId(), itemId);
@ -351,7 +411,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
function getEditorConfig(itemId, serverId) {
var apiClient = connectionManager.getApiClient(serverId);
const apiClient = connectionManager.getApiClient(serverId);
if (itemId) {
return apiClient.getJSON(apiClient.getUrl('Items/' + itemId + '/MetadataEditor'));
@ -362,13 +422,13 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
function populateCountries(select, allCountries) {
var html = '';
let html = '';
html += "<option value=''></option>";
for (var i = 0, length = allCountries.length; i < length; i++) {
for (let i = 0, length = allCountries.length; i < length; i++) {
var culture = allCountries[i];
const culture = allCountries[i];
html += "<option value='" + culture.TwoLetterISORegionName + "'>" + culture.DisplayName + '</option>';
}
@ -378,13 +438,13 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
function populateLanguages(select, languages) {
var html = '';
let html = '';
html += "<option value=''></option>";
for (var i = 0, length = languages.length; i < length; i++) {
for (let i = 0, length = languages.length; i < length; i++) {
var culture = languages[i];
const culture = languages[i];
html += "<option value='" + culture.TwoLetterISOLanguageName + "'>" + culture.DisplayName + '</option>';
}
@ -400,41 +460,41 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
showElement('#fldContentType', context);
}
var html = metadataInfo.ContentTypeOptions.map(function (i) {
const html = metadataInfo.ContentTypeOptions.map(function (i) {
return '<option value="' + i.Value + '">' + i.Name + '</option>';
}).join('');
var selectEl = context.querySelector('#selectContentType');
const selectEl = context.querySelector('#selectContentType');
selectEl.innerHTML = html;
selectEl.value = metadataInfo.ContentType || '';
}
function loadExternalIds(context, item, externalIds) {
var html = '';
let html = '';
var providerIds = item.ProviderIds || {};
const providerIds = item.ProviderIds || {};
for (var i = 0, length = externalIds.length; i < length; i++) {
for (let i = 0, length = externalIds.length; i < length; i++) {
var idInfo = externalIds[i];
const idInfo = externalIds[i];
var id = 'txt1' + idInfo.Key;
var formatString = idInfo.UrlFormatString || '';
const id = 'txt1' + idInfo.Key;
const formatString = idInfo.UrlFormatString || '';
var fullName = idInfo.Name;
let fullName = idInfo.Name;
if (idInfo.Type) {
fullName = idInfo.Name + ' ' + globalize.translate(idInfo.Type);
}
var labelText = globalize.translate('LabelDynamicExternalId', fullName);
const labelText = globalize.translate('LabelDynamicExternalId', fullName);
html += '<div class="inputContainer">';
html += '<div class="flex align-items-center">';
var value = providerIds[idInfo.Key] || '';
const value = providerIds[idInfo.Key] || '';
html += '<div class="flex-grow">';
html += '<input is="emby-input" class="txtExternalId" value="' + value + '" data-providerkey="' + idInfo.Key + '" data-formatstring="' + formatString + '" id="' + id + '" label="' + labelText + '"/>';
@ -448,7 +508,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
html += '</div>';
}
var elem = context.querySelector('.externalIds', context);
const elem = context.querySelector('.externalIds', context);
elem.innerHTML = html;
if (externalIds.length) {
@ -465,7 +525,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
context = context || document;
if (typeof selector === 'string') {
var elements = multiple ? context.querySelectorAll(selector) : [context.querySelector(selector)];
const elements = multiple ? context.querySelectorAll(selector) : [context.querySelector(selector)];
Array.prototype.forEach.call(elements, function (el) {
if (el) {
@ -484,7 +544,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
context = context || document;
if (typeof selector === 'string') {
var elements = multiple ? context.querySelectorAll(selector) : [context.querySelector(selector)];
const elements = multiple ? context.querySelectorAll(selector) : [context.querySelector(selector)];
Array.prototype.forEach.call(elements, function (el) {
if (el) {
@ -686,7 +746,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
function fillItemInfo(context, item, parentalRatingOptions) {
var select = context.querySelector('#selectOfficialRating');
let select = context.querySelector('#selectOfficialRating');
populateRatings(parentalRatingOptions, select, item.OfficialRating);
@ -698,7 +758,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
select.value = item.CustomRating || '';
var selectStatus = context.querySelector('#selectStatus');
const selectStatus = context.querySelector('#selectStatus');
populateStatus(selectStatus);
selectStatus.value = item.Status || '';
@ -717,8 +777,8 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
populateListView(context.querySelector('#listTags'), item.Tags);
var lockData = (item.LockData || false);
var chkLockData = context.querySelector('#chkLockData');
const lockData = (item.LockData || false);
const chkLockData = context.querySelector('#chkLockData');
chkLockData.checked = lockData;
if (chkLockData.checked) {
hideElement('.providerSettingsContainer', context);
@ -756,7 +816,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
return a.Name;
}).join(';');
var date;
let date;
if (item.DateCreated) {
try {
@ -798,7 +858,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
context.querySelector('#txtAirTime').value = item.AirTime || '';
var placeofBirth = item.ProductionLocations && item.ProductionLocations.length ? item.ProductionLocations[0] : '';
const placeofBirth = item.ProductionLocations && item.ProductionLocations.length ? item.ProductionLocations[0] : '';
context.querySelector('#txtPlaceOfBirth').value = placeofBirth;
context.querySelector('#txtOriginalAspectRatio').value = item.AspectRatio || '';
@ -808,7 +868,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
if (item.RunTimeTicks) {
var minutes = item.RunTimeTicks / 600000000;
const minutes = item.RunTimeTicks / 600000000;
context.querySelector('#txtSeriesRuntime').value = Math.round(minutes);
} else {
@ -818,18 +878,16 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
function populateRatings(allParentalRatings, select, currentValue) {
var html = '';
let html = '';
html += "<option value=''></option>";
var ratings = [];
var i;
var length;
var rating;
const ratings = [];
let rating;
var currentValueFound = false;
let currentValueFound = false;
for (i = 0, length = allParentalRatings.length; i < length; i++) {
for (let i = 0, length = allParentalRatings.length; i < length; i++) {
rating = allParentalRatings[i];
@ -844,7 +902,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
ratings.push({ Name: currentValue, Value: currentValue });
}
for (i = 0, length = ratings.length; i < length; i++) {
for (let i = 0, length = ratings.length; i < length; i++) {
rating = ratings[i];
@ -855,7 +913,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
}
function populateStatus(select) {
var html = '';
let html = '';
html += "<option value=''></option>";
html += "<option value='Continuing'>" + globalize.translate('Continuing') + '</option>';
@ -873,8 +931,8 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
} else {
items = sortCallback(items);
}
var html = '';
for (var i = 0; i < items.length; i++) {
let html = '';
for (let i = 0; i < items.length; i++) {
html += '<div class="listItem">';
html += '<span class="material-icons listItemIcon live_tv" style="background-color:#333;"></span>';
@ -897,14 +955,14 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
function populatePeople(context, people) {
var lastType = '';
var html = '';
let lastType = '';
let html = '';
var elem = context.querySelector('#peopleList');
const elem = context.querySelector('#peopleList');
for (var i = 0, length = people.length; i < length; i++) {
for (let i = 0, length = people.length; i < length; i++) {
var person = people[i];
const person = people[i];
html += '<div class="listItem">';
@ -934,13 +992,13 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
function getLockedFieldsHtml(fields, currentFields) {
var html = '';
for (var i = 0; i < fields.length; i++) {
let html = '';
for (let i = 0; i < fields.length; i++) {
var field = fields[i];
var name = field.name;
var value = field.value || field.name;
var checkedHtml = currentFields.indexOf(value) === -1 ? ' checked' : '';
const field = fields[i];
const name = field.name;
const value = field.value || field.name;
const checkedHtml = currentFields.indexOf(value) === -1 ? ' checked' : '';
html += '<label>';
html += '<input type="checkbox" is="emby-checkbox" class="selectLockedField" data-value="' + value + '"' + checkedHtml + '/>';
html += '<span>' + name + '</span>';
@ -950,10 +1008,10 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
}
function fillMetadataSettings(context, item, lockedFields) {
var container = context.querySelector('.providerSettingsContainer');
const container = context.querySelector('.providerSettingsContainer');
lockedFields = lockedFields || [];
var lockedFieldsList = [
const lockedFieldsList = [
{ name: globalize.translate('Name'), value: 'Name' },
{ name: globalize.translate('Overview'), value: 'Overview' },
{ name: globalize.translate('Genres'), value: 'Genres' },
@ -974,7 +1032,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
lockedFieldsList.push({ name: globalize.translate('Studios'), value: 'Studios' });
lockedFieldsList.push({ name: globalize.translate('Tags'), value: 'Tags' });
var html = '';
let html = '';
html += '<h2>' + globalize.translate('HeaderEnabledFields') + '</h2>';
html += '<p>' + globalize.translate('HeaderEnabledFieldsHelp') + '</p>';
@ -988,13 +1046,13 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
Promise.all([getItem(itemId, serverId), getEditorConfig(itemId, serverId)]).then(function (responses) {
var item = responses[0];
const item = responses[0];
metadataEditorInfo = responses[1];
currentItem = item;
var languages = metadataEditorInfo.Cultures;
var countries = metadataEditorInfo.Countries;
const languages = metadataEditorInfo.Cultures;
const countries = metadataEditorInfo.Countries;
renderContentTypeOptions(context, metadataEditorInfo);
@ -1017,8 +1075,8 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
}
function centerFocus(elem, horiz, on) {
require(['scrollHelper'], function (scrollHelper) {
var fn = on ? 'on' : 'off';
import('scrollHelper').then(({default: scrollHelper}) => {
const fn = on ? 'on' : 'off';
scrollHelper.centerFocus[fn](elem, horiz);
});
}
@ -1026,9 +1084,8 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
function show(itemId, serverId, resolve, reject) {
loading.show();
require(['text!./metadataEditor.template.html'], function (template) {
var dialogOptions = {
import('text!./metadataEditor.template.html').then(({default: template}) => {
const dialogOptions = {
removeOnClose: true,
scrollY: false
};
@ -1039,13 +1096,13 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
dialogOptions.size = 'small';
}
var dlg = dialogHelper.createDialog(dialogOptions);
const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog');
var html = '';
let html = '';
html += globalize.translateDocument(template, 'core');
html += globalize.translateHtml(template, 'core');
dlg.innerHTML = html;
@ -1071,7 +1128,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
});
}
return {
export default {
show: function (itemId, serverId) {
return new Promise(function (resolve, reject) {
return show(itemId, serverId, resolve, reject);
@ -1083,11 +1140,11 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
loading.show();
require(['text!./metadataEditor.template.html'], function (template) {
elem.innerHTML = globalize.translateDocument(template, 'core');
import('text!./metadataEditor.template.html').then(({default: template}) => {
elem.innerHTML = globalize.translateHtml(template, 'core');
elem.querySelector('.formDialogFooter').classList.remove('formDialogFooter');
elem.querySelector('.btnClose').classList.add('hide');
elem.querySelector('.btnHeaderSave').classList.remove('hide');
elem.querySelector('.btnCancel').classList.add('hide');
@ -1101,4 +1158,5 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
});
}
};
});
/* eslint-enable indent */

View file

@ -8,6 +8,9 @@
<span class="material-icons check"></span>
<span>${Save}</span>
</button>
<button is="paper-icon-button-light" class="btnMore autoSize" tabindex="-1">
<span class="material-icons more_vert"></span>
</button>
<button is="paper-icon-button-light" class="btnCancel btnClose autoSize" tabindex="-1">
<span class="material-icons close"></span>
</button>

View file

@ -1,9 +1,17 @@
define(['dialogHelper', 'layoutManager', 'globalize', 'require', 'paper-icon-button-light', 'emby-input', 'emby-select', 'css!./../formdialog'], function (dialogHelper, layoutManager, globalize, require) {
'use strict';
import dialogHelper from 'dialogHelper';
import layoutManager from 'layoutManager';
import globalize from 'globalize';
import require from 'require';
import 'paper-icon-button-light';
import 'emby-input';
import 'emby-select';
import 'css!./../formdialog';
/* eslint-disable indent */
function centerFocus(elem, horiz, on) {
require(['scrollHelper'], function (scrollHelper) {
var fn = on ? 'on' : 'off';
import('scrollHelper').then(({default: scrollHelper}) => {
const fn = on ? 'on' : 'off';
scrollHelper.centerFocus[fn](elem, horiz);
});
}
@ -11,9 +19,9 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'require', 'paper-icon-but
function show(person) {
return new Promise(function (resolve, reject) {
require(['text!./personEditor.template.html'], function (template) {
import('text!./personEditor.template.html').then(({default: template}) => {
var dialogOptions = {
const dialogOptions = {
removeOnClose: true,
scrollY: false
};
@ -24,14 +32,14 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'require', 'paper-icon-but
dialogOptions.size = 'small';
}
var dlg = dialogHelper.createDialog(dialogOptions);
const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog');
var html = '';
var submitted = false;
let html = '';
let submitted = false;
html += globalize.translateDocument(template, 'core');
html += globalize.translateHtml(template, 'core');
dlg.innerHTML = html;
@ -93,7 +101,8 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'require', 'paper-icon-but
});
}
return {
export default {
show: show
};
});
};
/* eslint-enable indent */

View file

@ -7,7 +7,6 @@
<div class="formDialogContent smoothScrollY" style="padding-top:2em;">
<form class="popupEditPersonForm dialogContentInner dialog-content-centered">
<div class="inputContainer">
<input type="text" is="emby-input" class="txtPersonName" required="required" label="${LabelName}" />
</div>
@ -23,6 +22,7 @@
<option value="Writer">${Writer}</option>
</select>
</div>
<div class="inputContainer fldRole hide">
<input is="emby-input" type="text" class="txtPersonRole" label="${LabelPersonRole}" />
<div class="fieldDescription">${LabelPersonRoleHelp}</div>
@ -33,6 +33,5 @@
<span>${Save}</span>
</button>
</div>
</form>
</div>

View file

@ -1,13 +1,20 @@
define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'globalize', 'appRouter', 'dom', 'css!./multiSelect'], function (browser, appStorage, appHost, loading, connectionManager, globalize, appRouter, dom) {
'use strict';
import browser from 'browser';
import appHost from 'apphost';
import loading from 'loading';
import connectionManager from 'connectionManager';
import globalize from 'globalize';
import dom from 'dom';
import 'css!./multiSelect';
var selectedItems = [];
var selectedElements = [];
var currentSelectionCommandsPanel;
/* eslint-disable indent */
let selectedItems = [];
let selectedElements = [];
let currentSelectionCommandsPanel;
function hideSelections() {
var selectionCommandsPanel = currentSelectionCommandsPanel;
const selectionCommandsPanel = currentSelectionCommandsPanel;
if (selectionCommandsPanel) {
selectionCommandsPanel.parentNode.removeChild(selectionCommandsPanel);
@ -15,10 +22,10 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
selectedItems = [];
selectedElements = [];
var elems = document.querySelectorAll('.itemSelectionPanel');
for (var i = 0, length = elems.length; i < length; i++) {
const elems = document.querySelectorAll('.itemSelectionPanel');
for (let i = 0, length = elems.length; i < length; i++) {
var parent = elems[i].parentNode;
const parent = elems[i].parentNode;
parent.removeChild(elems[i]);
parent.classList.remove('withMultiSelect');
}
@ -29,14 +36,14 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
// toggle the checkbox, if it wasn't clicked on
if (!dom.parentWithClass(e.target, 'chkItemSelect')) {
var chkItemSelect = itemSelectionPanel.querySelector('.chkItemSelect');
const chkItemSelect = itemSelectionPanel.querySelector('.chkItemSelect');
if (chkItemSelect) {
if (chkItemSelect.classList.contains('checkedInitial')) {
chkItemSelect.classList.remove('checkedInitial');
} else {
var newValue = !chkItemSelect.checked;
const newValue = !chkItemSelect.checked;
chkItemSelect.checked = newValue;
updateItemSelection(chkItemSelect, newValue);
}
@ -50,11 +57,11 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
function updateItemSelection(chkItemSelect, selected) {
var id = dom.parentWithAttribute(chkItemSelect, 'data-id').getAttribute('data-id');
const id = dom.parentWithAttribute(chkItemSelect, 'data-id').getAttribute('data-id');
if (selected) {
var current = selectedItems.filter(function (i) {
const current = selectedItems.filter(i => {
return i === id;
});
@ -64,16 +71,16 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
}
} else {
selectedItems = selectedItems.filter(function (i) {
selectedItems = selectedItems.filter(i => {
return i !== id;
});
selectedElements = selectedElements.filter(function (i) {
selectedElements = selectedElements.filter(i => {
return i !== chkItemSelect;
});
}
if (selectedItems.length) {
var itemSelectionCount = document.querySelector('.itemSelectionCount');
const itemSelectionCount = document.querySelector('.itemSelectionCount');
if (itemSelectionCount) {
itemSelectionCount.innerHTML = selectedItems.length;
}
@ -88,33 +95,33 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
function showSelection(item, isChecked) {
var itemSelectionPanel = item.querySelector('.itemSelectionPanel');
let itemSelectionPanel = item.querySelector('.itemSelectionPanel');
if (!itemSelectionPanel) {
itemSelectionPanel = document.createElement('div');
itemSelectionPanel.classList.add('itemSelectionPanel');
var parent = item.querySelector('.cardBox') || item.querySelector('.cardContent');
const parent = item.querySelector('.cardBox') || item.querySelector('.cardContent');
parent.classList.add('withMultiSelect');
parent.appendChild(itemSelectionPanel);
var cssClass = 'chkItemSelect';
let cssClass = 'chkItemSelect';
if (isChecked && !browser.firefox) {
// In firefox, the initial tap hold doesnt' get treated as a click
// In other browsers it does, so we need to make sure that initial click is ignored
cssClass += ' checkedInitial';
}
var checkedAttribute = isChecked ? ' checked' : '';
itemSelectionPanel.innerHTML = '<label class="checkboxContainer"><input type="checkbox" is="emby-checkbox" data-outlineclass="multiSelectCheckboxOutline" class="' + cssClass + '"' + checkedAttribute + '/><span></span></label>';
var chkItemSelect = itemSelectionPanel.querySelector('.chkItemSelect');
const checkedAttribute = isChecked ? ' checked' : '';
itemSelectionPanel.innerHTML = `<label class="checkboxContainer"><input type="checkbox" is="emby-checkbox" data-outlineclass="multiSelectCheckboxOutline" class="${cssClass}"${checkedAttribute}/><span></span></label>`;
const chkItemSelect = itemSelectionPanel.querySelector('.chkItemSelect');
chkItemSelect.addEventListener('change', onSelectionChange);
}
}
function showSelectionCommands() {
var selectionCommandsPanel = currentSelectionCommandsPanel;
let selectionCommandsPanel = currentSelectionCommandsPanel;
if (!selectionCommandsPanel) {
@ -124,19 +131,19 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
document.body.appendChild(selectionCommandsPanel);
currentSelectionCommandsPanel = selectionCommandsPanel;
var html = '';
let html = '';
html += '<button is="paper-icon-button-light" class="btnCloseSelectionPanel autoSize"><span class="material-icons close"></span></button>';
html += '<h1 class="itemSelectionCount"></h1>';
const moreIcon = 'more_vert';
html += '<button is="paper-icon-button-light" class="btnSelectionPanelOptions autoSize" style="margin-left:auto;"><span class="material-icons ' + moreIcon + '"></span></button>';
html += `<button is="paper-icon-button-light" class="btnSelectionPanelOptions autoSize" style="margin-left:auto;"><span class="material-icons ${moreIcon}"></span></button>`;
selectionCommandsPanel.innerHTML = html;
selectionCommandsPanel.querySelector('.btnCloseSelectionPanel').addEventListener('click', hideSelections);
var btnSelectionPanelOptions = selectionCommandsPanel.querySelector('.btnSelectionPanelOptions');
const btnSelectionPanelOptions = selectionCommandsPanel.querySelector('.btnSelectionPanelOptions');
dom.addEventListener(btnSelectionPanelOptions, 'click', showMenuForSelectedItems, { passive: true });
}
@ -144,9 +151,9 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
function alertText(options) {
return new Promise(function (resolve, reject) {
return new Promise((resolve, reject) => {
require(['alert'], function (alert) {
import('alert').then(({default: alert}) => {
alert(options).then(resolve, resolve);
});
});
@ -154,24 +161,24 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
function deleteItems(apiClient, itemIds) {
return new Promise(function (resolve, reject) {
return new Promise((resolve, reject) => {
var msg = globalize.translate('ConfirmDeleteItem');
var title = globalize.translate('HeaderDeleteItem');
let msg = globalize.translate('ConfirmDeleteItem');
let title = globalize.translate('HeaderDeleteItem');
if (itemIds.length > 1) {
msg = globalize.translate('ConfirmDeleteItems');
title = globalize.translate('HeaderDeleteItems');
}
require(['confirm'], function (confirm) {
import('confirm').then(({default: confirm}) => {
confirm(msg, title).then(function () {
var promises = itemIds.map(function (itemId) {
confirm(msg, title).then(() => {
const promises = itemIds.map(itemId => {
apiClient.deleteItem(itemId);
});
Promise.all(promises).then(resolve, function () {
Promise.all(promises).then(resolve, () => {
alertText(globalize.translate('ErrorDeletingItem')).then(reject, reject);
});
@ -183,11 +190,11 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
function showMenuForSelectedItems(e) {
var apiClient = connectionManager.currentApiClient();
const apiClient = connectionManager.currentApiClient();
apiClient.getCurrentUser().then(function (user) {
apiClient.getCurrentUser().then(user => {
var menuItems = [];
const menuItems = [];
menuItems.push({
name: globalize.translate('AddToCollection'),
@ -244,18 +251,18 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
icon: 'refresh'
});
require(['actionsheet'], function (actionsheet) {
import('actionsheet').then(({default: actionsheet}) => {
actionsheet.show({
items: menuItems,
positionTo: e.target,
callback: function (id) {
var items = selectedItems.slice(0);
var serverId = apiClient.serverInfo().Id;
const items = selectedItems.slice(0);
const serverId = apiClient.serverInfo().Id;
switch (id) {
case 'addtocollection':
require(['collectionEditor'], function (collectionEditor) {
new collectionEditor().show({
import('collectionEditor').then(({default: collectionEditor}) => {
new collectionEditor({
items: items,
serverId: serverId
});
@ -264,8 +271,8 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
dispatchNeedsRefresh();
break;
case 'playlist':
require(['playlistEditor'], function (playlistEditor) {
new playlistEditor().show({
import('playlistEditor').then(({default: playlistEditor}) => {
new playlistEditor({
items: items,
serverId: serverId
});
@ -282,21 +289,21 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
combineVersions(apiClient, items);
break;
case 'markplayed':
items.forEach(function (itemId) {
items.forEach(itemId => {
apiClient.markPlayed(apiClient.getCurrentUserId(), itemId);
});
hideSelections();
dispatchNeedsRefresh();
break;
case 'markunplayed':
items.forEach(function (itemId) {
items.forEach(itemId => {
apiClient.markUnplayed(apiClient.getCurrentUserId(), itemId);
});
hideSelections();
dispatchNeedsRefresh();
break;
case 'refresh':
require(['refreshDialog'], function (refreshDialog) {
import('refreshDialog').then(({default: refreshDialog}) => {
new refreshDialog({
itemIds: items,
serverId: serverId
@ -317,18 +324,18 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
function dispatchNeedsRefresh() {
var elems = [];
const elems = [];
[].forEach.call(selectedElements, function (i) {
[].forEach.call(selectedElements, i => {
var container = dom.parentWithAttribute(i, 'is', 'emby-itemscontainer');
const container = dom.parentWithAttribute(i, 'is', 'emby-itemscontainer');
if (container && elems.indexOf(container) === -1) {
if (container && !elems.includes(container)) {
elems.push(container);
}
});
for (var i = 0, length = elems.length; i < length; i++) {
for (let i = 0, length = elems.length; i < length; i++) {
elems[i].notifyRefreshNeeded(true);
}
}
@ -337,8 +344,9 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
if (selection.length < 2) {
require(['alert'], function (alert) {
import('alert').then(({default: alert}) => {
alert({
text: globalize.translate('PleaseSelectTwoItems')
});
});
@ -352,7 +360,7 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
type: 'POST',
url: apiClient.getUrl('Videos/MergeVersions', { Ids: selection.join(',') })
}).then(function () {
}).then(() => {
loading.hide();
hideSelections();
@ -362,9 +370,9 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
function showSelections(initialCard) {
require(['emby-checkbox'], function () {
var cards = document.querySelectorAll('.card');
for (var i = 0, length = cards.length; i < length; i++) {
import('emby-checkbox').then(() => {
const cards = document.querySelectorAll('.card');
for (let i = 0, length = cards.length; i < length; i++) {
showSelection(cards[i], initialCard === cards[i]);
}
@ -375,13 +383,13 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
function onContainerClick(e) {
var target = e.target;
const target = e.target;
if (selectedItems.length) {
var card = dom.parentWithClass(target, 'card');
const card = dom.parentWithClass(target, 'card');
if (card) {
var itemSelectionPanel = card.querySelector('.itemSelectionPanel');
const itemSelectionPanel = card.querySelector('.itemSelectionPanel');
if (itemSelectionPanel) {
return onItemSelectionPanelClick(e, itemSelectionPanel);
}
@ -395,15 +403,15 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
document.addEventListener('viewbeforehide', hideSelections);
return function (options) {
export default function (options) {
var self = this;
const self = this;
var container = options.container;
const container = options.container;
function onTapHold(e) {
var card = dom.parentWithClass(e.target, 'card');
const card = dom.parentWithClass(e.target, 'card');
if (card) {
@ -423,13 +431,13 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
return e.changedTouches || e.targetTouches || e.touches;
}
var touchTarget;
var touchStartTimeout;
var touchStartX;
var touchStartY;
let touchTarget;
let touchStartTimeout;
let touchStartX;
let touchStartY;
function onTouchStart(e) {
var touch = getTouches(e)[0];
const touch = getTouches(e)[0];
touchTarget = null;
touchStartX = 0;
touchStartY = 0;
@ -437,10 +445,10 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
if (touch) {
touchStartX = touch.clientX;
touchStartY = touch.clientY;
var element = touch.target;
const element = touch.target;
if (element) {
var card = dom.parentWithClass(element, 'card');
const card = dom.parentWithClass(element, 'card');
if (card) {
@ -459,13 +467,13 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
function onTouchMove(e) {
if (touchTarget) {
var touch = getTouches(e)[0];
var deltaX;
var deltaY;
const touch = getTouches(e)[0];
let deltaX;
let deltaY;
if (touch) {
var touchEndX = touch.clientX || 0;
var touchEndY = touch.clientY || 0;
const touchEndX = touch.clientX || 0;
const touchEndY = touch.clientY || 0;
deltaX = Math.abs(touchEndX - (touchStartX || 0));
deltaY = Math.abs(touchEndY - (touchStartY || 0));
} else {
@ -509,7 +517,7 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
return;
}
var card = dom.parentWithClass(touchTarget, 'card');
const card = dom.parentWithClass(touchTarget, 'card');
touchTarget = null;
if (card) {
@ -556,12 +564,12 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
self.onContainerClick = onContainerClick;
self.destroy = function () {
self.destroy = () => {
container.removeEventListener('click', onContainerClick);
container.removeEventListener('contextmenu', onTapHold);
var element = container;
const element = container;
dom.removeEventListener(element, 'touchstart', onTouchStart, {
passive: true
@ -586,5 +594,6 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
passive: true
});
};
};
});
}
/* eslint-enable indent */

View file

@ -46,7 +46,7 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir
function showNonPersistentNotification(title, options, timeoutMs) {
try {
var notif = new Notification(title, options);
var notif = new Notification(title, options); /* eslint-disable-line compat/compat */
if (notif.show) {
notif.show();

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