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

Merge branch 'es6' into es6-migration-optionseditor

This commit is contained in:
dkanada 2020-07-24 10:08:27 +09:00 committed by GitHub
commit 1caaeea89a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
283 changed files with 11119 additions and 6942 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,106 @@
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: 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,88 +12,6 @@ pr:
- '*'
jobs:
- job: Build
displayName: 'Build'
strategy:
matrix:
Development:
BuildConfiguration: development
Production:
BuildConfiguration: production
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: '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

@ -132,6 +132,7 @@ module.exports = {
'Object.getOwnPropertyDescriptor',
'Object.getPrototypeOf',
'Object.keys',
'Object.entries',
'Object.getOwnPropertyNames',
'Function.name',
'Function.hasInstance',
@ -192,4 +193,4 @@ module.exports = {
}
}
]
}
};

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

@ -16,6 +16,7 @@ const stream = require('webpack-stream');
const inject = require('gulp-inject');
const postcss = require('gulp-postcss');
const sass = require('gulp-sass');
const gulpif = require('gulp-if');
const lazypipe = require('lazypipe');
sass.compiler = require('node-sass');
@ -67,7 +68,7 @@ function serve() {
}
});
watch(options.apploader.query, apploader());
watch(options.apploader.query, apploader(true));
watch('src/bundle.js', webpack);
@ -130,12 +131,18 @@ function javascript(query) {
.pipe(browserSync.stream());
}
function apploader() {
function apploader(standalone) {
function task() {
return src(options.apploader.query, { base: './src/' })
.pipe(concat('scripts/apploader.js'))
.pipe(gulpif(standalone, concat('scripts/apploader.js')))
.pipe(pipelineJavascript())
.pipe(dest('dist/'))
.pipe(browserSync.stream());
}
task.displayName = 'apploader';
return task;
}
function webpack() {
@ -183,5 +190,10 @@ function injectBundle() {
.pipe(browserSync.stream());
}
exports.default = series(clean, parallel(javascript, apploader, webpack, css, html, images, copy), injectBundle);
exports.serve = series(exports.default, serve);
function build(standalone) {
return series(clean, parallel(javascript, apploader(standalone), webpack, css, html, images, copy));
}
exports.default = series(build(false), injectBundle);
exports.standalone = series(build(true), injectBundle);
exports.serve = series(exports.standalone, serve);

View file

@ -5,29 +5,29 @@
"repository": "https://github.com/jellyfin/jellyfin-web",
"license": "GPL-2.0-or-later",
"devDependencies": {
"@babel/core": "^7.10.2",
"@babel/core": "^7.10.3",
"@babel/plugin-proposal-class-properties": "^7.10.1",
"@babel/plugin-proposal-private-methods": "^7.10.1",
"@babel/plugin-transform-modules-amd": "^7.9.6",
"@babel/polyfill": "^7.8.7",
"@babel/preset-env": "^7.10.2",
"autoprefixer": "^9.8.0",
"@babel/preset-env": "^7.10.3",
"autoprefixer": "^9.8.2",
"babel-eslint": "^11.0.0-beta.2",
"babel-loader": "^8.0.6",
"browser-sync": "^2.26.7",
"copy-webpack-plugin": "^5.1.1",
"css-loader": "^3.4.2",
"css-loader": "^3.6.0",
"cssnano": "^4.1.10",
"del": "^5.1.0",
"eslint": "^6.8.0",
"eslint-plugin-compat": "^3.5.1",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-import": "^2.20.2",
"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",
@ -44,10 +44,10 @@
"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",
"stylelint-order": "^4.1.0",
"webpack": "^4.41.5",
"webpack-merge": "^4.2.2",
"webpack-stream": "^5.2.1"
@ -60,26 +60,26 @@
"date-fns": "^2.14.0",
"document-register-element": "^1.14.3",
"epubjs": "^0.3.85",
"fast-text-encoding": "^1.0.1",
"fast-text-encoding": "^1.0.3",
"flv.js": "^1.5.0",
"headroom.js": "^0.11.0",
"hls.js": "^0.13.1",
"howler": "^2.2.0",
"intersection-observer": "^0.10.0",
"jellyfin-apiclient": "^1.2.0",
"jellyfin-apiclient": "^1.2.2",
"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.12",
"shaka-player": "^3.0.1",
"sortablejs": "^1.10.2",
"swiper": "^5.4.1",
"swiper": "^5.4.5",
"webcomponents.js": "^0.7.24",
"whatwg-fetch": "^3.0.0"
},
@ -90,14 +90,45 @@
"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/components/imageOptionsEditor/imageOptionsEditor.js",
"src/components/cardbuilder/chaptercardbuilder.js",
"src/components/cardbuilder/peoplecardbuilder.js",
"src/components/channelMapper/channelMapper.js",
"src/components/confirm/confirm.js",
"src/components/displaySettings/displaySettings.js",
"src/components/homeScreenSettings/homeScreenSettings.js",
"src/components/directorybrowser/directorybrowser.js",
"src/components/collectionEditor/collectionEditor.js",
"src/components/dialog/dialog.js",
"src/components/directorybrowser/directorybrowser.js",
"src/components/dialogHelper/dialogHelper.js",
"src/components/homesections/homesections.js",
"src/components/images/imageLoader.js",
"src/components/imageUploader/imageUploader.js",
"src/components/indicators/indicators.js",
"src/components/libraryoptionseditor/libraryoptionseditor.js",
"src/components/itemContextMenu.js",
"src/components/itemidentifier/itemidentifier.js",
"src/components/itemMediaInfo/itemMediaInfo.js",
"src/components/lazyLoader/lazyLoaderIntersectionObserver.js",
"src/components/mediainfo/mediainfo.js",
"src/components/multiSelect/multiSelect.js",
"src/components/maintabsmanager.js",
"src/components/mediaLibraryCreator/mediaLibraryCreator.js",
"src/components/mediaLibraryEditor/mediaLibraryEditor.js",
"src/components/metadataEditor/metadataEditor.js",
"src/components/metadataEditor/personEditor.js",
"src/components/nowPlayingBar/nowPlayingBar.js",
"src/components/listview/listview.js",
"src/components/playback/brightnessosd.js",
"src/components/playback/mediasession.js",
"src/components/playback/nowplayinghelper.js",
@ -107,16 +138,101 @@
"src/components/playback/playmethodhelper.js",
"src/components/playback/remotecontrolautoplay.js",
"src/components/playback/volumeosd.js",
"src/components/playerstats/playerstats.js",
"src/components/prompt/prompt.js",
"src/components/playbackSettings/playbackSettings.js",
"src/components/playlisteditor/playlisteditor.js",
"src/components/groupedcards.js",
"src/components/htmlMediaHelper.js",
"src/components/playmenu.js",
"src/components/sanatizefilename.js",
"src/components/scrollManager.js",
"src/components/syncplay/groupSelectionMenu.js",
"src/components/syncplay/playbackPermissionManager.js",
"src/components/syncplay/syncPlayManager.js",
"src/components/syncplay/timeSyncManager.js",
"src/components/search/searchfields.js",
"src/components/search/searchresults.js",
"src/components/settingshelper.js",
"src/components/subtitlesettings/subtitlesettings.js",
"src/components/subtitlesettings/subtitleappearancehelper.js",
"src/components/shortcuts.js",
"src/components/syncPlay/groupSelectionMenu.js",
"src/components/syncPlay/playbackPermissionManager.js",
"src/components/syncPlay/syncPlayManager.js",
"src/components/syncPlay/timeSyncManager.js",
"src/controllers/auth/addserver.js",
"src/controllers/auth/forgotpassword.js",
"src/controllers/auth/forgotpasswordpin.js",
"src/controllers/auth/login.js",
"src/controllers/auth/selectserver.js",
"src/controllers/dashboard/apikeys.js",
"src/controllers/dashboard/dashboard.js",
"src/controllers/dashboard/encodingsettings.js",
"src/controllers/dashboard/logs.js",
"src/controllers/user/menu.js",
"src/controllers/user/profile.js",
"src/controllers/user/subtitles.js",
"src/controllers/dashboard/general.js",
"src/controllers/dashboard/librarydisplay.js",
"src/controllers/dashboard/metadataImages.js",
"src/controllers/dashboard/metadatanfo.js",
"src/controllers/dashboard/plugins/repositories.js",
"src/controllers/dashboard/streaming.js",
"src/controllers/dashboard/mediaLibrary.js",
"src/controllers/dashboard/networking.js",
"src/controllers/dashboard/playback.js",
"src/controllers/dashboard/plugins/repositories.js",
"src/controllers/wizard/finish.js",
"src/controllers/wizard/remoteaccess.js",
"src/controllers/wizard/settings.js",
"src/controllers/wizard/start.js",
"src/controllers/wizard/user.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/searchpage.js",
"src/controllers/dashboard/scheduledtasks/scheduledtask.js",
"src/controllers/dashboard/scheduledtasks/scheduledtasks.js",
"src/controllers/dashboard/dlna/profile.js",
"src/controllers/dashboard/dlna/profiles.js",
"src/controllers/dashboard/dlna/settings.js",
"src/controllers/dashboard/devices/devices.js",
"src/controllers/dashboard/devices/device.js",
"src/controllers/dashboard/serveractivity.js",
"src/elements/emby-tabs/emby-tabs.js",
"src/elements/emby-scroller/emby-scroller.js",
"src/elements/emby-radio/emby-radio.js",
"src/elements/emby-checkbox/emby-checkbox.js",
"src/elements/emby-itemrefreshindicator/emby-itemrefreshindicator.js",
"src/elements/emby-progressbar/emby-progressbar.js",
"src/elements/emby-progressring/emby-progressring.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-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/elements/emby-button/emby-button.js",
"src/elements/emby-button/paper-icon-button-light.js",
"src/elements/emby-collapse/emby-collapse.js",
"src/elements/emby-input/emby-input.js",
"src/plugins/bookPlayer/plugin.js",
"src/plugins/bookPlayer/tableOfContent.js",
"src/plugins/bookPlayer/tableOfContents.js",
"src/plugins/photoPlayer/plugin.js",
"src/scripts/alphanumericshortcuts.js",
"src/scripts/autoBackdrops.js",
"src/scripts/settings/appSettings.js",
"src/scripts/settings/userSettings.js",
"src/scripts/settings/webSettings.js",
"src/scripts/datetime.js",
"src/scripts/deleteHelper.js",
"src/scripts/dfnshelper.js",
"src/scripts/dom.js",
@ -124,10 +240,20 @@
"src/scripts/filesystem.js",
"src/scripts/imagehelper.js",
"src/scripts/inputManager.js",
"src/plugins/backdropScreensaver/plugin.js",
"src/plugins/youtubePlayer/plugin.js",
"src/components/filterdialog/filterdialog.js",
"src/components/fetchhelper.js",
"src/scripts/editorsidebar.js",
"src/scripts/globalize.js",
"src/scripts/playlists.js",
"src/scripts/keyboardNavigation.js",
"src/scripts/settings/appSettings.js",
"src/scripts/settings/userSettings.js",
"src/scripts/settings/webSettings.js"
"src/scripts/taskbutton.js",
"src/scripts/touchHelper.js",
"src/scripts/themeLoader.js",
"src/plugins/backdropScreensaver/plugin.js",
"src/components/filterdialog/filterdialog.js",
"src/components/fetchhelper.js"
],
"plugins": [
"@babel/plugin-transform-modules-amd",
@ -157,6 +283,7 @@
"prepare": "gulp --production",
"build:development": "gulp --development",
"build:production": "gulp --production",
"build:standalone": "gulp standalone --development",
"lint": "eslint \".\"",
"stylelint": "stylelint \"src/**/*.css\""
}

View file

@ -1,6 +1,6 @@
<div data-role="page" class="page standalonePage">
<div class="padded-left padded-right padded-bottom-page">
<form class="addServerForm" style="margin: 0 auto;">
<form class="addServerForm" style="margin: 0 auto;" novalidate>
<h1>${HeaderConnectToServer}</h1>
<div class="inputContainer">
<input is="emby-input" type="url" id="txtServerHost" required="required" label="${LabelServerHost}"/>

View file

@ -597,6 +597,7 @@
.detailImageContainer {
position: relative;
margin-top: -25vh;
margin-bottom: 10vh;
float: left;
width: 25vw;
z-index: 3;
@ -641,7 +642,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 {
@ -797,9 +799,9 @@ div.itemDetailGalleryLink.defaultCardBackground {
}
.detailImageProgressContainer {
position: absolute;
bottom: 0;
width: 22.786458333333332vw;
margin-top: -0.4vw;
width: 100%;
}
.detailButton-text {

View file

@ -121,6 +121,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;
}

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!./components/accessSchedule/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 () {
dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg);
});
dlg.querySelector('form').addEventListener('submit', function (event) {
dlg.querySelector('form').addEventListener('submit', event => {
submitSchedule(dlg, options);
event.preventDefault();
return false;
});
};
xhr.send();
});
});
}
};
});
/* eslint-enable indent */
export default {
show: show
};

View file

@ -73,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);
});

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';
@ -56,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
@ -74,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) {
@ -91,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);
@ -99,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];
@ -118,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);
@ -154,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) {
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);
this.value(itemFocusValue);
}
var alphaFocusedElement;
var alphaFocusTimeout;
let alphaFocusedElement;
let alphaFocusTimeout;
function onAlphaFocusTimeout() {
alphaFocusTimeout = null;
if (document.activeElement === alphaFocusedElement) {
var value = alphaFocusedElement.getAttribute('data-value');
self.value(value, true);
const value = alphaFocusedElement.getAttribute('data-value');
this.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 new appFooter;

View file

@ -21,7 +21,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
};
function beginConnectionWizard() {
backdrop.clear();
backdrop.clearBackdrop();
loading.show();
connectionManager.connect({
enableAutoLogin: appSettings.enableAutoLogin()
@ -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 () {
@ -465,7 +465,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
function loadContent(ctx, route, html, request) {
html = globalize.translateDocument(html, route.dictionary);
html = globalize.translateHtml(html, route.dictionary);
request.view = html;
viewManager.loadView(request);
@ -657,7 +657,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

@ -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

@ -192,9 +192,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 +208,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 +221,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) {
@ -541,7 +539,7 @@ import 'programStyles';
imgType = 'Backdrop';
imgTag = item.ParentBackdropImageTags[0];
itemId = item.ParentBackdropItemId;
} else if (item.ImageTags && item.ImageTags.Primary) {
} 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;
@ -556,7 +554,10 @@ 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;
@ -577,10 +578,6 @@ import 'programStyles';
imgType = 'Primary';
imgTag = item.ParentPrimaryImageTag;
itemId = item.ParentPrimaryImageItemId;
} else if (item.SeriesPrimaryImageTag) {
imgType = 'Primary';
imgTag = item.SeriesPrimaryImageTag;
itemId = item.SeriesId;
} else if (item.AlbumId && item.AlbumPrimaryImageTag) {
imgType = 'Primary';
imgTag = item.AlbumPrimaryImageTag;
@ -1163,10 +1160,10 @@ import 'programStyles';
/**
* Imports the refresh indicator element.
*/
function requireRefreshIndicator() {
function importRefreshIndicator() {
if (!refreshIndicatorLoaded) {
refreshIndicatorLoaded = true;
require(['emby-itemrefreshindicator']);
import('emby-itemrefreshindicator');
}
}
@ -1370,9 +1367,6 @@ import 'programStyles';
let cardScalableClose = '';
let cardContentClass = 'cardContent';
if (!options.cardLayout) {
cardContentClass += ' cardContent-shadow';
}
let blurhashAttrib = '';
if (blurhash && blurhash.length > 0) {
@ -1380,21 +1374,20 @@ import 'programStyles';
}
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 + '" ' + 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 + '" ' + blurhashAttrib + '>') : ('<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>';
@ -1421,7 +1414,7 @@ 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) {
@ -1502,7 +1495,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>';
}
@ -1510,7 +1503,7 @@ 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>';
}

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);
@ -195,7 +207,7 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
context.querySelector('.selectLayout').value = layoutManager.getSavedLayout() || '';
showOrHideMissingEpisodesField(context, user, apiClient);
showOrHideMissingEpisodesField(context);
loading.hide();
}
@ -239,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);
});
@ -272,50 +284,51 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
return false;
}
function embed(options, self) {
require(['text!./displaySettings.template.html'], function (template) {
async function embed(options, self) {
const { default: template } = await import('text!./displaySettings.template.html');
options.element.innerHTML = globalize.translateDocument(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

@ -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');
@ -31,7 +34,7 @@ define(['dom', 'appRouter', 'connectionManager'], function (dom, appRouter, conn
}
}
function onItemsContainerClick(e) {
export 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

@ -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,7 +242,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
}
var options = {
const options = {
Limit: limit,
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo,Path',
ImageTypeLimit: 1,
@ -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,7 +681,7 @@ 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,Path',
@ -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

@ -99,7 +99,7 @@ import 'emby-input';
scrollY: false
});
dlg.classList.add('formDialog');
dlg.innerHTML = globalize.translateDocument(template);
dlg.innerHTML = globalize.translateHtml(template);
dlg.addEventListener('close', function () {
saveValues(dlg, options);
});
@ -112,7 +112,6 @@ import 'emby-input';
dlg.querySelector('.btnCancel').addEventListener('click', function () {
dialogHelper.close(dlg);
});
}
export class 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,11 +1,11 @@
.lazy-image-fadein {
opacity: 1;
transition: opacity 0.7s;
transition: opacity 0.5s;
}
.lazy-image-fadein-fast {
opacity: 1;
transition: opacity 0.2s;
transition: opacity 0.1s;
}
.lazy-hidden {
@ -29,4 +29,5 @@
width: 100%;
height: 100%;
z-index: 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) {
@ -161,10 +171,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',
@ -311,31 +321,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 +356,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 +381,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 +390,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 +400,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 +408,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':
@ -431,7 +442,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
getResolveFunction(resolve, id)();
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;
@ -502,8 +513,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 +522,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 +530,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 +553,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 +573,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 +585,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 +594,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 +609,9 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
});
}
return {
/* eslint-enable indent */
export default {
getCommands: getCommands,
show: show
};
});
};

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,30 @@ 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 = 2;
if (currentItemType === 'MusicAlbum') {
numLines++;
}
var lines = [result.Name];
const lines = [result.Name];
if (result.AlbumArtist) {
lines.push(result.AlbumArtist.Name);
@ -235,7 +254,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 +271,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 +280,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 +309,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 +357,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 +376,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 +403,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 +440,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 +458,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 +474,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 +518,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 +529,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 +541,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

@ -366,7 +366,7 @@ import 'emby-input';
isNewLibrary && parent.classList.add('newlibrary');
const response = await fetch('components/libraryoptionseditor/libraryoptionseditor.template.html');
const template = await response.text();
parent.innerHTML = globalize.translateDocument(template);
parent.innerHTML = globalize.translateHtml(template);
populateRefreshInterval(parent.querySelector('#selectAutoRefreshInterval'));
const promises = [populateLanguages(parent), populateCountries(parent.querySelector('#selectCountry'))];
Promise.all(promises).then(function() {

View file

@ -1,5 +1,20 @@
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 'css!./listview';
import 'emby-ratingbutton';
import 'emby-playstatebutton';
function getIndex(item, options) {
@ -8,9 +23,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,10 +84,10 @@ 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'
};
@ -80,9 +95,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
if (item.ImageTags && item.ImageTags.Primary) {
options.tag = item.ImageTags.Primary;
itemId = item.Id;
}
if (item.AlbumId && item.AlbumPrimaryImageTag) {
} else if (item.AlbumId && item.AlbumPrimaryImageTag) {
options.tag = item.AlbumPrimaryImageTag;
itemId = item.AlbumId;
} else if (item.SeriesId && item.SeriesPrimaryImageTag) {
@ -92,18 +105,20 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
options.tag = item.ParentPrimaryImageTag;
itemId = item.ParentPrimaryImageItemId;
}
let blurHashes = item.ImageBlurHashes || {};
let blurhashstr = (blurHashes[options.type] || {})[options.tag];
if (itemId) {
return { url: apiClient.getScaledImageUrl(itemId, options), blurhash: blurhashstr };
}
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'
};
@ -121,13 +136,13 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
function getTextLinesHtml(textlines, isLargeStyle) {
var html = '';
let html = '';
var largeTitleTagName = layoutManager.tv ? 'h2' : 'div';
const largeTitleTagName = layoutManager.tv ? 'h2' : 'div';
for (var i = 0, length = textlines.length; i < length; i++) {
for (let i = 0, length = textlines.length; i < length; i++) {
var text = textlines[i];
const text = textlines[i];
if (!text) {
continue;
@ -135,7 +150,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
if (i === 0) {
if (isLargeStyle) {
html += '<' + largeTitleTagName + ' class="listItemBodyText">';
html += `<${largeTitleTagName} class="listItemBodyText">`;
} else {
html += '<div class="listItemBodyText">';
}
@ -144,7 +159,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
}
html += (textlines[i] || '&nbsp;');
if (i === 0 && isLargeStyle) {
html += '</' + largeTitleTagName + '>';
html += `</${largeTitleTagName}>`;
} else {
html += '</div>';
}
@ -155,13 +170,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;
@ -171,34 +186,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) {
@ -220,7 +235,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
}
}
var cssClass = 'listItem';
let cssClass = 'listItem';
if (options.border || (options.highlight !== false && !layoutManager.tv)) {
cssClass += ' listItem-border';
@ -234,28 +249,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) {
@ -278,37 +293,37 @@ 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 ? 'resume' : action;
let blurhashAttrib = '';
if (blurhash && blurhash.length > 0) {
blurhashAttrib = 'data-blurhash="' + blurhash + '"';
blurhashAttrib = `data-blurhash="${blurhash}"`;
}
if (imgUrl) {
html += '<div data-action="' + imageAction + '" class="' + imageClass + ' lazy" data-src="' + imgUrl + '" ' + blurhashAttrib + ' item-icon>';
html += `<div data-action="${imageAction}" class="${imageClass} lazy" data-src="${imgUrl}" ${blurhashAttrib} item-icon>`;
} else {
html += '<div class="' + imageClass + '">';
html += `<div class="${imageClass}">`;
}
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'
});
@ -325,7 +340,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
html += '</div>';
}
var textlines = [];
const textlines = [];
if (options.showProgramDateTime) {
textlines.push(datetime.toLocaleString(datetime.parseISO8601Date(item.StartDate), {
@ -348,7 +363,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
}
}
var parentTitle = null;
let parentTitle = null;
if (options.showParentTitle) {
if (item.Type === 'Episode') {
@ -358,12 +373,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) {
@ -394,14 +409,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;
}
}
@ -409,7 +424,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(', '));
}
@ -432,7 +447,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
cssClass += ' listItemBody-noleftpadding';
}
html += '<div class="' + cssClass + '">';
html += `<div class="${cssClass}">`;
const moreIcon = 'more_vert';
@ -441,14 +456,16 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
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>';
}
}
@ -462,7 +479,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,
@ -470,7 +488,8 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
criticRating: false,
endsAt: false
}) + '</div>';
});
html += '</div>';
}
}
@ -487,7 +506,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
}
if (options.moreButton !== false) {
html += '<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="menu"><span class="material-icons ' + moreIcon + '"></span></button>';
html += `<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="menu"><span class="material-icons ${moreIcon}"></span></button>`;
}
if (options.infoButton) {
@ -500,15 +519,15 @@ 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)) {
html += '<button is="emby-playstatebutton" type="button" class="listItemButton paper-icon-button-light" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-played="' + (userData.Played) + '"><span class="material-icons check"></span></button>';
html += `<button is="emby-playstatebutton" type="button" class="listItemButton paper-icon-button-light" data-id="${item.Id}" data-serverid="${item.ServerId}" data-itemtype="${item.Type}" data-played="${userData.Played}"><span class="material-icons check"></span></button>`;
}
if (itemHelper.canRate(item)) {
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>';
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>`;
}
}
}
@ -524,7 +543,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
}
}
html += '</' + outerTagName + '>';
html += `</${outerTagName}>`;
outerHtml += html;
}
@ -532,7 +551,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
return outerHtml;
}
return {
/* eslint-enable indent */
export default {
getListViewHtml: getListViewHtml
};
});
};

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

@ -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);
@ -212,11 +233,11 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
function addElementToList(source, sortCallback) {
require(['prompt'], function (prompt) {
prompt({
prompt.default({
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 +245,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 +255,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);
@ -247,13 +268,13 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
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,7 +285,7 @@ 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);
}
}
@ -272,11 +293,11 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
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));
@ -308,10 +329,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 +343,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 +361,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 +372,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 +383,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 +399,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 +421,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 +469,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 +486,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 +505,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 +707,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 +719,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 +738,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 +777,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
return a.Name;
}).join(';');
var date;
let date;
if (item.DateCreated) {
try {
@ -798,7 +819,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 +829,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 +839,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 +863,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 +874,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 +892,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 +916,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 +953,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 +969,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 +993,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 +1007,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);
@ -1018,7 +1037,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
function centerFocus(elem, horiz, on) {
require(['scrollHelper'], function (scrollHelper) {
var fn = on ? 'on' : 'off';
const fn = on ? 'on' : 'off';
scrollHelper.centerFocus[fn](elem, horiz);
});
}
@ -1028,7 +1047,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
require(['text!./metadataEditor.template.html'], function (template) {
var dialogOptions = {
const dialogOptions = {
removeOnClose: true,
scrollY: false
};
@ -1039,13 +1058,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 +1090,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);
@ -1085,7 +1104,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
require(['text!./metadataEditor.template.html'], function (template) {
elem.innerHTML = globalize.translateDocument(template, 'core');
elem.innerHTML = globalize.translateHtml(template, 'core');
elem.querySelector('.formDialogFooter').classList.remove('formDialogFooter');
elem.querySelector('.btnHeaderSave').classList.remove('hide');
@ -1101,4 +1120,5 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
});
}
};
});
/* eslint-enable indent */

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';
const fn = on ? 'on' : 'off';
scrollHelper.centerFocus[fn](elem, horiz);
});
}
@ -13,7 +21,7 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'require', 'paper-icon-but
require(['text!./personEditor.template.html'], function (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.showEditor({
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.showEditor({
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

@ -1,31 +1,46 @@
define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader', 'layoutManager', 'playbackManager', 'nowPlayingHelper', 'apphost', 'dom', 'connectionManager', 'itemContextMenu', 'paper-icon-button-light', 'emby-ratingbutton'], function (require, datetime, itemHelper, events, browser, imageLoader, layoutManager, playbackManager, nowPlayingHelper, appHost, dom, connectionManager, itemContextMenu) {
'use strict';
import require from 'require';
import datetime from 'datetime';
import itemHelper from 'itemHelper';
import events from 'events';
import browser from 'browser';
import imageLoader from 'imageLoader';
import layoutManager from 'layoutManager';
import playbackManager from 'playbackManager';
import nowPlayingHelper from 'nowPlayingHelper';
import appHost from 'apphost';
import dom from 'dom';
import connectionManager from 'connectionManager';
import itemContextMenu from 'itemContextMenu';
import 'paper-icon-button-light';
import 'emby-ratingbutton';
var currentPlayer;
var currentPlayerSupportedCommands = [];
/* eslint-disable indent */
var currentTimeElement;
var nowPlayingImageElement;
var nowPlayingTextElement;
var nowPlayingUserData;
var muteButton;
var volumeSlider;
var volumeSliderContainer;
var playPauseButtons;
var positionSlider;
var toggleRepeatButton;
var toggleRepeatButtonIcon;
let currentPlayer;
let currentPlayerSupportedCommands = [];
var lastUpdateTime = 0;
var lastPlayerState = {};
var isEnabled;
var currentRuntimeTicks = 0;
let currentTimeElement;
let nowPlayingImageElement;
let nowPlayingTextElement;
let nowPlayingUserData;
let muteButton;
let volumeSlider;
let volumeSliderContainer;
let playPauseButtons;
let positionSlider;
let toggleRepeatButton;
let toggleRepeatButtonIcon;
var isVisibilityAllowed = true;
let lastUpdateTime = 0;
let lastPlayerState = {};
let isEnabled;
let currentRuntimeTicks = 0;
let isVisibilityAllowed = true;
function getNowPlayingBarHtml() {
var html = '';
let html = '';
html += '<div class="nowPlayingBar hide nowPlayingBar-hidden">';
@ -198,7 +213,7 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
if (currentPlayer) {
var newPercent = parseFloat(this.value);
const newPercent = parseFloat(this.value);
playbackManager.seekPercent(newPercent, currentPlayer);
}
@ -207,13 +222,13 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
positionSlider.getBubbleText = function (value) {
var state = lastPlayerState;
const state = lastPlayerState;
if (!state || !state.NowPlayingItem || !currentRuntimeTicks) {
return '--:--';
}
var ticks = currentRuntimeTicks;
let ticks = currentRuntimeTicks;
ticks /= 100;
ticks *= value;
@ -230,12 +245,12 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
function showRemoteControl() {
require(['appRouter'], function (appRouter) {
import('appRouter').then(({default: appRouter}) => {
appRouter.showNowPlaying();
});
}
var nowPlayingBarElement;
let nowPlayingBarElement;
function getNowPlayingBar() {
if (nowPlayingBarElement) {
@ -243,10 +258,15 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
}
return new Promise(function (resolve, reject) {
require(['appFooter-shared', 'itemShortcuts', 'css!./nowPlayingBar.css', 'emby-slider'], function (appfooter, itemShortcuts) {
var parentContainer = appfooter.element;
Promise.all([
import('appFooter-shared'),
import('itemShortcuts'),
import('css!./nowPlayingBar.css'),
import('emby-slider')
])
.then(([appfooter, itemShortcuts]) => {
console.log(appfooter);
const parentContainer = appfooter.element;
nowPlayingBarElement = parentContainer.querySelector('.nowPlayingBar');
if (nowPlayingBarElement) {
@ -294,13 +314,13 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
lastPlayerState = state;
var playerInfo = playbackManager.getPlayerInfo();
const playerInfo = playbackManager.getPlayerInfo();
var playState = state.PlayState || {};
const playState = state.PlayState || {};
updatePlayPauseState(playState.IsPaused);
var supportedCommands = playerInfo.supportedCommands;
const supportedCommands = playerInfo.supportedCommands;
currentPlayerSupportedCommands = supportedCommands;
if (supportedCommands.indexOf('SetRepeatMode') === -1) {
@ -317,11 +337,11 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
positionSlider.disabled = !playState.CanSeek;
// determines if both forward and backward buffer progress will be visible
var isProgressClear = state.MediaSource && state.MediaSource.RunTimeTicks == null;
const isProgressClear = state.MediaSource && state.MediaSource.RunTimeTicks == null;
positionSlider.setIsClear(isProgressClear);
}
var nowPlayingItem = state.NowPlayingItem || {};
const nowPlayingItem = state.NowPlayingItem || {};
updateTimeDisplay(playState.PositionTicks, nowPlayingItem.RunTimeTicks, playbackManager.getBufferedRanges(player));
updateNowPlayingInfo(state);
@ -348,7 +368,7 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
if (positionSlider && !positionSlider.dragging) {
if (runtimeTicks) {
var pct = positionTicks / runtimeTicks;
let pct = positionTicks / runtimeTicks;
pct *= 100;
positionSlider.value = pct;
@ -365,7 +385,7 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
if (currentTimeElement) {
var timeText = positionTicks == null ? '--:--' : datetime.getDisplayRunningTime(positionTicks);
let timeText = positionTicks == null ? '--:--' : datetime.getDisplayRunningTime(positionTicks);
if (runtimeTicks) {
timeText += ' / ' + datetime.getDisplayRunningTime(runtimeTicks);
@ -377,10 +397,10 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
function updatePlayerVolumeState(isMuted, volumeLevel) {
var supportedCommands = currentPlayerSupportedCommands;
const supportedCommands = currentPlayerSupportedCommands;
var showMuteButton = true;
var showVolumeSlider = true;
let showMuteButton = true;
let showVolumeSlider = true;
if (supportedCommands.indexOf('ToggleMute') === -1) {
showMuteButton = false;
@ -495,37 +515,37 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
return null;
}
var currentImgUrl;
let currentImgUrl;
function updateNowPlayingInfo(state) {
var nowPlayingItem = state.NowPlayingItem;
const nowPlayingItem = state.NowPlayingItem;
var textLines = nowPlayingItem ? nowPlayingHelper.getNowPlayingNames(nowPlayingItem) : [];
const textLines = nowPlayingItem ? nowPlayingHelper.getNowPlayingNames(nowPlayingItem) : [];
if (textLines.length > 1) {
textLines[1].secondary = true;
}
nowPlayingTextElement.innerHTML = textLines.map(function (nowPlayingName) {
var cssClass = nowPlayingName.secondary ? ' class="nowPlayingBarSecondaryText"' : '';
const cssClass = nowPlayingName.secondary ? ' class="nowPlayingBarSecondaryText"' : '';
if (nowPlayingName.item) {
var nowPlayingText = getTextActionButton(nowPlayingName.item, nowPlayingName.text);
const nowPlayingText = getTextActionButton(nowPlayingName.item, nowPlayingName.text);
return `<div ${cssClass}>${nowPlayingText}</div>`;
}
let nowPlayingText = '';
return `<div ${cssClass}>${nowPlayingText}</div>`;
}).join('');
var imgHeight = 70;
const imgHeight = 70;
var url = nowPlayingItem ? (seriesImageUrl(nowPlayingItem, {
const url = nowPlayingItem ? (seriesImageUrl(nowPlayingItem, {
height: imgHeight
}) || imageUrl(nowPlayingItem, {
height: imgHeight
})) : null;
var isRefreshing = false;
let isRefreshing = false;
if (url !== currentImgUrl) {
currentImgUrl = url;
@ -541,12 +561,12 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
if (nowPlayingItem.Id) {
if (isRefreshing) {
var apiClient = connectionManager.getApiClient(nowPlayingItem.ServerId);
const apiClient = connectionManager.getApiClient(nowPlayingItem.ServerId);
apiClient.getItem(apiClient.getCurrentUserId(), nowPlayingItem.Id).then(function (item) {
var userData = item.UserData || {};
var likes = userData.Likes == null ? '' : userData.Likes;
var contextButton = document.querySelector('.btnToggleContextMenu');
var options = {
const userData = item.UserData || {};
const likes = userData.Likes == null ? '' : userData.Likes;
const contextButton = document.querySelector('.btnToggleContextMenu');
const options = {
play: false,
queue: false,
positionTo: contextButton
@ -570,7 +590,7 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
function onPlaybackStart(e, state) {
console.debug('nowplaying event: ' + e.type);
var player = this;
const player = this;
onStateChanged.call(player, e, state);
}
@ -581,7 +601,7 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
return;
}
var player = this;
const player = this;
updateRepeatModeDisplay(playbackManager.getRepeatMode(player));
}
@ -604,7 +624,7 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
// in the event of a stop->play command
// Don't call getNowPlayingBar here because we don't want to end up creating it just to hide it
var elem = document.getElementsByClassName('nowPlayingBar')[0];
const elem = document.getElementsByClassName('nowPlayingBar')[0];
if (elem) {
slideDown(elem);
@ -614,7 +634,7 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
function onPlaybackStopped(e, state) {
console.debug('nowplaying event: ' + e.type);
var player = this;
const player = this;
if (player.isLocalPlayer) {
if (state.NextMediaType !== 'Audio') {
@ -633,14 +653,14 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
return;
}
var player = this;
const player = this;
updatePlayPauseState(player.paused());
}
function onStateChanged(event, state) {
console.debug('nowplaying event: ' + event.type);
var player = this;
const player = this;
if (!state.NowPlayingItem || layoutManager.tv) {
hideNowPlayingBar();
@ -671,21 +691,21 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
}
// Try to avoid hammering the document with changes
var now = new Date().getTime();
const now = new Date().getTime();
if ((now - lastUpdateTime) < 700) {
return;
}
lastUpdateTime = now;
var player = this;
const player = this;
currentRuntimeTicks = playbackManager.duration(player);
updateTimeDisplay(playbackManager.currentTime(player), currentRuntimeTicks, playbackManager.getBufferedRanges(player));
}
function releaseCurrentPlayer() {
var player = currentPlayer;
const player = currentPlayer;
if (player) {
events.off(player, 'playbackstart', onPlaybackStart);
@ -708,14 +728,14 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
return;
}
var player = this;
const player = this;
updatePlayerVolumeState(player.isMuted(), player.getVolume());
}
function refreshFromPlayer(player) {
var state = playbackManager.getPlayerState(player);
const state = playbackManager.getPlayerState(player);
onStateChanged.call(player, { type: 'init' }, state);
}
@ -771,4 +791,5 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
}
}
});
});
/* eslint-enable indent */

View file

@ -241,6 +241,15 @@ import connectionManager from 'connectionManager';
navigator.mediaSession.setActionHandler('seekforward', function () {
execute('fastForward');
});
/* eslint-disable-next-line compat/compat */
navigator.mediaSession.setActionHandler('seekto', function (object) {
let item = playbackManager.getPlayerState(currentPlayer).NowPlayingItem;
// Convert to ms
let duration = parseInt(item.RunTimeTicks ? (item.RunTimeTicks / 10000) : 0);
let wantedTime = object.seekTime * 1000;
playbackManager.seekPercent(wantedTime / duration * 100, currentPlayer);
});
}
events.on(playbackManager, 'playerchange', function () {

View file

@ -709,7 +709,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla
function showPlaybackInfoErrorMessage(instance, errorCode, playNextTrack) {
require(['alert'], function (alert) {
alert({
alert.default({
text: globalize.translate('PlaybackError' + errorCode),
title: globalize.translate('HeaderPlaybackError')
}).then(function () {
@ -1907,11 +1907,8 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla
// Setting this to true may cause some incorrect sorting
Recursive: false,
SortBy: options.shuffle ? 'Random' : 'SortName',
MediaTypes: 'Photo,Video',
Limit: 500
MediaTypes: 'Photo,Video'
}).then(function (result) {
var items = result.Items;
var index = items.map(function (i) {

View file

@ -118,7 +118,7 @@ export function show(button) {
});
require(['actionsheet'], function (actionsheet) {
import('actionsheet').then(({default: actionsheet}) => {
loading.hide();
@ -153,8 +153,12 @@ export function show(button) {
}
function showActivePlayerMenu(playerInfo) {
require(['dialogHelper', 'dialog', 'emby-checkbox', 'emby-button'], function (dialogHelper) {
Promise.all([
import('dialogHelper'),
import('dialog'),
import('emby-checkbox'),
import('emby-button')
]).then(([dialogHelper]) => {
showActivePlayerMenuInternal(dialogHelper, playerInfo);
});
}
@ -163,7 +167,7 @@ function disconnectFromPlayer(currentDeviceName) {
if (playbackManager.getSupportedCommands().indexOf('EndSession') !== -1) {
require(['dialog'], function (dialog) {
import('dialog').then(({default: dialog}) => {
var menuItems = [];

View file

@ -1,31 +1,42 @@
define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'qualityoptions', 'globalize', 'loading', 'connectionManager', 'dom', 'events', 'emby-select', 'emby-checkbox'], function (require, browser, appSettings, appHost, focusManager, qualityoptions, globalize, loading, connectionManager, dom, events) {
'use strict';
import browser from 'browser';
import appSettings from 'appSettings';
import appHost from 'apphost';
import focusManager from 'focusManager';
import qualityoptions from 'qualityoptions';
import globalize from 'globalize';
import loading from 'loading';
import connectionManager from 'connectionManager';
import events from 'events';
import 'emby-select';
import 'emby-checkbox';
/* eslint-disable indent */
function fillSkipLengths(select) {
var options = [5, 10, 15, 20, 25, 30];
const options = [5, 10, 15, 20, 25, 30];
select.innerHTML = options.map(function (option) {
select.innerHTML = options.map(option => {
return {
name: globalize.translate('ValueSeconds', option),
value: option * 1000
};
}).map(function (o) {
return '<option value="' + o.value + '">' + o.name + '</option>';
}).map(o => {
return `<option value="${o.value}">${o.name}</option>`;
}).join('');
}
function populateLanguages(select, languages) {
var html = '';
let html = '';
html += "<option value=''>" + globalize.translate('AnyLanguage') + '</option>';
html += `<option value=''>${globalize.translate('AnyLanguage')}</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.ThreeLetterISOLanguageName + "'>" + culture.DisplayName + '</option>';
html += `<option value='${culture.ThreeLetterISOLanguageName}'>${culture.DisplayName}</option>`;
}
select.innerHTML = html;
@ -33,7 +44,7 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
function setMaxBitrateIntoField(select, isInNetwork, mediatype) {
var options = mediatype === 'Audio' ? qualityoptions.getAudioQualityOptions({
const options = mediatype === 'Audio' ? qualityoptions.getAudioQualityOptions({
currentMaxBitrate: appSettings.maxStreamingBitrate(isInNetwork, mediatype),
isAutomaticBitrateEnabled: appSettings.enableAutomaticBitrateDetection(isInNetwork, mediatype),
@ -47,10 +58,10 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
});
select.innerHTML = options.map(function (i) {
select.innerHTML = options.map(i => {
// render empty string instead of 0 for the auto option
return '<option value="' + (i.bitrate || '') + '">' + i.name + '</option>';
return `<option value="${i.bitrate || ''}">${i.name}</option>`;
}).join('');
if (appSettings.enableAutomaticBitrateDetection(isInNetwork, mediatype)) {
@ -62,23 +73,23 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
function fillChromecastQuality(select) {
var options = qualityoptions.getVideoQualityOptions({
const options = qualityoptions.getVideoQualityOptions({
currentMaxBitrate: appSettings.maxChromecastBitrate(),
isAutomaticBitrateEnabled: !appSettings.maxChromecastBitrate(),
enableAuto: true
});
select.innerHTML = options.map(function (i) {
select.innerHTML = options.map(i => {
// render empty string instead of 0 for the auto option
return '<option value="' + (i.bitrate || '') + '">' + i.name + '</option>';
return `<option value="${i.bitrate || ''}">${i.name}</option>`;
}).join('');
select.value = appSettings.maxChromecastBitrate() || '';
}
function setMaxBitrateFromField(select, isInNetwork, mediatype, value) {
function setMaxBitrateFromField(select, isInNetwork, mediatype) {
if (select.value) {
appSettings.maxStreamingBitrate(isInNetwork, mediatype, select.value);
@ -110,7 +121,7 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
return;
}
apiClient.getEndpointInfo().then(function (endpointInfo) {
apiClient.getEndpointInfo().then(endpointInfo => {
if (endpointInfo.IsInNetwork) {
@ -133,7 +144,7 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
});
}
function showOrHideEpisodesField(context, user, apiClient) {
function showOrHideEpisodesField(context) {
if (browser.tizen || browser.web0s) {
context.querySelector('.fldEpisodeAutoPlay').classList.add('hide');
@ -145,12 +156,12 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
function loadForm(context, user, userSettings, apiClient) {
var loggedInUserId = apiClient.getCurrentUserId();
var userId = user.Id;
const loggedInUserId = apiClient.getCurrentUserId();
const userId = user.Id;
showHideQualityFields(context, user, apiClient);
apiClient.getCultures().then(function (allCultures) {
apiClient.getCultures().then(allCultures => {
populateLanguages(context.querySelector('#selectAudioLanguage'), allCultures);
@ -159,7 +170,7 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
});
// hide cinema mode options if disabled at server level
apiClient.getNamedConfiguration('cinemamode').then(function (cinemaConfig) {
apiClient.getNamedConfiguration('cinemamode').then(cinemaConfig => {
if (cinemaConfig.EnableIntrosForMovies || cinemaConfig.EnableIntrosForEpisodes) {
context.querySelector('.cinemaModeOptions').classList.remove('hide');
@ -204,18 +215,18 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
fillChromecastQuality(context.querySelector('.selectChromecastVideoQuality'));
var selectChromecastVersion = context.querySelector('.selectChromecastVersion');
const selectChromecastVersion = context.querySelector('.selectChromecastVersion');
selectChromecastVersion.value = userSettings.chromecastVersion();
var selectSkipForwardLength = context.querySelector('.selectSkipForwardLength');
const selectSkipForwardLength = context.querySelector('.selectSkipForwardLength');
fillSkipLengths(selectSkipForwardLength);
selectSkipForwardLength.value = userSettings.skipForwardLength();
var selectSkipBackLength = context.querySelector('.selectSkipBackLength');
const selectSkipBackLength = context.querySelector('.selectSkipBackLength');
fillSkipLengths(selectSkipBackLength);
selectSkipBackLength.value = userSettings.skipBackLength();
showOrHideEpisodesField(context, user, apiClient);
showOrHideEpisodesField(context);
loading.hide();
}
@ -248,20 +259,20 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
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();
});
});
@ -269,14 +280,14 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
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);
});
@ -289,9 +300,9 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
function embed(options, self) {
require(['text!./playbackSettings.template.html'], function (template) {
return import('text!./playbackSettings.template.html').then(({default: template}) => {
options.element.innerHTML = globalize.translateDocument(template, 'core');
options.element.innerHTML = globalize.translateHtml(template, 'core');
options.element.querySelector('form').addEventListener('submit', onSubmit.bind(self));
@ -307,43 +318,43 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
});
}
function PlaybackSettings(options) {
class PlaybackSettings {
constructor(options) {
this.options = options;
embed(options, this);
}
PlaybackSettings.prototype.loadData = function () {
loadData() {
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;
loadForm(context, user, userSettings, apiClient);
});
});
};
}
PlaybackSettings.prototype.submit = function () {
submit() {
onSubmit.call(this);
};
}
PlaybackSettings.prototype.destroy = function () {
destroy() {
this.options = null;
};
}
}
return PlaybackSettings;
});
/* eslint-enable indent */
export default PlaybackSettings;

View file

@ -1,9 +1,19 @@
define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlayManager', 'playMethodHelper', 'layoutManager', 'serverNotifications', 'paper-icon-button-light', 'css!./playerstats'], function (events, globalize, playbackManager, connectionManager, syncPlayManager, playMethodHelper, layoutManager, serverNotifications) {
'use strict';
import events from 'events';
import globalize from 'globalize';
import playbackManager from 'playbackManager';
import connectionManager from 'connectionManager';
import syncPlayManager from 'syncPlayManager';
import playMethodHelper from 'playMethodHelper';
import layoutManager from 'layoutManager';
import serverNotifications from 'serverNotifications';
import 'paper-icon-button-light';
import 'css!./playerstats';
/* eslint-disable indent */
function init(instance) {
var parent = document.createElement('div');
const parent = document.createElement('div');
parent.classList.add('playerStats');
@ -13,7 +23,7 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
parent.classList.add('hide');
var button;
let button;
if (layoutManager.tv) {
button = '';
@ -21,7 +31,7 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
button = '<button type="button" is="paper-icon-button-light" class="playerStats-closeButton"><span class="material-icons close"></span></button>';
}
var contentClass = layoutManager.tv ? 'playerStats-content playerStats-content-tv' : 'playerStats-content';
const contentClass = layoutManager.tv ? 'playerStats-content playerStats-content-tv' : 'playerStats-content';
parent.innerHTML = '<div class="' + contentClass + '">' + button + '<div class="playerStats-stats"></div></div>';
@ -44,9 +54,9 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
elem.querySelector('.playerStats-stats').innerHTML = categories.map(function (category) {
var categoryHtml = '';
let categoryHtml = '';
var stats = category.stats;
const stats = category.stats;
if (stats.length && category.name) {
categoryHtml += '<div class="playerStats-stat playerStats-stat-header">';
@ -62,11 +72,11 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
categoryHtml += '</div>';
}
for (var i = 0, length = stats.length; i < length; i++) {
for (let i = 0, length = stats.length; i < length; i++) {
categoryHtml += '<div class="playerStats-stat">';
var stat = stats[i];
const stat = stats[i];
categoryHtml += '<div class="playerStats-stat-label">';
categoryHtml += stat.label;
@ -86,13 +96,13 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
function getSession(instance, player) {
var now = new Date().getTime();
const now = new Date().getTime();
if ((now - (instance.lastSessionTime || 0)) < 10000) {
return Promise.resolve(instance.lastSession);
}
var apiClient = connectionManager.getApiClient(playbackManager.currentItem(player).ServerId);
const apiClient = connectionManager.getApiClient(playbackManager.currentItem(player).ServerId);
return apiClient.getSessions({
deviceId: apiClient.deviceId()
@ -114,12 +124,12 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
}
function getTranscodingStats(session, player, displayPlayMethod) {
var sessionStats = [];
const sessionStats = [];
var videoCodec;
var audioCodec;
var totalBitrate;
var audioChannels;
let videoCodec;
let audioCodec;
let totalBitrate;
let audioChannels;
if (session.TranscodingInfo) {
@ -208,11 +218,11 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
function getMediaSourceStats(session, player, displayPlayMethod) {
var sessionStats = [];
const sessionStats = [];
var mediaSource = playbackManager.currentMediaSource(player) || {};
var totalBitrate = mediaSource.Bitrate;
var mediaFileSize = mediaSource.Size;
const mediaSource = playbackManager.currentMediaSource(player) || {};
const totalBitrate = mediaSource.Bitrate;
const mediaFileSize = mediaSource.Size;
if (mediaSource.Container) {
sessionStats.push({
@ -236,26 +246,26 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
});
}
var mediaStreams = mediaSource.MediaStreams || [];
var videoStream = mediaStreams.filter(function (s) {
const mediaStreams = mediaSource.MediaStreams || [];
const videoStream = mediaStreams.filter(function (s) {
return s.Type === 'Video';
})[0] || {};
var videoCodec = videoStream.Codec;
const videoCodec = videoStream.Codec;
var audioStreamIndex = playbackManager.getAudioStreamIndex(player);
var audioStream = playbackManager.audioTracks(player).filter(function (s) {
const audioStreamIndex = playbackManager.getAudioStreamIndex(player);
const audioStream = playbackManager.audioTracks(player).filter(function (s) {
return s.Type === 'Audio' && s.Index === audioStreamIndex;
})[0] || {};
var audioCodec = audioStream.Codec;
var audioChannels = audioStream.Channels;
const audioCodec = audioStream.Codec;
const audioChannels = audioStream.Channels;
var videoInfos = [];
const videoInfos = [];
if (videoCodec) {
videoInfos.push(videoCodec.toUpperCase());
@ -279,7 +289,7 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
});
}
var audioInfos = [];
const audioInfos = [];
if (audioCodec) {
audioInfos.push(audioCodec.toUpperCase());
@ -328,8 +338,8 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
}
function getSyncPlayStats() {
var syncStats = [];
var stats = syncPlayManager.getStats();
const syncStats = [];
const stats = syncPlayManager.getStats();
syncStats.push({
label: globalize.translate('LabelSyncPlayTimeOffset'),
@ -351,18 +361,18 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
function getStats(instance, player) {
var statsPromise = player.getStats ? player.getStats() : Promise.resolve({});
var sessionPromise = getSession(instance, player);
const statsPromise = player.getStats ? player.getStats() : Promise.resolve({});
const sessionPromise = getSession(instance, player);
return Promise.all([statsPromise, sessionPromise]).then(function (responses) {
var playerStatsResult = responses[0];
var playerStats = playerStatsResult.categories || [];
var session = responses[1];
const playerStatsResult = responses[0];
const playerStats = playerStatsResult.categories || [];
const session = responses[1];
var displayPlayMethod = playMethodHelper.getDisplayPlayMethod(session);
const displayPlayMethod = playMethodHelper.getDisplayPlayMethod(session);
var baseCategory = {
const baseCategory = {
stats: [],
name: 'Playback Info'
};
@ -377,13 +387,13 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
value: player.name
});
var categories = [];
const categories = [];
categories.push(baseCategory);
for (var i = 0, length = playerStats.length; i < length; i++) {
for (let i = 0, length = playerStats.length; i < length; i++) {
var category = playerStats[i];
const category = playerStats[i];
if (category.type === 'audio') {
category.name = 'Audio Info';
} else if (category.type === 'video') {
@ -418,7 +428,7 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
function renderPlayerStats(instance, player) {
var now = new Date().getTime();
const now = new Date().getTime();
if ((now - (instance.lastRender || 0)) < 700) {
return;
@ -428,7 +438,7 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
getStats(instance, player).then(function (stats) {
var elem = instance.element;
const elem = instance.element;
if (!elem) {
return;
}
@ -439,7 +449,7 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
function bindEvents(instance, player) {
var localOnTimeUpdate = function () {
const localOnTimeUpdate = function () {
renderPlayerStats(instance, player);
};
@ -449,14 +459,15 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
function unbindEvents(instance, player) {
var localOnTimeUpdate = instance.onTimeUpdate;
const localOnTimeUpdate = instance.onTimeUpdate;
if (localOnTimeUpdate) {
events.off(player, 'timeupdate', localOnTimeUpdate);
}
}
function PlayerStats(options) {
class PlayerStats {
constructor(options) {
this.options = options;
@ -465,13 +476,13 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
this.enabled(true);
}
PlayerStats.prototype.enabled = function (enabled) {
enabled(enabled) {
if (enabled == null) {
return this._enabled;
}
var options = this.options;
const options = this.options;
if (!options) {
return;
@ -485,15 +496,15 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
this.element.classList.add('hide');
unbindEvents(this, options.player);
}
};
}
PlayerStats.prototype.toggle = function () {
toggle() {
this.enabled(!this.enabled());
};
}
PlayerStats.prototype.destroy = function () {
destroy() {
var options = this.options;
const options = this.options;
if (options) {
@ -501,12 +512,14 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
unbindEvents(this, options.player);
}
var elem = this.element;
const elem = this.element;
if (elem) {
elem.parentNode.removeChild(elem);
this.element = null;
}
};
}
}
return PlayerStats;
});
/* eslint-enable indent */
export default PlayerStats;

View file

@ -1,13 +1,28 @@
define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackManager', 'connectionManager', 'userSettings', 'appRouter', 'globalize', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button'], function (dom, shell, dialogHelper, loading, layoutManager, playbackManager, connectionManager, userSettings, appRouter, globalize) {
'use strict';
import dom from 'dom';
import dialogHelper from 'dialogHelper';
import loading from 'loading';
import layoutManager from 'layoutManager';
import playbackManager from 'playbackManager';
import connectionManager from 'connectionManager';
import * as userSettings from 'userSettings';
import appRouter from 'appRouter';
import globalize from 'globalize';
import 'emby-input';
import 'paper-icon-button-light';
import 'emby-select';
import 'material-icons';
import 'css!./../formdialog';
import 'emby-button';
var currentServerId;
/* eslint-disable indent */
let currentServerId;
function onSubmit(e) {
var panel = dom.parentWithClass(this, 'dialog');
const panel = dom.parentWithClass(this, 'dialog');
var playlistId = panel.querySelector('#selectPlaylistToAddTo').value;
var apiClient = connectionManager.getApiClient(currentServerId);
const playlistId = panel.querySelector('#selectPlaylistToAddTo').value;
const apiClient = connectionManager.getApiClient(currentServerId);
if (playlistId) {
userSettings.set('playlisteditor-lastplaylistid', playlistId);
@ -23,7 +38,7 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
function createPlaylist(apiClient, dlg) {
loading.show();
var url = apiClient.getUrl('Playlists', {
const url = apiClient.getUrl('Playlists', {
Name: dlg.querySelector('#txtNewPlaylistName').value,
Ids: dlg.querySelector('.fldSelectedItemIds').value || '',
userId: apiClient.getCurrentUserId()
@ -34,10 +49,10 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
type: 'POST',
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);
redirectToPlaylist(apiClient, id);
@ -49,7 +64,7 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
}
function addToPlaylist(apiClient, dlg, id) {
var itemIds = dlg.querySelector('.fldSelectedItemIds').value || '';
const itemIds = dlg.querySelector('.fldSelectedItemIds').value || '';
if (id === 'queue') {
playbackManager.queue({
@ -63,7 +78,7 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
loading.show();
var url = apiClient.getUrl('Playlists/' + id + '/Items', {
const url = apiClient.getUrl(`Playlists/${id}/Items`, {
Ids: itemIds,
userId: apiClient.getCurrentUserId()
});
@ -72,7 +87,7 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
type: 'POST',
url: url
}).then(function () {
}).then(() => {
loading.hide();
dlg.submitted = true;
@ -85,36 +100,36 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
}
function populatePlaylists(editorOptions, panel) {
var select = panel.querySelector('#selectPlaylistToAddTo');
const select = panel.querySelector('#selectPlaylistToAddTo');
loading.hide();
panel.querySelector('.newPlaylistInfo').classList.add('hide');
var options = {
const options = {
Recursive: true,
IncludeItemTypes: 'Playlist',
SortBy: 'SortName',
EnableTotalRecordCount: false
};
var apiClient = connectionManager.getApiClient(currentServerId);
apiClient.getItems(apiClient.getCurrentUserId(), options).then(function (result) {
var html = '';
const apiClient = connectionManager.getApiClient(currentServerId);
apiClient.getItems(apiClient.getCurrentUserId(), options).then(result => {
let html = '';
if (editorOptions.enableAddToPlayQueue !== false && playbackManager.isPlaying()) {
html += '<option value="queue">' + globalize.translate('AddToPlayQueue') + '</option>';
html += `<option value="queue">${globalize.translate('AddToPlayQueue')}</option>`;
}
html += '<option value="">' + globalize.translate('OptionNew') + '</option>';
html += `<option value="">${globalize.translate('OptionNew')}</option>`;
html += result.Items.map(function (i) {
return '<option value="' + i.Id + '">' + i.Name + '</option>';
html += result.Items.map(i => {
return `<option value="${i.Id}">${i.Name}</option>`;
});
select.innerHTML = html;
var defaultValue = editorOptions.defaultValue;
let defaultValue = editorOptions.defaultValue;
if (!defaultValue) {
defaultValue = userSettings.get('playlisteditor-lastplaylistid') || '';
}
@ -132,29 +147,29 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
}
function getEditorHtml(items) {
var html = '';
let html = '';
html += '<div class="formDialogContent smoothScrollY" style="padding-top:2em;">';
html += '<div class="dialogContentInner dialog-content-centered">';
html += '<form style="margin:auto;">';
html += '<div class="fldSelectPlaylist selectContainer">';
var autoFocus = items.length ? ' autofocus' : '';
html += '<select is="emby-select" id="selectPlaylistToAddTo" label="' + globalize.translate('LabelPlaylist') + '"' + autoFocus + '></select>';
let autoFocus = items.length ? ' autofocus' : '';
html += `<select is="emby-select" id="selectPlaylistToAddTo" label="${globalize.translate('LabelPlaylist')}"${autoFocus}></select>`;
html += '</div>';
html += '<div class="newPlaylistInfo">';
html += '<div class="inputContainer">';
autoFocus = items.length ? '' : ' autofocus';
html += '<input is="emby-input" type="text" id="txtNewPlaylistName" required="required" label="' + globalize.translate('LabelName') + '"' + autoFocus + ' />';
html += `<input is="emby-input" type="text" id="txtNewPlaylistName" required="required" label="${globalize.translate('LabelName')}"${autoFocus} />`;
html += '</div>';
// newPlaylistInfo
html += '</div>';
html += '<div class="formDialogFooter">';
html += '<button is="emby-button" type="submit" class="raised btnSubmit block formDialogFooterItem button-submit">' + globalize.translate('Add') + '</button>';
html += `<button is="emby-button" type="submit" class="raised btnSubmit block formDialogFooterItem button-submit">${globalize.translate('Add')}</button>`;
html += '</div>';
html += '<input type="hidden" class="fldSelectedItemIds" />';
@ -187,7 +202,7 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
} else {
content.querySelector('.fldSelectPlaylist').classList.add('hide');
var selectPlaylistToAddTo = content.querySelector('#selectPlaylistToAddTo');
const selectPlaylistToAddTo = content.querySelector('#selectPlaylistToAddTo');
selectPlaylistToAddTo.innerHTML = '';
selectPlaylistToAddTo.value = '';
triggerChange(selectPlaylistToAddTo);
@ -195,21 +210,18 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
}
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 PlaylistEditor() {
}
PlaylistEditor.prototype.show = function (options) {
var items = options.items || {};
export class showEditor {
constructor(options) {
const items = options.items || {};
currentServerId = options.serverId;
var dialogOptions = {
const dialogOptions = {
removeOnClose: true,
scrollY: false
};
@ -220,12 +232,12 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
dialogOptions.size = 'small';
}
var dlg = dialogHelper.createDialog(dialogOptions);
const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog');
var html = '';
var title = globalize.translate('HeaderAddToPlaylist');
let html = '';
const title = globalize.translate('HeaderAddToPlaylist');
html += '<div class="formDialogHeader">';
html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
@ -241,7 +253,7 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
initEditor(dlg, options, items);
dlg.querySelector('.btnCancel').addEventListener('click', function () {
dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg);
});
@ -249,7 +261,7 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
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);
}
@ -260,7 +272,8 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
return Promise.reject();
});
};
}
}
return PlaylistEditor;
});
/* eslint-enable indent */
export default showEditor;

View file

@ -1,12 +1,24 @@
define(['browser', 'dialogHelper', 'layoutManager', 'scrollHelper', 'globalize', 'dom', 'require', 'material-icons', 'emby-button', 'paper-icon-button-light', 'emby-input', 'formDialogStyle'], function(browser, dialogHelper, layoutManager, scrollHelper, globalize, dom, require) {
'use strict';
import browser from 'browser';
import dialogHelper from 'dialogHelper';
import layoutManager from 'layoutManager';
import scrollHelper from 'scrollHelper';
import globalize from 'globalize';
import dom from 'dom';
import 'material-icons';
import 'emby-button';
import 'paper-icon-button-light';
import 'emby-input';
import 'formDialogStyle';
/* eslint-disable indent */
export default (() => {
function replaceAll(str, find, replace) {
return str.split(find).join(replace);
}
function setInputProperties(dlg, options) {
var txtInput = dlg.querySelector('#txtInput');
const txtInput = dlg.querySelector('#txtInput');
if (txtInput.label) {
txtInput.label(options.label || '');
@ -17,7 +29,7 @@ define(['browser', 'dialogHelper', 'layoutManager', 'scrollHelper', 'globalize',
}
function showDialog(options, template) {
var dialogOptions = {
const dialogOptions = {
removeOnClose: true,
scrollY: false
};
@ -26,7 +38,7 @@ define(['browser', 'dialogHelper', 'layoutManager', 'scrollHelper', 'globalize',
dialogOptions.size = 'fullscreen';
}
var dlg = dialogHelper.createDialog(dialogOptions);
const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog');
@ -39,7 +51,7 @@ define(['browser', 'dialogHelper', 'layoutManager', 'scrollHelper', 'globalize',
dlg.classList.add('dialog-fullscreen-lowres');
}
dlg.querySelector('.btnCancel').addEventListener('click', function (e) {
dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg);
});
@ -53,16 +65,16 @@ define(['browser', 'dialogHelper', 'layoutManager', 'scrollHelper', 'globalize',
setInputProperties(dlg, options);
var submitValue;
let submitValue;
dlg.querySelector('form').addEventListener('submit', function (e) {
dlg.querySelector('form').addEventListener('submit', e => {
submitValue = dlg.querySelector('#txtInput').value;
e.preventDefault();
e.stopPropagation();
// Important, don't close the dialog until after the form has completed submitting, or it will cause an error in Chrome
setTimeout(function () {
setTimeout(() => {
dialogHelper.close(dlg);
}, 300);
@ -71,9 +83,9 @@ define(['browser', 'dialogHelper', 'layoutManager', 'scrollHelper', 'globalize',
dlg.querySelector('.submitText').innerHTML = options.confirmText || globalize.translate('ButtonOk');
dlg.style.minWidth = (Math.min(400, dom.getWindowSize().innerWidth - 50)) + 'px';
dlg.style.minWidth = `${Math.min(400, dom.getWindowSize().innerWidth - 50)}px`;
return dialogHelper.open(dlg).then(function () {
return dialogHelper.open(dlg).then(() => {
if (layoutManager.tv) {
scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false);
}
@ -87,7 +99,7 @@ define(['browser', 'dialogHelper', 'layoutManager', 'scrollHelper', 'globalize',
}
if ((browser.tv || browser.xboxOne) && window.confirm) {
return function (options) {
return options => {
if (typeof options === 'string') {
options = {
label: '',
@ -95,8 +107,8 @@ define(['browser', 'dialogHelper', 'layoutManager', 'scrollHelper', 'globalize',
};
}
var label = replaceAll(options.label || '', '<br/>', '\n');
var result = prompt(label, options.text || '');
const label = replaceAll(options.label || '', '<br/>', '\n');
const result = prompt(label, options.text || '');
if (result) {
return Promise.resolve(result);
@ -105,9 +117,9 @@ define(['browser', 'dialogHelper', 'layoutManager', 'scrollHelper', 'globalize',
}
};
} else {
return function (options) {
return new Promise(function (resolve, reject) {
require(['text!./prompt.template.html'], function (template) {
return options => {
return new Promise((resolve, reject) => {
import('text!./prompt.template.html').then(({default: template}) => {
if (typeof options === 'string') {
options = {
title: '',
@ -119,4 +131,5 @@ define(['browser', 'dialogHelper', 'layoutManager', 'scrollHelper', 'globalize',
});
};
}
});
})();
/* eslint-enable indent */

View file

@ -2,12 +2,12 @@
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1">
<span class="material-icons arrow_back"></span>
</button>
<h3 class="formDialogHeaderTitle"></h3>
</div>
<div class="formDialogContent smoothScrollY">
<div class="dialogContentInner dialog-content-centered" style="padding-top:2em;">
<form>
<div class="inputContainer">
<input is="emby-input" type="text" id="txtInput" label="" />
@ -19,7 +19,6 @@
<span class="submitText"></span>
</button>
</div>
</form>
</div>
</div>

View file

@ -156,7 +156,7 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
var html = '';
html += globalize.translateDocument(template, 'core');
html += globalize.translateHtml(template, 'core');
dlg.innerHTML = html;

View file

@ -116,7 +116,7 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
var html = '';
html += globalize.translateDocument(template, 'core');
html += globalize.translateHtml(template, 'core');
dlg.innerHTML = html;

View file

@ -219,7 +219,7 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa
require(['text!./recordingfields.template.html'], function (template) {
var options = self.options;
var context = options.parent;
context.innerHTML = globalize.translateDocument(template, 'core');
context.innerHTML = globalize.translateHtml(template, 'core');
context.querySelector('.singleRecordingButton').addEventListener('click', onRecordChange.bind(self));
context.querySelector('.seriesRecordingButton').addEventListener('click', onRecordSeriesChange.bind(self));

View file

@ -34,7 +34,7 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
require(['confirm'], function (confirm) {
confirm({
confirm.default({
text: globalize.translate('MessageConfirmRecordingCancellation'),
primary: 'delete',
@ -59,7 +59,7 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
require(['confirm'], function (confirm) {
confirm({
confirm.default({
text: globalize.translate('MessageConfirmRecordingCancellation'),
primary: 'delete',

View file

@ -168,7 +168,7 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
var dlg = options.context;
dlg.classList.add('hide');
dlg.innerHTML = globalize.translateDocument(template, 'core');
dlg.innerHTML = globalize.translateHtml(template, 'core');
dlg.querySelector('.formDialogHeader').classList.add('hide');
dlg.querySelector('.formDialogFooter').classList.add('hide');
@ -221,7 +221,7 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
var html = '';
html += globalize.translateDocument(template, 'core');
html += globalize.translateHtml(template, 'core');
dlg.innerHTML = html;

View file

@ -175,7 +175,7 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
context.querySelector('.nowPlayingPageUserDataButtons').innerHTML = '<button is="emby-ratingbutton" type="button" class="listItemButton paper-icon-button-light" data-id="' + fullItem.Id + '" data-serverid="' + fullItem.ServerId + '" data-itemtype="' + fullItem.Type + '" data-likes="' + likes + '" data-isfavorite="' + userData.IsFavorite + '"><span class="material-icons favorite"></span></button>';
});
} else {
backdrop.clear();
backdrop.clearBackdrop();
context.querySelector('.nowPlayingPageUserDataButtons').innerHTML = '';
}
}
@ -196,7 +196,7 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
context.querySelector('.nowPlayingPageImage').classList.remove('nowPlayingPageImageAudio');
}
} else {
imgContainer.innerHTML = '<div class="nowPlayingPageImageContainerNoAlbum"><button data-action="link" class="cardContent-button cardImageContainer coveredImage ' + cardBuilder.getDefaultBackgroundClass(item.Name) + ' cardContent cardContent-shadow itemAction"><span class="cardImageIcon material-icons album"></span></button></div>';
imgContainer.innerHTML = '<div class="nowPlayingPageImageContainerNoAlbum"><button data-action="link" class="cardImageContainer coveredImage ' + cardBuilder.getDefaultBackgroundClass(item.Name) + ' cardContent cardContent-shadow itemAction"><span class="cardImageIcon material-icons album"></span></button></div>';
}
}
@ -589,7 +589,7 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
require(['playlistEditor'], function (playlistEditor) {
getSaveablePlaylistItems().then(function (items) {
var serverId = items.length ? items[0].ServerId : ApiClient.serverId();
new playlistEditor().show({
new playlistEditor.showEditor({
items: items.map(function (i) {
return i.Id;
}),

View file

@ -1,10 +1,20 @@
define(['layoutManager', 'globalize', 'require', 'events', 'browser', 'alphaPicker', 'emby-input', 'flexStyles', 'material-icons', 'css!./searchfields'], function (layoutManager, globalize, require, events, browser, AlphaPicker) {
'use strict';
import layoutManager from 'layoutManager';
import globalize from 'globalize';
import require from 'require';
import events from 'events';
import browser from 'browser';
import AlphaPicker from 'alphaPicker';
import 'emby-input';
import 'flexStyles';
import 'material-icons';
import 'css!./searchfields';
/* eslint-disable indent */
function onSearchTimeout() {
var instance = this;
var value = instance.nextSearchValue;
const instance = this;
let value = instance.nextSearchValue;
value = (value || '').trim();
events.trigger(instance, 'search', [value]);
@ -22,14 +32,14 @@ define(['layoutManager', 'globalize', 'require', 'events', 'browser', 'alphaPick
function onAlphaValueClicked(e) {
var value = e.detail.value;
var searchFieldsInstance = this;
const value = e.detail.value;
const searchFieldsInstance = this;
var txtSearch = searchFieldsInstance.options.element.querySelector('.searchfields-txtSearch');
const txtSearch = searchFieldsInstance.options.element.querySelector('.searchfields-txtSearch');
if (value === 'backspace') {
var val = txtSearch.value;
const val = txtSearch.value;
txtSearch.value = val.length ? val.substring(0, val.length - 1) : '';
} else {
@ -43,7 +53,7 @@ define(['layoutManager', 'globalize', 'require', 'events', 'browser', 'alphaPick
function initAlphaPicker(alphaPickerElement, instance) {
instance.alphaPicker = new AlphaPicker({
instance.alphaPicker = new AlphaPicker.default({
element: alphaPickerElement,
mode: 'keyboard'
});
@ -53,16 +63,16 @@ define(['layoutManager', 'globalize', 'require', 'events', 'browser', 'alphaPick
function onSearchInput(e) {
var value = e.target.value;
var searchFieldsInstance = this;
const value = e.target.value;
const searchFieldsInstance = this;
triggerSearch(searchFieldsInstance, value);
}
function embed(elem, instance, options) {
require(['text!./searchfields.template.html'], function (template) {
import('text!./searchfields.template.html').then(({default: template}) => {
var html = globalize.translateDocument(template, 'core');
let html = globalize.translateHtml(template, 'core');
if (browser.tizen || browser.orsay) {
html = html.replace('<input ', '<input readonly ');
@ -72,10 +82,10 @@ define(['layoutManager', 'globalize', 'require', 'events', 'browser', 'alphaPick
elem.classList.add('searchFields');
var txtSearch = elem.querySelector('.searchfields-txtSearch');
const txtSearch = elem.querySelector('.searchfields-txtSearch');
if (layoutManager.tv) {
var alphaPickerElement = elem.querySelector('.alphaPicker');
const alphaPickerElement = elem.querySelector('.alphaPicker');
elem.querySelector('.alphaPicker').classList.remove('hide');
initAlphaPicker(alphaPickerElement, instance);
@ -87,38 +97,39 @@ define(['layoutManager', 'globalize', 'require', 'events', 'browser', 'alphaPick
});
}
function SearchFields(options) {
class SearchFields {
constructor(options) {
this.options = options;
embed(options.element, this, options);
}
SearchFields.prototype.focus = function () {
focus() {
this.options.element.querySelector('.searchfields-txtSearch').focus();
};
}
destroy() {
SearchFields.prototype.destroy = function () {
var options = this.options;
const options = this.options;
if (options) {
options.element.classList.remove('searchFields');
}
this.options = null;
var alphaPicker = this.alphaPicker;
const alphaPicker = this.alphaPicker;
if (alphaPicker) {
alphaPicker.destroy();
}
this.alphaPicker = null;
var searchTimeout = this.searchTimeout;
const searchTimeout = this.searchTimeout;
if (searchTimeout) {
clearTimeout(searchTimeout);
}
this.searchTimeout = null;
this.nextSearchValue = null;
};
}
}
return SearchFields;
});
export default SearchFields;
/* eslint-enable indent */

View file

@ -1,9 +1,19 @@
define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager', 'cardBuilder', 'appRouter', 'emby-scroller', 'emby-itemscontainer', 'emby-button'], function (layoutManager, globalize, require, events, connectionManager, cardBuilder, appRouter) {
'use strict';
import layoutManager from 'layoutManager';
import globalize from 'globalize';
import require from 'require';
import events from 'events';
import connectionManager from 'connectionManager';
import cardBuilder from 'cardBuilder';
import appRouter from 'appRouter';
import 'emby-scroller';
import 'emby-itemscontainer';
import 'emby-button';
/* eslint-disable indent */
function loadSuggestions(instance, context, apiClient) {
var options = {
const options = {
SortBy: 'IsFavoriteOrLiked,Random',
IncludeItemTypes: 'Movie,Series,MusicArtist',
@ -21,18 +31,18 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager',
result.Items = [];
}
var html = result.Items.map(function (i) {
const html = result.Items.map(function (i) {
var href = appRouter.getRouteUrl(i);
const href = appRouter.getRouteUrl(i);
var itemHtml = '<div><a is="emby-linkbutton" class="button-link" style="display:inline-block;padding:.5em 1em;" href="' + href + '">';
let itemHtml = '<div><a is="emby-linkbutton" class="button-link" style="display:inline-block;padding:.5em 1em;" href="' + href + '">';
itemHtml += i.Name;
itemHtml += '</a></div>';
return itemHtml;
}).join('');
var searchSuggestions = context.querySelector('.searchSuggestions');
const searchSuggestions = context.querySelector('.searchSuggestions');
searchSuggestions.querySelector('.searchSuggestionsList').innerHTML = html;
if (result.Items.length) {
@ -49,9 +59,9 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager',
});
}
var allowSearch = true;
let allowSearch = true;
var queryIncludeItemTypes = query.IncludeItemTypes;
const queryIncludeItemTypes = query.IncludeItemTypes;
if (instance.options.collectionType === 'tvshows') {
if (query.IncludeArtists) {
@ -127,7 +137,7 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager',
query.EnableTotalRecordCount = false;
query.ImageTypeLimit = 1;
var methodName = 'getItems';
let methodName = 'getItems';
if (!query.IncludeMedia) {
if (query.IncludePeople) {
@ -566,9 +576,9 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager',
section = context.querySelector(section);
var items = result.Items || result.SearchHints;
const items = result.Items || result.SearchHints;
var itemsContainer = section.querySelector('.itemsContainer');
const itemsContainer = section.querySelector('.itemsContainer');
cardBuilder.buildCards(items, Object.assign({
@ -588,20 +598,20 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager',
}
function replaceAll(originalString, strReplace, strWith) {
var reg = new RegExp(strReplace, 'ig');
const reg = new RegExp(strReplace, 'ig');
return originalString.replace(reg, strWith);
}
function embed(elem, instance, options) {
require(['text!./searchresults.template.html'], function (template) {
import('text!./searchresults.template.html').then(({default: template}) => {
if (!enableScrollX()) {
template = replaceAll(template, 'data-horizontal="true"', 'data-horizontal="false"');
template = replaceAll(template, 'itemsContainer scrollSlider', 'itemsContainer scrollSlider vertical-wrap');
}
var html = globalize.translateDocument(template, 'core');
const html = globalize.translateHtml(template, 'core');
elem.innerHTML = html;
@ -610,28 +620,29 @@ define(['layoutManager', 'globalize', 'require', 'events', 'connectionManager',
});
}
function SearchResults(options) {
class SearchResults {
constructor(options) {
this.options = options;
embed(options.element, this, options);
}
search(value) {
SearchResults.prototype.search = function (value) {
var apiClient = connectionManager.getApiClient(this.options.serverId);
const apiClient = connectionManager.getApiClient(this.options.serverId);
search(this, apiClient, this.options.element, value);
};
}
destroy() {
SearchResults.prototype.destroy = function () {
var options = this.options;
const options = this.options;
if (options) {
options.element.classList.remove('searchFields');
}
this.options = null;
};
}
}
return SearchResults;
});
export default SearchResults;
/* eslint-enable indent */

View file

@ -1,158 +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';
var currentApiClient;
var currentDlg;
var currentInstance;
function reloadPageWhenServerAvailable(retryCount) {
var apiClient = currentApiClient;
if (!apiClient) {
return;
}
// Don't use apiclient method because we don't want it reporting authentication under the old version
apiClient.getJSON(apiClient.getUrl('System/Info')).then(function (info) {
// If this is back to false, the restart completed
if (!info.IsShuttingDown) {
currentInstance.restarted = true;
dialogHelper.close(currentDlg);
} else {
retryReload(retryCount);
}
}, function () {
retryReload(retryCount);
});
}
function retryReload(retryCount) {
setTimeout(function () {
retryCount = retryCount || 0;
retryCount++;
if (retryCount < 150) {
reloadPageWhenServerAvailable(retryCount);
}
}, 500);
}
function startRestart(instance, apiClient, dlg) {
currentApiClient = apiClient;
currentDlg = dlg;
currentInstance = instance;
apiClient.restartServer().then(function () {
setTimeout(reloadPageWhenServerAvailable, 250);
});
}
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';
if (enableTvLayout) {
formDialogContent.style['max-width'] = '50%';
formDialogContent.style['max-height'] = '60%';
scrollHelper.centerFocus.on(formDialogContent, false);
} else {
formDialogContent.style.maxWidth = (Math.min((configuredButtons.length * 150) + 200, dom.getWindowSize().innerWidth - 50)) + 'px';
dlg.classList.add('dialog-fullscreen-lowres');
}
dlg.querySelector('.formDialogHeaderTitle').innerHTML = globalize.translate('HeaderRestartingServer');
dlg.querySelector('.text').innerHTML = globalize.translate('RestartPleaseWaitMessage');
var i;
var length;
var html = '';
for (i = 0, length = configuredButtons.length; i < length; i++) {
var item = configuredButtons[i];
var autoFocus = i === 0 ? ' autofocus' : '';
var buttonClass = 'btnOption raised formDialogFooterItem formDialogFooterItem-autosize';
if (item.type) {
buttonClass += ' button-' + item.type;
}
html += '<button is="emby-button" type="button" class="' + buttonClass + '" data-id="' + item.id + '"' + autoFocus + '>' + item.name + '</button>';
}
dlg.querySelector('.formDialogFooter').innerHTML = html;
function onButtonClick() {
dialogHelper.close(dlg);
}
var buttons = dlg.querySelectorAll('.btnOption');
for (i = 0, length = buttons.length; i < length; i++) {
buttons[i].addEventListener('click', onButtonClick);
}
var dlgPromise = dialogHelper.open(dlg);
startRestart(instance, options.apiClient, dlg);
return dlgPromise.then(function () {
if (enableTvLayout) {
scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false);
}
instance.destroy();
loading.hide();
if (instance.restarted) {
events.trigger(instance, 'restarted');
}
});
}
function ServerRestartDialog(options) {
this.options = options;
}
ServerRestartDialog.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).then(resolve, reject);
});
});
};
ServerRestartDialog.prototype.destroy = function () {
currentApiClient = null;
currentDlg = null;
currentInstance = null;
this.options = null;
};
return ServerRestartDialog;
});

View file

@ -0,0 +1,22 @@
import globalize from 'globalize';
/**
* Helper for handling settings.
* @module components/settingsHelper
*/
export function populateLanguages(select, languages) {
let html = '';
html += "<option value=''>" + globalize.translate('AnyLanguage') + '</option>';
for (let i = 0, length = languages.length; i < length; i++) {
const culture = languages[i];
html += "<option value='" + culture.ThreeLetterISOLanguageName + "'>" + culture.DisplayName + '</option>';
}
select.innerHTML = html;
}
export default {
populateLanguages: populateLanguages
};

View file

@ -1,18 +1,30 @@
define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'globalize', 'loading', 'dom', 'recordingHelper'], function (playbackManager, inputManager, connectionManager, appRouter, globalize, loading, dom, recordingHelper) {
'use strict';
/* eslint-disable indent */
/**
* Module shortcuts.
* @module components/shortcuts
*/
import playbackManager from 'playbackManager';
import inputManager from 'inputManager';
import connectionManager from 'connectionManager';
import appRouter from 'appRouter';
import globalize from 'globalize';
import dom from 'dom';
import recordingHelper from 'recordingHelper';
function playAllFromHere(card, serverId, queue) {
var parent = card.parentNode;
var className = card.classList.length ? ('.' + card.classList[0]) : '';
var cards = parent.querySelectorAll(className + '[data-id]');
const parent = card.parentNode;
const className = card.classList.length ? (`.${card.classList[0]}`) : '';
const cards = parent.querySelectorAll(`${className}[data-id]`);
var ids = [];
const ids = [];
var foundCard = false;
var startIndex;
let foundCard = false;
let startIndex;
for (var i = 0, length = cards.length; i < length; i++) {
for (let i = 0, length = cards.length; i < length; i++) {
if (cards[i] === card) {
foundCard = true;
startIndex = i;
@ -22,12 +34,12 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
}
}
var itemsContainer = dom.parentWithClass(card, 'itemsContainer');
const itemsContainer = dom.parentWithClass(card, 'itemsContainer');
if (itemsContainer && itemsContainer.fetchData) {
var queryOptions = queue ? { StartIndex: startIndex } : {};
const queryOptions = queue ? { StartIndex: startIndex } : {};
return itemsContainer.fetchData(queryOptions).then(function (result) {
return itemsContainer.fetchData(queryOptions).then(result => {
if (queue) {
return playbackManager.queue({
@ -64,7 +76,7 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
function showProgramDialog(item) {
require(['recordingCreator'], function (recordingCreator) {
import('recordingCreator').then(({default:recordingCreator}) => {
recordingCreator.show(item.Id, item.ServerId);
});
@ -73,11 +85,11 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
function getItem(button) {
button = dom.parentWithAttribute(button, 'data-id');
var serverId = button.getAttribute('data-serverid');
var id = button.getAttribute('data-id');
var type = button.getAttribute('data-type');
const serverId = button.getAttribute('data-serverid');
const id = button.getAttribute('data-id');
const type = button.getAttribute('data-type');
var apiClient = connectionManager.getApiClient(serverId);
const apiClient = connectionManager.getApiClient(serverId);
if (type === 'Timer') {
return apiClient.getLiveTvTimer(id);
@ -99,19 +111,19 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
function showContextMenu(card, options) {
getItem(card).then(function (item) {
getItem(card).then(item => {
var playlistId = card.getAttribute('data-playlistid');
var collectionId = card.getAttribute('data-collectionid');
const playlistId = card.getAttribute('data-playlistid');
const collectionId = card.getAttribute('data-collectionid');
if (playlistId) {
var elem = dom.parentWithAttribute(card, 'data-playlistitemid');
const elem = dom.parentWithAttribute(card, 'data-playlistitemid');
item.PlaylistItemId = elem ? elem.getAttribute('data-playlistitemid') : null;
}
require(['itemContextMenu'], function (itemContextMenu) {
import('itemContextMenu').then(({default: itemContextMenu}) => {
connectionManager.getApiClient(item.ServerId).getCurrentUser().then(function (user) {
connectionManager.getApiClient(item.ServerId).getCurrentUser().then(user => {
itemContextMenu.show(Object.assign({
item: item,
play: true,
@ -122,9 +134,7 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
collectionId: collectionId,
user: user
}, options || {})).then(function (result) {
var itemsContainer;
}, options || {})).then(result => {
if (result.command === 'playallfromhere' || result.command === 'queueallfromhere') {
executeAction(card, options.positionTo, result.command);
@ -157,9 +167,9 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
function showPlayMenu(card, target) {
var item = getItemInfoFromCard(card);
const item = getItemInfoFromCard(card);
require(['playMenu'], function (playMenu) {
import('playMenu').then(({default: playMenu}) => {
playMenu.show({
@ -170,7 +180,7 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
}
function sendToast(text) {
require(['toast'], function (toast) {
import('toast').then(({default: toast}) => {
toast(text);
});
}
@ -179,19 +189,19 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
target = target || card;
var id = card.getAttribute('data-id');
let id = card.getAttribute('data-id');
if (!id) {
card = dom.parentWithAttribute(card, 'data-id');
id = card.getAttribute('data-id');
}
var item = getItemInfoFromCard(card);
const item = getItemInfoFromCard(card);
var serverId = item.ServerId;
var type = item.Type;
const serverId = item.ServerId;
const type = item.Type;
var playableItemId = type === 'Program' ? item.ChannelId : item.Id;
const playableItemId = type === 'Program' ? item.ChannelId : item.Id;
if (item.MediaType === 'Photo' && action === 'link') {
action = 'play';
@ -213,7 +223,7 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
});
} else if (action === 'play' || action === 'resume') {
var startPositionTicks = parseInt(card.getAttribute('data-positionticks') || '0');
const startPositionTicks = parseInt(card.getAttribute('data-positionticks') || '0');
playbackManager.play({
ids: [playableItemId],
@ -244,7 +254,7 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
onRecordCommand(serverId, id, type, card.getAttribute('data-timerid'), card.getAttribute('data-seriestimerid'));
} else if (action === 'menu') {
var options = target.getAttribute('data-playoptions') === 'false' ?
const options = target.getAttribute('data-playoptions') === 'false' ?
{
shuffle: false,
instantMix: false,
@ -261,7 +271,7 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
} else if (action === 'playmenu') {
showPlayMenu(card, target);
} else if (action === 'edit') {
getItem(target).then(function (item) {
getItem(target).then(item => {
editItem(item, serverId);
});
} else if (action === 'playtrailer') {
@ -270,9 +280,9 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
getItem(target).then(addToPlaylist);
} else if (action === 'custom') {
var customAction = target.getAttribute('data-customaction');
const customAction = target.getAttribute('data-customaction');
card.dispatchEvent(new CustomEvent('action-' + customAction, {
card.dispatchEvent(new CustomEvent(`action-${customAction}`, {
detail: {
playlistItemId: card.getAttribute('data-playlistitemid')
},
@ -283,7 +293,7 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
}
function addToPlaylist(item) {
require(['playlistEditor'], function (playlistEditor) {
import('playlistEditor').then(({default: playlistEditor}) => {
new playlistEditor().show({
items: [item.Id],
@ -295,35 +305,35 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
function playTrailer(item) {
var apiClient = connectionManager.getApiClient(item.ServerId);
const apiClient = connectionManager.getApiClient(item.ServerId);
apiClient.getLocalTrailers(apiClient.getCurrentUserId(), item.Id).then(function (trailers) {
apiClient.getLocalTrailers(apiClient.getCurrentUserId(), item.Id).then(trailers => {
playbackManager.play({ items: trailers });
});
}
function editItem(item, serverId) {
var apiClient = connectionManager.getApiClient(serverId);
const apiClient = connectionManager.getApiClient(serverId);
return new Promise(function (resolve, reject) {
return new Promise((resolve, reject) => {
var serverId = apiClient.serverInfo().Id;
const serverId = apiClient.serverInfo().Id;
if (item.Type === 'Timer') {
if (item.ProgramId) {
require(['recordingCreator'], function (recordingCreator) {
import('recordingCreator').then(({default: recordingCreator}) => {
recordingCreator.show(item.ProgramId, serverId).then(resolve, reject);
});
} else {
require(['recordingEditor'], function (recordingEditor) {
import('recordingEditor').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);
});
@ -335,19 +345,19 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
if (type === 'Program' || timerId || seriesTimerId) {
var programId = type === 'Program' ? id : null;
const programId = type === 'Program' ? id : null;
recordingHelper.toggleRecording(serverId, programId, timerId, seriesTimerId);
}
}
function onClick(e) {
export function onClick(e) {
var card = dom.parentWithClass(e.target, 'itemAction');
const card = dom.parentWithClass(e.target, 'itemAction');
if (card) {
var actionElement = card;
var action = actionElement.getAttribute('data-action');
let actionElement = card;
let action = actionElement.getAttribute('data-action');
if (!action) {
actionElement = dom.parentWithAttribute(actionElement, 'data-action');
@ -368,12 +378,12 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
function onCommand(e) {
var cmd = e.detail.command;
const cmd = e.detail.command;
if (cmd === 'play' || cmd === 'resume' || cmd === 'record' || cmd === 'menu' || cmd === 'info') {
var target = e.target;
var card = dom.parentWithClass(target, 'itemAction') || dom.parentWithAttribute(target, 'data-id');
const target = e.target;
const card = dom.parentWithClass(target, 'itemAction') || dom.parentWithAttribute(target, 'data-id');
if (card) {
e.preventDefault();
@ -383,7 +393,7 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
}
}
function on(context, options) {
export function on(context, options) {
options = options || {};
@ -396,7 +406,7 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
}
}
function off(context, options) {
export function off(context, options) {
options = options || {};
context.removeEventListener('click', onClick);
@ -406,23 +416,24 @@ define(['playbackManager', 'inputManager', 'connectionManager', 'appRouter', 'gl
}
}
function getShortcutAttributesHtml(item, serverId) {
export function getShortcutAttributesHtml(item, serverId) {
var html = 'data-id="' + item.Id + '" data-serverid="' + (serverId || item.ServerId) + '" data-type="' + item.Type + '" data-mediatype="' + item.MediaType + '" data-channelid="' + item.ChannelId + '" data-isfolder="' + item.IsFolder + '"';
let html = `data-id="${item.Id}" data-serverid="${serverId || item.ServerId}" data-type="${item.Type}" data-mediatype="${item.MediaType}" data-channelid="${item.ChannelId}" data-isfolder="${item.IsFolder}"`;
var collectionType = item.CollectionType;
const collectionType = item.CollectionType;
if (collectionType) {
html += ' data-collectiontype="' + collectionType + '"';
html += ` data-collectiontype="${collectionType}"`;
}
return html;
}
return {
/* eslint-enable indent */
export default {
on: on,
off: off,
onClick: onClick,
getShortcutAttributesHtml: getShortcutAttributesHtml
};
};
});

View file

@ -84,7 +84,7 @@ define(['apphost', 'userSettings', 'browser', 'events', 'backdrop', 'globalize',
currentSound = null;
}
backdrop.clear();
backdrop.clearBackdrop();
}
function onThemeLoaded() {

View file

@ -2,9 +2,20 @@
* Image viewer component
* @module components/slideshow/slideshow
*/
define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'focusManager', 'browser', 'apphost', 'css!./style', 'material-icons', 'paper-icon-button-light'], function (dialogHelper, inputManager, connectionManager, layoutManager, focusManager, browser, appHost) {
define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'focusManager', 'browser', 'apphost', 'dom', 'css!./style', 'material-icons', 'paper-icon-button-light'], function (dialogHelper, inputManager, connectionManager, layoutManager, focusManager, browser, appHost, dom) {
'use strict';
/**
* Name of transition event.
*/
const transitionEndEventName = dom.whichTransitionEvent();
/**
* Flag to use fake image to fix blurry zoomed image.
* At least WebKit doesn't restore quality for zoomed images.
*/
const useFakeZoomImage = browser.safari;
/**
* Retrieves an item's image URL from the API.
* @param {object|string} item - Item used to generate the image URL.
@ -240,6 +251,41 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f
}
}
/**
* Handles zoom changes.
*/
function onZoomChange(scale, imageEl, slideEl) {
const zoomImage = slideEl.querySelector('.swiper-zoom-fakeimg');
if (zoomImage) {
zoomImage.style.width = zoomImage.style.height = scale * 100 + '%';
if (scale > 1) {
if (zoomImage.classList.contains('swiper-zoom-fakeimg-hidden')) {
// Await for Swiper style changes
setTimeout(() => {
const callback = () => {
imageEl.removeEventListener(transitionEndEventName, callback);
zoomImage.classList.remove('swiper-zoom-fakeimg-hidden');
};
// Swiper set 'transition-duration: 300ms' for auto zoom
// and 'transition-duration: 0s' for touch zoom
const transitionDuration = parseFloat(imageEl.style.transitionDuration.replace(/[a-z]/i, ''));
if (transitionDuration > 0) {
imageEl.addEventListener(transitionEndEventName, callback);
} else {
callback();
}
}, 0);
}
} else {
zoomImage.classList.add('swiper-zoom-fakeimg-hidden');
}
}
}
/**
* Initializes the Swiper instance and binds the relevant events.
* @param {HTMLElement} dialog - Element containing the dialog.
@ -260,8 +306,7 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f
loop: false,
zoom: {
minRatio: 1,
toggle: true,
containerClass: 'slider-zoom-container'
toggle: true
},
autoplay: !options.interactive,
keyboard: {
@ -288,6 +333,10 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f
swiperInstance.on('autoplayStart', onAutoplayStart);
swiperInstance.on('autoplayStop', onAutoplayStop);
if (useFakeZoomImage) {
swiperInstance.on('zoomChange', onZoomChange);
}
});
}
@ -328,7 +377,10 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f
function getSwiperSlideHtmlFromSlide(item) {
var html = '';
html += '<div class="swiper-slide" data-original="' + item.originalImage + '" data-itemid="' + item.Id + '" data-serverid="' + item.ServerId + '">';
html += '<div class="slider-zoom-container">';
html += '<div class="swiper-zoom-container">';
if (useFakeZoomImage) {
html += `<div class="swiper-zoom-fakeimg swiper-zoom-fakeimg-hidden" style="background-image: url('${item.originalImage}')"></div>`;
}
html += '<img src="' + item.originalImage + '" class="swiper-slide-img">';
html += '</div>';
if (item.title || item.subtitle) {

View file

@ -40,16 +40,6 @@
text-shadow: 3px 3px 0 #000, -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
}
.swiper-slide-img {
max-height: 100%;
max-width: 100%;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
margin: auto;
}
.slideshowButtonIcon {
color: #fff;
opacity: 0.7;
@ -135,13 +125,18 @@
color: #ccc;
}
.swiper-slide {
display: flex;
flex-direction: column;
.swiper-zoom-fakeimg {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-position: 50% 50%;
background-repeat: no-repeat;
background-size: contain;
z-index: 1;
pointer-events: none;
}
.slider-zoom-container {
margin: auto;
max-height: 100%;
max-width: 100%;
.swiper-zoom-fakeimg-hidden {
display: none;
}

View file

@ -73,7 +73,7 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'layoutMana
html += template;
dlg.innerHTML = globalize.translateDocument(html, 'core');
dlg.innerHTML = globalize.translateHtml(html, 'core');
fillSortBy(dlg, options.sortOptions);
initEditor(dlg, options.settings);

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