mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Merge branch 'es6' into es6-shortcuts
This commit is contained in:
commit
ed3a820c21
166 changed files with 6500 additions and 3182 deletions
63
.ci/azure-pipelines-build.yml
Normal file
63
.ci/azure-pipelines-build.yml
Normal 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)'
|
29
.ci/azure-pipelines-lint.yml
Normal file
29
.ci/azure-pipelines-lint.yml
Normal 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'
|
106
.ci/azure-pipelines-package.yml
Normal file
106
.ci/azure-pipelines-package.yml
Normal 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)'
|
|
@ -12,88 +12,6 @@ pr:
|
||||||
- '*'
|
- '*'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
- job: Build
|
- template: azure-pipelines-build.yml
|
||||||
displayName: 'Build'
|
- template: azure-pipelines-lint.yml
|
||||||
|
- template: azure-pipelines-package.yml
|
||||||
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'
|
|
||||||
|
|
|
@ -132,6 +132,7 @@ module.exports = {
|
||||||
'Object.getOwnPropertyDescriptor',
|
'Object.getOwnPropertyDescriptor',
|
||||||
'Object.getPrototypeOf',
|
'Object.getPrototypeOf',
|
||||||
'Object.keys',
|
'Object.keys',
|
||||||
|
'Object.entries',
|
||||||
'Object.getOwnPropertyNames',
|
'Object.getOwnPropertyNames',
|
||||||
'Function.name',
|
'Function.name',
|
||||||
'Function.hasInstance',
|
'Function.hasInstance',
|
||||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,6 +1,3 @@
|
||||||
# config
|
|
||||||
config.json
|
|
||||||
|
|
||||||
# npm
|
# npm
|
||||||
dist
|
dist
|
||||||
web
|
web
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
FROM centos:7
|
FROM centos:7
|
||||||
|
|
||||||
# Docker build arguments
|
# Docker build arguments
|
||||||
ARG SOURCE_DIR=/jellyfin
|
ARG SOURCE_DIR=/jellyfin
|
||||||
ARG ARTIFACT_DIR=/dist
|
ARG ARTIFACT_DIR=/dist
|
||||||
|
|
||||||
# Docker run environment
|
# Docker run environment
|
||||||
ENV SOURCE_DIR=/jellyfin
|
ENV SOURCE_DIR=/jellyfin
|
||||||
ENV ARTIFACT_DIR=/dist
|
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
|
&& yum install -y yarn
|
||||||
|
|
||||||
# Link to build script
|
# 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"]
|
ENTRYPOINT ["/build.sh"]
|
|
@ -1,7 +1,9 @@
|
||||||
FROM debian:10
|
FROM debian:10
|
||||||
|
|
||||||
# Docker build arguments
|
# Docker build arguments
|
||||||
ARG SOURCE_DIR=/jellyfin
|
ARG SOURCE_DIR=/jellyfin
|
||||||
ARG ARTIFACT_DIR=/dist
|
ARG ARTIFACT_DIR=/dist
|
||||||
|
|
||||||
# Docker run environment
|
# Docker run environment
|
||||||
ENV SOURCE_DIR=/jellyfin
|
ENV SOURCE_DIR=/jellyfin
|
||||||
ENV ARTIFACT_DIR=/dist
|
ENV ARTIFACT_DIR=/dist
|
||||||
|
@ -16,10 +18,10 @@ RUN apt-get update \
|
||||||
RUN npm install -g yarn
|
RUN npm install -g yarn
|
||||||
|
|
||||||
# Link to build script
|
# 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"]
|
ENTRYPOINT ["/build.sh"]
|
11
deployment/Dockerfile.docker
Normal file
11
deployment/Dockerfile.docker
Normal 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}
|
|
@ -1,7 +1,9 @@
|
||||||
FROM fedora:31
|
FROM fedora:31
|
||||||
|
|
||||||
# Docker build arguments
|
# Docker build arguments
|
||||||
ARG SOURCE_DIR=/jellyfin
|
ARG SOURCE_DIR=/jellyfin
|
||||||
ARG ARTIFACT_DIR=/dist
|
ARG ARTIFACT_DIR=/dist
|
||||||
|
|
||||||
# Docker run environment
|
# Docker run environment
|
||||||
ENV SOURCE_DIR=/jellyfin
|
ENV SOURCE_DIR=/jellyfin
|
||||||
ENV ARTIFACT_DIR=/dist
|
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
|
&& dnf install -y @buildsys-build rpmdevtools git dnf-plugins-core nodejs-yarn autoconf automake glibc-devel
|
||||||
|
|
||||||
# Link to build script
|
# 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"]
|
ENTRYPOINT ["/build.sh"]
|
|
@ -1,11 +1,12 @@
|
||||||
FROM debian:10
|
FROM debian:10
|
||||||
|
|
||||||
# Docker build arguments
|
# Docker build arguments
|
||||||
ARG SOURCE_DIR=/jellyfin
|
ARG SOURCE_DIR=/jellyfin
|
||||||
ARG ARTIFACT_DIR=/dist
|
ARG ARTIFACT_DIR=/dist
|
||||||
|
|
||||||
# Docker run environment
|
# Docker run environment
|
||||||
ENV SOURCE_DIR=/jellyfin
|
ENV SOURCE_DIR=/jellyfin
|
||||||
ENV ARTIFACT_DIR=/dist
|
ENV ARTIFACT_DIR=/dist
|
||||||
ENV DEB_BUILD_OPTIONS=noddebs
|
|
||||||
ENV IS_DOCKER=YES
|
ENV IS_DOCKER=YES
|
||||||
|
|
||||||
# Prepare Debian build environment
|
# Prepare Debian build environment
|
||||||
|
@ -18,8 +19,8 @@ RUN npm install -g yarn
|
||||||
# Link to build script
|
# Link to build script
|
||||||
RUN ln -sf ${SOURCE_DIR}/deployment/build.portable /build.sh
|
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"]
|
ENTRYPOINT ["/build.sh"]
|
||||||
|
|
41
deployment/build.centos
Executable file
41
deployment/build.centos
Executable 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
|
|
@ -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
39
deployment/build.debian
Executable 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
|
|
@ -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
41
deployment/build.fedora
Executable 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
|
|
@ -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
|
|
|
@ -1,25 +1,27 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
#= Portable .NET DLL .tar.gz
|
|
||||||
|
|
||||||
set -o errexit
|
set -o errexit
|
||||||
set -o xtrace
|
set -o xtrace
|
||||||
|
|
||||||
# Move to source directory
|
# move to source directory
|
||||||
pushd ${SOURCE_DIR}
|
pushd ${SOURCE_DIR}
|
||||||
|
|
||||||
# Get version
|
# get version
|
||||||
|
if [[ ${IS_UNSTABLE} == 'yes' ]]; then
|
||||||
|
version="${BUILD_ID}"
|
||||||
|
else
|
||||||
version="$( grep "version:" ./build.yaml | sed -E 's/version: "([0-9\.]+.*)"/\1/' )"
|
version="$( grep "version:" ./build.yaml | sed -E 's/version: "([0-9\.]+.*)"/\1/' )"
|
||||||
|
fi
|
||||||
|
|
||||||
# Build archives
|
# build archives
|
||||||
npx yarn install
|
npx yarn install
|
||||||
mv dist/ jellyfin-web_${version}
|
mv dist jellyfin-web_${version}
|
||||||
tar -czf jellyfin-web_${version}_portable.tar.gz jellyfin-web_${version}
|
tar -czf jellyfin-web_${version}_portable.tar.gz jellyfin-web_${version}
|
||||||
rm -rf dist/
|
rm -rf dist
|
||||||
|
|
||||||
# Move the artifacts out
|
# move the artifacts
|
||||||
mkdir -p ${ARTIFACT_DIR}/
|
mkdir -p ${ARTIFACT_DIR}
|
||||||
mv jellyfin[-_]*.tar.gz ${ARTIFACT_DIR}/
|
mv jellyfin[-_]*.tar.gz ${ARTIFACT_DIR}
|
||||||
|
|
||||||
if [[ ${IS_DOCKER} == YES ]]; then
|
if [[ ${IS_DOCKER} == YES ]]; then
|
||||||
chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
|
chown -Rc $(stat -c %u:%g ${ARTIFACT_DIR}) ${ARTIFACT_DIR}
|
||||||
|
|
|
@ -12,7 +12,7 @@ Source0: jellyfin-web-%{version}.tar.gz
|
||||||
%if 0%{?centos}
|
%if 0%{?centos}
|
||||||
BuildRequires: yarn
|
BuildRequires: yarn
|
||||||
%else
|
%else
|
||||||
BuildRequires nodejs-yarn
|
BuildRequires: nodejs-yarn
|
||||||
%endif
|
%endif
|
||||||
BuildArch: noarch
|
BuildArch: noarch
|
||||||
|
|
||||||
|
|
22
gulpfile.js
22
gulpfile.js
|
@ -16,6 +16,7 @@ const stream = require('webpack-stream');
|
||||||
const inject = require('gulp-inject');
|
const inject = require('gulp-inject');
|
||||||
const postcss = require('gulp-postcss');
|
const postcss = require('gulp-postcss');
|
||||||
const sass = require('gulp-sass');
|
const sass = require('gulp-sass');
|
||||||
|
const gulpif = require('gulp-if');
|
||||||
const lazypipe = require('lazypipe');
|
const lazypipe = require('lazypipe');
|
||||||
|
|
||||||
sass.compiler = require('node-sass');
|
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);
|
watch('src/bundle.js', webpack);
|
||||||
|
|
||||||
|
@ -130,14 +131,20 @@ function javascript(query) {
|
||||||
.pipe(browserSync.stream());
|
.pipe(browserSync.stream());
|
||||||
}
|
}
|
||||||
|
|
||||||
function apploader() {
|
function apploader(standalone) {
|
||||||
|
function task() {
|
||||||
return src(options.apploader.query, { base: './src/' })
|
return src(options.apploader.query, { base: './src/' })
|
||||||
.pipe(concat('scripts/apploader.js'))
|
.pipe(gulpif(standalone, concat('scripts/apploader.js')))
|
||||||
.pipe(pipelineJavascript())
|
.pipe(pipelineJavascript())
|
||||||
.pipe(dest('dist/'))
|
.pipe(dest('dist/'))
|
||||||
.pipe(browserSync.stream());
|
.pipe(browserSync.stream());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task.displayName = 'apploader';
|
||||||
|
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
function webpack() {
|
function webpack() {
|
||||||
return stream(config)
|
return stream(config)
|
||||||
.pipe(dest('dist/'))
|
.pipe(dest('dist/'))
|
||||||
|
@ -183,5 +190,10 @@ function injectBundle() {
|
||||||
.pipe(browserSync.stream());
|
.pipe(browserSync.stream());
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.default = series(clean, parallel(javascript, apploader, webpack, css, html, images, copy), injectBundle);
|
function build(standalone) {
|
||||||
exports.serve = series(exports.default, serve);
|
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);
|
||||||
|
|
55
package.json
55
package.json
|
@ -5,29 +5,29 @@
|
||||||
"repository": "https://github.com/jellyfin/jellyfin-web",
|
"repository": "https://github.com/jellyfin/jellyfin-web",
|
||||||
"license": "GPL-2.0-or-later",
|
"license": "GPL-2.0-or-later",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.10.2",
|
"@babel/core": "^7.10.3",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.10.1",
|
"@babel/plugin-proposal-class-properties": "^7.10.1",
|
||||||
"@babel/plugin-proposal-private-methods": "^7.10.1",
|
"@babel/plugin-proposal-private-methods": "^7.10.1",
|
||||||
"@babel/plugin-transform-modules-amd": "^7.9.6",
|
"@babel/plugin-transform-modules-amd": "^7.9.6",
|
||||||
"@babel/polyfill": "^7.8.7",
|
"@babel/polyfill": "^7.8.7",
|
||||||
"@babel/preset-env": "^7.10.2",
|
"@babel/preset-env": "^7.10.3",
|
||||||
"autoprefixer": "^9.8.0",
|
"autoprefixer": "^9.8.2",
|
||||||
"babel-eslint": "^11.0.0-beta.2",
|
"babel-eslint": "^11.0.0-beta.2",
|
||||||
"babel-loader": "^8.0.6",
|
"babel-loader": "^8.0.6",
|
||||||
"browser-sync": "^2.26.7",
|
"browser-sync": "^2.26.7",
|
||||||
"copy-webpack-plugin": "^5.1.1",
|
"copy-webpack-plugin": "^5.1.1",
|
||||||
"css-loader": "^3.4.2",
|
"css-loader": "^3.6.0",
|
||||||
"cssnano": "^4.1.10",
|
"cssnano": "^4.1.10",
|
||||||
"del": "^5.1.0",
|
"del": "^5.1.0",
|
||||||
"eslint": "^6.8.0",
|
"eslint": "^6.8.0",
|
||||||
"eslint-plugin-compat": "^3.5.1",
|
"eslint-plugin-compat": "^3.5.1",
|
||||||
"eslint-plugin-eslint-comments": "^3.2.0",
|
"eslint-plugin-eslint-comments": "^3.2.0",
|
||||||
"eslint-plugin-import": "^2.20.2",
|
"eslint-plugin-import": "^2.21.2",
|
||||||
"eslint-plugin-promise": "^4.2.1",
|
"eslint-plugin-promise": "^4.2.1",
|
||||||
"file-loader": "^6.0.0",
|
"file-loader": "^6.0.0",
|
||||||
"gulp": "^4.0.2",
|
"gulp": "^4.0.2",
|
||||||
"gulp-babel": "^8.0.0",
|
"gulp-babel": "^8.0.0",
|
||||||
"gulp-cli": "^2.2.1",
|
"gulp-cli": "^2.3.0",
|
||||||
"gulp-concat": "^2.6.1",
|
"gulp-concat": "^2.6.1",
|
||||||
"gulp-htmlmin": "^5.0.1",
|
"gulp-htmlmin": "^5.0.1",
|
||||||
"gulp-if": "^3.0.0",
|
"gulp-if": "^3.0.0",
|
||||||
|
@ -44,41 +44,42 @@
|
||||||
"postcss-loader": "^3.0.0",
|
"postcss-loader": "^3.0.0",
|
||||||
"postcss-preset-env": "^6.7.0",
|
"postcss-preset-env": "^6.7.0",
|
||||||
"style-loader": "^1.1.3",
|
"style-loader": "^1.1.3",
|
||||||
"stylelint": "^13.5.0",
|
"stylelint": "^13.6.1",
|
||||||
"stylelint-config-rational-order": "^0.1.2",
|
"stylelint-config-rational-order": "^0.1.2",
|
||||||
"stylelint-no-browser-hacks": "^1.2.1",
|
"stylelint-no-browser-hacks": "^1.2.1",
|
||||||
"stylelint-order": "^4.0.0",
|
"stylelint-order": "^4.1.0",
|
||||||
"webpack": "^4.41.5",
|
"webpack": "^4.41.5",
|
||||||
"webpack-merge": "^4.2.2",
|
"webpack-merge": "^4.2.2",
|
||||||
"webpack-stream": "^5.2.1"
|
"webpack-stream": "^5.2.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"alameda": "^1.4.0",
|
"alameda": "^1.4.0",
|
||||||
|
"blurhash": "^1.1.3",
|
||||||
"classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz",
|
"classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz",
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
"date-fns": "^2.14.0",
|
"date-fns": "^2.14.0",
|
||||||
"document-register-element": "^1.14.3",
|
"document-register-element": "^1.14.3",
|
||||||
"epubjs": "^0.3.85",
|
"epubjs": "^0.3.85",
|
||||||
"fast-text-encoding": "^1.0.1",
|
"fast-text-encoding": "^1.0.3",
|
||||||
"flv.js": "^1.5.0",
|
"flv.js": "^1.5.0",
|
||||||
"headroom.js": "^0.11.0",
|
"headroom.js": "^0.11.0",
|
||||||
"hls.js": "^0.13.1",
|
"hls.js": "^0.13.1",
|
||||||
"howler": "^2.2.0",
|
"howler": "^2.2.0",
|
||||||
"intersection-observer": "^0.10.0",
|
"intersection-observer": "^0.10.0",
|
||||||
"jellyfin-apiclient": "^1.2.0",
|
"jellyfin-apiclient": "^1.2.2",
|
||||||
"jellyfin-noto": "https://github.com/jellyfin/jellyfin-noto",
|
"jellyfin-noto": "https://github.com/jellyfin/jellyfin-noto",
|
||||||
"jquery": "^3.5.1",
|
"jquery": "^3.5.1",
|
||||||
"jstree": "^3.3.7",
|
"jstree": "^3.3.10",
|
||||||
"libass-wasm": "https://github.com/jellyfin/JavascriptSubtitlesOctopus#4.0.0-jf-smarttv",
|
"libass-wasm": "https://github.com/jellyfin/JavascriptSubtitlesOctopus#4.0.0-jf-smarttv",
|
||||||
"material-design-icons-iconfont": "^5.0.1",
|
"material-design-icons-iconfont": "^5.0.1",
|
||||||
"native-promise-only": "^0.8.0-a",
|
"native-promise-only": "^0.8.0-a",
|
||||||
"page": "^1.11.6",
|
"page": "^1.11.6",
|
||||||
"query-string": "^6.11.1",
|
"query-string": "^6.13.1",
|
||||||
"resize-observer-polyfill": "^1.5.1",
|
"resize-observer-polyfill": "^1.5.1",
|
||||||
"screenfull": "^5.0.2",
|
"screenfull": "^5.0.2",
|
||||||
"shaka-player": "^2.5.12",
|
"shaka-player": "^3.0.1",
|
||||||
"sortablejs": "^1.10.2",
|
"sortablejs": "^1.10.2",
|
||||||
"swiper": "^5.4.1",
|
"swiper": "^5.4.5",
|
||||||
"webcomponents.js": "^0.7.24",
|
"webcomponents.js": "^0.7.24",
|
||||||
"whatwg-fetch": "^3.0.0"
|
"whatwg-fetch": "^3.0.0"
|
||||||
},
|
},
|
||||||
|
@ -89,24 +90,36 @@
|
||||||
"overrides": [
|
"overrides": [
|
||||||
{
|
{
|
||||||
"test": [
|
"test": [
|
||||||
|
"src/components/accessSchedule/accessSchedule.js",
|
||||||
"src/components/actionSheet/actionSheet.js",
|
"src/components/actionSheet/actionSheet.js",
|
||||||
"src/components/autoFocuser.js",
|
"src/components/autoFocuser.js",
|
||||||
"src/components/cardbuilder/cardBuilder.js",
|
"src/components/cardbuilder/cardBuilder.js",
|
||||||
|
"src/components/cardbuilder/chaptercardbuilder.js",
|
||||||
|
"src/components/cardbuilder/peoplecardbuilder.js",
|
||||||
"src/components/images/imageLoader.js",
|
"src/components/images/imageLoader.js",
|
||||||
"src/components/indicators/indicators.js",
|
"src/components/indicators/indicators.js",
|
||||||
"src/components/lazyLoader/lazyLoaderIntersectionObserver.js",
|
"src/components/lazyLoader/lazyLoaderIntersectionObserver.js",
|
||||||
|
"src/components/playback/brightnessosd.js",
|
||||||
"src/components/playback/mediasession.js",
|
"src/components/playback/mediasession.js",
|
||||||
|
"src/components/playback/nowplayinghelper.js",
|
||||||
|
"src/components/playback/playbackorientation.js",
|
||||||
|
"src/components/playback/playerSelectionMenu.js",
|
||||||
|
"src/components/playback/playersettingsmenu.js",
|
||||||
|
"src/components/playback/playmethodhelper.js",
|
||||||
"src/components/playback/remotecontrolautoplay.js",
|
"src/components/playback/remotecontrolautoplay.js",
|
||||||
|
"src/components/playback/volumeosd.js",
|
||||||
"src/components/playmenu.js",
|
"src/components/playmenu.js",
|
||||||
"src/components/sanatizefilename.js",
|
"src/components/sanatizefilename.js",
|
||||||
"src/components/scrollManager.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/shortcuts.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/dashboard/logs.js",
|
||||||
|
"src/controllers/dashboard/plugins/repositories.js",
|
||||||
"src/plugins/bookPlayer/plugin.js",
|
"src/plugins/bookPlayer/plugin.js",
|
||||||
"src/plugins/bookPlayer/tableOfContent.js",
|
"src/plugins/bookPlayer/tableOfContents.js",
|
||||||
"src/plugins/photoPlayer/plugin.js",
|
"src/plugins/photoPlayer/plugin.js",
|
||||||
"src/scripts/deleteHelper.js",
|
"src/scripts/deleteHelper.js",
|
||||||
"src/scripts/dfnshelper.js",
|
"src/scripts/dfnshelper.js",
|
||||||
|
@ -115,6 +128,9 @@
|
||||||
"src/scripts/filesystem.js",
|
"src/scripts/filesystem.js",
|
||||||
"src/scripts/imagehelper.js",
|
"src/scripts/imagehelper.js",
|
||||||
"src/scripts/inputManager.js",
|
"src/scripts/inputManager.js",
|
||||||
|
"src/plugins/backdropScreensaver/plugin.js",
|
||||||
|
"src/components/filterdialog/filterdialog.js",
|
||||||
|
"src/components/fetchhelper.js",
|
||||||
"src/scripts/keyboardNavigation.js",
|
"src/scripts/keyboardNavigation.js",
|
||||||
"src/scripts/settings/appSettings.js",
|
"src/scripts/settings/appSettings.js",
|
||||||
"src/scripts/settings/userSettings.js",
|
"src/scripts/settings/userSettings.js",
|
||||||
|
@ -148,6 +164,7 @@
|
||||||
"prepare": "gulp --production",
|
"prepare": "gulp --production",
|
||||||
"build:development": "gulp --development",
|
"build:development": "gulp --development",
|
||||||
"build:production": "gulp --production",
|
"build:production": "gulp --production",
|
||||||
|
"build:standalone": "gulp standalone --development",
|
||||||
"lint": "eslint \".\"",
|
"lint": "eslint \".\"",
|
||||||
"stylelint": "stylelint \"src/**/*.css\""
|
"stylelint": "stylelint \"src/**/*.css\""
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<div data-role="page" class="page standalonePage">
|
<div data-role="page" class="page standalonePage">
|
||||||
<div class="padded-left padded-right padded-bottom-page">
|
<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>
|
<h1>${HeaderConnectToServer}</h1>
|
||||||
<div class="inputContainer">
|
<div class="inputContainer">
|
||||||
<input is="emby-input" type="url" id="txtServerHost" required="required" label="${LabelServerHost}"/>
|
<input is="emby-input" type="url" id="txtServerHost" required="required" label="${LabelServerHost}"/>
|
||||||
|
|
|
@ -597,6 +597,7 @@
|
||||||
.detailImageContainer {
|
.detailImageContainer {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-top: -25vh;
|
margin-top: -25vh;
|
||||||
|
margin-bottom: 10vh;
|
||||||
float: left;
|
float: left;
|
||||||
width: 25vw;
|
width: 25vw;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
|
@ -641,7 +642,8 @@ div.itemDetailGalleryLink.defaultCardBackground {
|
||||||
}
|
}
|
||||||
|
|
||||||
.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 {
|
.itemDetailGalleryLink.defaultCardBackground > .material-icons {
|
||||||
|
@ -797,9 +799,9 @@ div.itemDetailGalleryLink.defaultCardBackground {
|
||||||
}
|
}
|
||||||
|
|
||||||
.detailImageProgressContainer {
|
.detailImageProgressContainer {
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 22.786458333333332vw;
|
margin-top: -0.4vw;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detailButton-text {
|
.detailButton-text {
|
||||||
|
|
|
@ -121,6 +121,11 @@ div[data-role=page] {
|
||||||
transform: translateY(-100%);
|
transform: translateY(-100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.drawerContent {
|
||||||
|
/* make sure the bottom of the drawer is visible when music is playing */
|
||||||
|
padding-bottom: 4em;
|
||||||
|
}
|
||||||
|
|
||||||
.force-scroll {
|
.force-scroll {
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,12 @@ _define('fetch', function() {
|
||||||
return fetch;
|
return fetch;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Blurhash
|
||||||
|
var blurhash = require('blurhash');
|
||||||
|
_define('blurhash', function() {
|
||||||
|
return blurhash;
|
||||||
|
});
|
||||||
|
|
||||||
// query-string
|
// query-string
|
||||||
var query = require('query-string');
|
var query = require('query-string');
|
||||||
_define('queryString', function() {
|
_define('queryString', function() {
|
||||||
|
|
|
@ -1,9 +1,20 @@
|
||||||
define(['dialogHelper', 'datetime', 'globalize', 'emby-select', 'paper-icon-button-light', 'formDialogStyle'], function (dialogHelper, datetime, globalize) {
|
/* eslint-disable indent */
|
||||||
'use strict';
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
function getDisplayTime(hours) {
|
||||||
var minutes = 0;
|
let minutes = 0;
|
||||||
var pct = hours % 1;
|
const pct = hours % 1;
|
||||||
|
|
||||||
if (pct) {
|
if (pct) {
|
||||||
minutes = parseInt(60 * pct);
|
minutes = parseInt(60 * pct);
|
||||||
|
@ -13,25 +24,25 @@ define(['dialogHelper', 'datetime', 'globalize', 'emby-select', 'paper-icon-butt
|
||||||
}
|
}
|
||||||
|
|
||||||
function populateHours(context) {
|
function populateHours(context) {
|
||||||
var html = '';
|
let html = '';
|
||||||
|
|
||||||
for (var i = 0; i < 24; i++) {
|
for (let i = 0; i < 24; i++) {
|
||||||
html += '<option value="' + i + '">' + getDisplayTime(i) + '</option>';
|
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('#selectStart').innerHTML = html;
|
||||||
context.querySelector('#selectEnd').innerHTML = html;
|
context.querySelector('#selectEnd').innerHTML = html;
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadSchedule(context, schedule) {
|
function loadSchedule(context, {DayOfWeek, StartHour, EndHour}) {
|
||||||
context.querySelector('#selectDay').value = schedule.DayOfWeek || 'Sunday';
|
context.querySelector('#selectDay').value = DayOfWeek || 'Sunday';
|
||||||
context.querySelector('#selectStart').value = schedule.StartHour || 0;
|
context.querySelector('#selectStart').value = StartHour || 0;
|
||||||
context.querySelector('#selectEnd').value = schedule.EndHour || 0;
|
context.querySelector('#selectEnd').value = EndHour || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function submitSchedule(context, options) {
|
function submitSchedule(context, options) {
|
||||||
var updatedSchedule = {
|
const updatedSchedule = {
|
||||||
DayOfWeek: context.querySelector('#selectDay').value,
|
DayOfWeek: context.querySelector('#selectDay').value,
|
||||||
StartHour: context.querySelector('#selectStart').value,
|
StartHour: context.querySelector('#selectStart').value,
|
||||||
EndHour: context.querySelector('#selectEnd').value
|
EndHour: context.querySelector('#selectEnd').value
|
||||||
|
@ -46,44 +57,42 @@ define(['dialogHelper', 'datetime', 'globalize', 'emby-select', 'paper-icon-butt
|
||||||
dialogHelper.close(context);
|
dialogHelper.close(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
export function show(options) {
|
||||||
show: function (options) {
|
return new Promise((resolve, reject) => {
|
||||||
return new Promise(function (resolve, reject) {
|
// TODO: remove require
|
||||||
var xhr = new XMLHttpRequest();
|
require(['text!./components/accessSchedule/accessSchedule.template.html'], template => {
|
||||||
xhr.open('GET', 'components/accessSchedule/accessSchedule.template.html', true);
|
const dlg = dialogHelper.createDialog({
|
||||||
|
|
||||||
xhr.onload = function (e) {
|
|
||||||
var template = this.response;
|
|
||||||
var dlg = dialogHelper.createDialog({
|
|
||||||
removeOnClose: true,
|
removeOnClose: true,
|
||||||
size: 'small'
|
size: 'small'
|
||||||
});
|
});
|
||||||
dlg.classList.add('formDialog');
|
dlg.classList.add('formDialog');
|
||||||
var html = '';
|
let html = '';
|
||||||
html += globalize.translateDocument(template);
|
html += globalize.translateDocument(template);
|
||||||
dlg.innerHTML = html;
|
dlg.innerHTML = html;
|
||||||
populateHours(dlg);
|
populateHours(dlg);
|
||||||
loadSchedule(dlg, options.schedule);
|
loadSchedule(dlg, options.schedule);
|
||||||
dialogHelper.open(dlg);
|
dialogHelper.open(dlg);
|
||||||
dlg.addEventListener('close', function () {
|
dlg.addEventListener('close', () => {
|
||||||
if (dlg.submitted) {
|
if (dlg.submitted) {
|
||||||
resolve(options.schedule);
|
resolve(options.schedule);
|
||||||
} else {
|
} else {
|
||||||
reject();
|
reject();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
dlg.querySelector('.btnCancel').addEventListener('click', function () {
|
dlg.querySelector('.btnCancel').addEventListener('click', () => {
|
||||||
dialogHelper.close(dlg);
|
dialogHelper.close(dlg);
|
||||||
});
|
});
|
||||||
dlg.querySelector('form').addEventListener('submit', function (event) {
|
dlg.querySelector('form').addEventListener('submit', event => {
|
||||||
submitSchedule(dlg, options);
|
submitSchedule(dlg, options);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
|
|
||||||
xhr.send();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* eslint-enable indent */
|
||||||
|
|
||||||
|
export default {
|
||||||
|
show: show
|
||||||
};
|
};
|
||||||
});
|
|
||||||
|
|
|
@ -192,9 +192,14 @@ button::-moz-focus-inner {
|
||||||
|
|
||||||
/* Needed in case this is a button */
|
/* Needed in case this is a button */
|
||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
/* Needed in case this is a button */
|
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
|
border: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
cursor: pointer;
|
||||||
|
color: inherit;
|
||||||
|
width: 100%;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
|
||||||
/* Needed in safari */
|
/* Needed in safari */
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -203,19 +208,12 @@ button::-moz-focus-inner {
|
||||||
contain: strict;
|
contain: strict;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardContent-button {
|
.cardContent:not(.defaultCardBackground) {
|
||||||
border: 0 !important;
|
background-color: transparent;
|
||||||
padding: 0 !important;
|
|
||||||
cursor: pointer;
|
|
||||||
color: inherit;
|
|
||||||
width: 100%;
|
|
||||||
vertical-align: middle;
|
|
||||||
font-family: inherit;
|
|
||||||
font-size: inherit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardContent-button:not(.defaultCardBackground) {
|
.cardBox:not(.visualCardBox) .cardPadder {
|
||||||
background-color: transparent;
|
background-color: #242424;
|
||||||
}
|
}
|
||||||
|
|
||||||
.visualCardBox .cardContent {
|
.visualCardBox .cardContent {
|
||||||
|
@ -223,7 +221,8 @@ button::-moz-focus-inner {
|
||||||
border-bottom-right-radius: 0;
|
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);
|
box-shadow: 0 0.0725em 0.29em 0 rgba(0, 0, 0, 0.37);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -368,9 +368,7 @@ import 'programStyles';
|
||||||
let apiClient;
|
let apiClient;
|
||||||
let lastServerId;
|
let lastServerId;
|
||||||
|
|
||||||
for (let i = 0; i < items.length; i++) {
|
for (const [i, item] of items.entries()) {
|
||||||
|
|
||||||
let item = items[i];
|
|
||||||
let serverId = item.ServerId || options.serverId;
|
let serverId = item.ServerId || options.serverId;
|
||||||
|
|
||||||
if (serverId !== lastServerId) {
|
if (serverId !== lastServerId) {
|
||||||
|
@ -503,94 +501,49 @@ import 'programStyles';
|
||||||
const primaryImageAspectRatio = item.PrimaryImageAspectRatio;
|
const primaryImageAspectRatio = item.PrimaryImageAspectRatio;
|
||||||
let forceName = false;
|
let forceName = false;
|
||||||
let imgUrl = null;
|
let imgUrl = null;
|
||||||
|
let imgTag = null;
|
||||||
let coverImage = false;
|
let coverImage = false;
|
||||||
let uiAspect = null;
|
let uiAspect = null;
|
||||||
|
let imgType = null;
|
||||||
|
let itemId = null;
|
||||||
|
|
||||||
if (options.preferThumb && item.ImageTags && item.ImageTags.Thumb) {
|
if (options.preferThumb && item.ImageTags && item.ImageTags.Thumb) {
|
||||||
|
imgType = 'Thumb';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.Id, {
|
imgTag = item.ImageTags.Thumb;
|
||||||
type: 'Thumb',
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ImageTags.Thumb
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if ((options.preferBanner || shape === 'banner') && item.ImageTags && item.ImageTags.Banner) {
|
} else if ((options.preferBanner || shape === 'banner') && item.ImageTags && item.ImageTags.Banner) {
|
||||||
|
imgType = 'Banner';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.Id, {
|
imgTag = item.ImageTags.Banner;
|
||||||
type: 'Banner',
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ImageTags.Banner
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (options.preferDisc && item.ImageTags && item.ImageTags.Disc) {
|
} else if (options.preferDisc && item.ImageTags && item.ImageTags.Disc) {
|
||||||
|
imgType = 'Disc';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.Id, {
|
imgTag = item.ImageTags.Disc;
|
||||||
type: 'Disc',
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ImageTags.Disc
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (options.preferLogo && item.ImageTags && item.ImageTags.Logo) {
|
} else if (options.preferLogo && item.ImageTags && item.ImageTags.Logo) {
|
||||||
|
imgType = 'Logo';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.Id, {
|
imgTag = item.ImageTags.Logo;
|
||||||
type: 'Logo',
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ImageTags.Logo
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (options.preferLogo && item.ParentLogoImageTag && item.ParentLogoItemId) {
|
} else if (options.preferLogo && item.ParentLogoImageTag && item.ParentLogoItemId) {
|
||||||
|
imgType = 'Logo';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.ParentLogoItemId, {
|
imgTag = item.ParentLogoImageTag;
|
||||||
type: 'Logo',
|
itemId = item.ParentLogoItemId;
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ParentLogoImageTag
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (options.preferThumb && item.SeriesThumbImageTag && options.inheritThumb !== false) {
|
} else if (options.preferThumb && item.SeriesThumbImageTag && options.inheritThumb !== false) {
|
||||||
|
imgType = 'Thumb';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.SeriesId, {
|
imgTag = item.SeriesThumbImageTag;
|
||||||
type: 'Thumb',
|
itemId = item.SeriesId;
|
||||||
maxWidth: width,
|
|
||||||
tag: item.SeriesThumbImageTag
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (options.preferThumb && item.ParentThumbItemId && options.inheritThumb !== false && item.MediaType !== 'Photo') {
|
} else if (options.preferThumb && item.ParentThumbItemId && options.inheritThumb !== false && item.MediaType !== 'Photo') {
|
||||||
|
imgType = 'Thumb';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.ParentThumbItemId, {
|
imgTag = item.ParentThumbImageTag;
|
||||||
type: 'Thumb',
|
itemId = item.ParentThumbItemId;
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ParentThumbImageTag
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (options.preferThumb && item.BackdropImageTags && item.BackdropImageTags.length) {
|
} else if (options.preferThumb && item.BackdropImageTags && item.BackdropImageTags.length) {
|
||||||
|
imgType = 'Backdrop';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.Id, {
|
imgTag = item.BackdropImageTags[0];
|
||||||
type: 'Backdrop',
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.BackdropImageTags[0]
|
|
||||||
});
|
|
||||||
|
|
||||||
forceName = true;
|
forceName = true;
|
||||||
|
|
||||||
} else if (options.preferThumb && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length && options.inheritThumb !== false && item.Type === 'Episode') {
|
} else if (options.preferThumb && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length && options.inheritThumb !== false && item.Type === 'Episode') {
|
||||||
|
imgType = 'Backdrop';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.ParentBackdropItemId, {
|
imgTag = item.ParentBackdropImageTags[0];
|
||||||
type: 'Backdrop',
|
itemId = item.ParentBackdropItemId;
|
||||||
maxWidth: width,
|
} else if (item.ImageTags && item.ImageTags.Primary && (item.Type !== 'Episode' || item.ChildCount !== 0)) {
|
||||||
tag: item.ParentBackdropImageTags[0]
|
imgType = 'Primary';
|
||||||
});
|
imgTag = item.ImageTags.Primary;
|
||||||
|
|
||||||
} else if (item.ImageTags && item.ImageTags.Primary) {
|
|
||||||
|
|
||||||
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
|
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
|
||||||
|
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.Id, {
|
|
||||||
type: 'Primary',
|
|
||||||
maxHeight: height,
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ImageTags.Primary
|
|
||||||
});
|
|
||||||
|
|
||||||
if (options.preferThumb && options.showTitle !== false) {
|
if (options.preferThumb && options.showTitle !== false) {
|
||||||
forceName = true;
|
forceName = true;
|
||||||
}
|
}
|
||||||
|
@ -601,18 +554,16 @@ import 'programStyles';
|
||||||
coverImage = (Math.abs(primaryImageAspectRatio - uiAspect) / uiAspect) <= 0.2;
|
coverImage = (Math.abs(primaryImageAspectRatio - uiAspect) / uiAspect) <= 0.2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (item.SeriesPrimaryImageTag) {
|
||||||
|
imgType = 'Primary';
|
||||||
|
imgTag = item.SeriesPrimaryImageTag;
|
||||||
|
itemId = item.SeriesId;
|
||||||
} else if (item.PrimaryImageTag) {
|
} else if (item.PrimaryImageTag) {
|
||||||
|
imgType = 'Primary';
|
||||||
|
imgTag = item.PrimaryImageTag;
|
||||||
|
itemId = item.PrimaryImageItemId;
|
||||||
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
|
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
|
||||||
|
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.PrimaryImageItemId || item.Id || item.ItemId, {
|
|
||||||
type: 'Primary',
|
|
||||||
maxHeight: height,
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.PrimaryImageTag
|
|
||||||
});
|
|
||||||
|
|
||||||
if (options.preferThumb && options.showTitle !== false) {
|
if (options.preferThumb && options.showTitle !== false) {
|
||||||
forceName = true;
|
forceName = true;
|
||||||
}
|
}
|
||||||
|
@ -624,30 +575,15 @@ import 'programStyles';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (item.ParentPrimaryImageTag) {
|
} else if (item.ParentPrimaryImageTag) {
|
||||||
|
imgType = 'Primary';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.ParentPrimaryImageItemId, {
|
imgTag = item.ParentPrimaryImageTag;
|
||||||
type: 'Primary',
|
itemId = item.ParentPrimaryImageItemId;
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ParentPrimaryImageTag
|
|
||||||
});
|
|
||||||
} else if (item.SeriesPrimaryImageTag) {
|
|
||||||
|
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.SeriesId, {
|
|
||||||
type: 'Primary',
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.SeriesPrimaryImageTag
|
|
||||||
});
|
|
||||||
} else if (item.AlbumId && item.AlbumPrimaryImageTag) {
|
} else if (item.AlbumId && item.AlbumPrimaryImageTag) {
|
||||||
|
imgType = 'Primary';
|
||||||
|
imgTag = item.AlbumPrimaryImageTag;
|
||||||
|
itemId = item.AlbumId;
|
||||||
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
|
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
|
||||||
|
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.AlbumId, {
|
|
||||||
type: 'Primary',
|
|
||||||
maxHeight: height,
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.AlbumPrimaryImageTag
|
|
||||||
});
|
|
||||||
|
|
||||||
if (primaryImageAspectRatio) {
|
if (primaryImageAspectRatio) {
|
||||||
uiAspect = getDesiredAspect(shape);
|
uiAspect = getDesiredAspect(shape);
|
||||||
if (uiAspect) {
|
if (uiAspect) {
|
||||||
|
@ -655,57 +591,46 @@ import 'programStyles';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (item.Type === 'Season' && item.ImageTags && item.ImageTags.Thumb) {
|
} else if (item.Type === 'Season' && item.ImageTags && item.ImageTags.Thumb) {
|
||||||
|
imgType = 'Thumb';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.Id, {
|
imgTag = item.ImageTags.Thumb;
|
||||||
type: 'Thumb',
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ImageTags.Thumb
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (item.BackdropImageTags && item.BackdropImageTags.length) {
|
} else if (item.BackdropImageTags && item.BackdropImageTags.length) {
|
||||||
|
imgType = 'Backdrop';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.Id, {
|
imgTag = item.BackdropImageTags[0];
|
||||||
type: 'Backdrop',
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.BackdropImageTags[0]
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (item.ImageTags && item.ImageTags.Thumb) {
|
} else if (item.ImageTags && item.ImageTags.Thumb) {
|
||||||
|
imgType = 'Thumb';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.Id, {
|
imgTag = item.ImageTags.Thumb;
|
||||||
type: 'Thumb',
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ImageTags.Thumb
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (item.SeriesThumbImageTag && options.inheritThumb !== false) {
|
} else if (item.SeriesThumbImageTag && options.inheritThumb !== false) {
|
||||||
|
imgType = 'Thumb';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.SeriesId, {
|
imgTag = item.SeriesThumbImageTag;
|
||||||
type: 'Thumb',
|
itemId = item.SeriesId;
|
||||||
maxWidth: width,
|
|
||||||
tag: item.SeriesThumbImageTag
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (item.ParentThumbItemId && options.inheritThumb !== false) {
|
} else if (item.ParentThumbItemId && options.inheritThumb !== false) {
|
||||||
|
imgType = 'Thumb';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.ParentThumbItemId, {
|
imgTag = item.ParentThumbImageTag;
|
||||||
type: 'Thumb',
|
itemId = item.ParentThumbItemId;
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ParentThumbImageTag
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (item.ParentBackdropImageTags && item.ParentBackdropImageTags.length && options.inheritThumb !== false) {
|
} else if (item.ParentBackdropImageTags && item.ParentBackdropImageTags.length && options.inheritThumb !== false) {
|
||||||
|
imgType = 'Backdrop';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.ParentBackdropItemId, {
|
imgTag = item.ParentBackdropImageTags[0];
|
||||||
type: 'Backdrop',
|
itemId = item.ParentBackdropItemId;
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ParentBackdropImageTags[0]
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!itemId) {
|
||||||
|
itemId = item.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imgTag && imgType) {
|
||||||
|
imgUrl = apiClient.getScaledImageUrl(itemId, {
|
||||||
|
type: imgType,
|
||||||
|
maxHeight: height,
|
||||||
|
maxWidth: width,
|
||||||
|
tag: imgTag
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let blurHashes = options.imageBlurhashes || item.ImageBlurHashes || {};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
imgUrl: imgUrl,
|
imgUrl: imgUrl,
|
||||||
|
blurhash: (blurHashes[imgType] || {})[imgTag],
|
||||||
forceName: forceName,
|
forceName: forceName,
|
||||||
coverImage: coverImage
|
coverImage: coverImage
|
||||||
};
|
};
|
||||||
|
@ -1321,6 +1246,7 @@ import 'programStyles';
|
||||||
|
|
||||||
const imgInfo = getCardImageUrl(item, apiClient, options, shape);
|
const imgInfo = getCardImageUrl(item, apiClient, options, shape);
|
||||||
const imgUrl = imgInfo.imgUrl;
|
const imgUrl = imgInfo.imgUrl;
|
||||||
|
const blurhash = imgInfo.blurhash;
|
||||||
|
|
||||||
const forceName = imgInfo.forceName;
|
const forceName = imgInfo.forceName;
|
||||||
|
|
||||||
|
@ -1441,26 +1367,27 @@ import 'programStyles';
|
||||||
let cardScalableClose = '';
|
let cardScalableClose = '';
|
||||||
|
|
||||||
let cardContentClass = 'cardContent';
|
let cardContentClass = 'cardContent';
|
||||||
if (!options.cardLayout) {
|
|
||||||
cardContentClass += ' cardContent-shadow';
|
let blurhashAttrib = '';
|
||||||
|
if (blurhash && blurhash.length > 0) {
|
||||||
|
blurhashAttrib = 'data-blurhash="' + blurhash + '"';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layoutManager.tv) {
|
if (layoutManager.tv) {
|
||||||
|
|
||||||
// Don't use the IMG tag with safari because it puts a white border around it
|
// Don't use the IMG tag with safari because it puts a white border around it
|
||||||
cardImageContainerOpen = imgUrl ? ('<div class="' + cardImageContainerClass + ' ' + cardContentClass + ' lazy" data-src="' + imgUrl + '">') : ('<div class="' + cardImageContainerClass + ' ' + cardContentClass + '">');
|
cardImageContainerOpen = imgUrl ? ('<div class="' + cardImageContainerClass + ' ' + cardContentClass + ' lazy" data-src="' + imgUrl + '" ' + blurhashAttrib + '>') : ('<div class="' + cardImageContainerClass + ' ' + cardContentClass + '">');
|
||||||
|
|
||||||
cardImageContainerClose = '</div>';
|
cardImageContainerClose = '</div>';
|
||||||
} else {
|
} else {
|
||||||
// Don't use the IMG tag with safari because it puts a white border around it
|
// Don't use the IMG tag with safari because it puts a white border around it
|
||||||
cardImageContainerOpen = imgUrl ? ('<button data-action="' + action + '" class="cardContent-button ' + cardImageContainerClass + ' ' + cardContentClass + ' itemAction lazy" data-src="' + imgUrl + '">') : ('<button data-action="' + action + '" class="cardContent-button ' + cardImageContainerClass + ' ' + cardContentClass + ' itemAction">');
|
cardImageContainerOpen = imgUrl ? ('<button data-action="' + action + '" class="' + cardImageContainerClass + ' ' + cardContentClass + ' itemAction lazy" data-src="' + imgUrl + '" ' + blurhashAttrib + '>') : ('<button data-action="' + action + '" class="' + cardImageContainerClass + ' ' + cardContentClass + ' itemAction">');
|
||||||
|
|
||||||
cardImageContainerClose = '</button>';
|
cardImageContainerClose = '</button>';
|
||||||
}
|
}
|
||||||
|
|
||||||
let cardScalableClass = 'cardScalable';
|
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>';
|
cardBoxClose = '</div>';
|
||||||
cardScalableClose = '</div>';
|
cardScalableClose = '</div>';
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,23 @@
|
||||||
define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browser'], function (datetime, imageLoader, connectionManager, layoutManager, browser) {
|
/* eslint-disable indent */
|
||||||
'use strict';
|
|
||||||
|
|
||||||
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) {
|
function buildChapterCardsHtml(item, chapters, options) {
|
||||||
|
|
||||||
// TODO move card creation code to Card component
|
// TODO move card creation code to Card component
|
||||||
|
|
||||||
var className = 'card itemAction chapterCard';
|
let className = 'card itemAction chapterCard';
|
||||||
|
|
||||||
if (layoutManager.tv) {
|
if (layoutManager.tv) {
|
||||||
className += ' show-focus';
|
className += ' show-focus';
|
||||||
|
@ -17,12 +27,12 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var mediaStreams = ((item.MediaSources || [])[0] || {}).MediaStreams || [];
|
const mediaStreams = ((item.MediaSources || [])[0] || {}).MediaStreams || [];
|
||||||
var videoStream = mediaStreams.filter(function (i) {
|
const videoStream = mediaStreams.filter(({Type}) => {
|
||||||
return i.Type === 'Video';
|
return Type === 'Video';
|
||||||
})[0] || {};
|
})[0] || {};
|
||||||
|
|
||||||
var shape = (options.backdropShape || 'backdrop');
|
let shape = (options.backdropShape || 'backdrop');
|
||||||
|
|
||||||
if (videoStream.Width && videoStream.Height) {
|
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) {
|
if (options.block || options.rows) {
|
||||||
className += ' block';
|
className += ' block';
|
||||||
}
|
}
|
||||||
|
|
||||||
var html = '';
|
let html = '';
|
||||||
var itemsInRow = 0;
|
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) {
|
if (options.rows && itemsInRow === 0) {
|
||||||
html += '<div class="cardColumn">';
|
html += '<div class="cardColumn">';
|
||||||
}
|
}
|
||||||
|
|
||||||
var chapter = chapters[i];
|
const chapter = chapters[i];
|
||||||
|
|
||||||
html += buildChapterCard(item, apiClient, chapter, i, options, className, shape);
|
html += buildChapterCard(item, apiClient, chapter, i, options, className, shape);
|
||||||
itemsInRow++;
|
itemsInRow++;
|
||||||
|
@ -62,50 +72,50 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browse
|
||||||
return html;
|
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,
|
maxWidth: maxWidth * 2,
|
||||||
tag: chapter.ImageTag,
|
tag: ImageTag,
|
||||||
type: 'Chapter',
|
type: 'Chapter',
|
||||||
index: index
|
index
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
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';
|
let cardImageContainerClass = 'cardContent cardContent-shadow cardImageContainer chapterCardImageContainer';
|
||||||
if (options.coverImage) {
|
if (coverImage) {
|
||||||
cardImageContainerClass += ' coveredImage';
|
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 + '"';
|
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}"`;
|
||||||
var cardImageContainer = imgUrl ? ('<div class="' + cardImageContainerClass + ' lazy" data-src="' + imgUrl + '">') : ('<div class="' + cardImageContainerClass + '">');
|
let cardImageContainer = imgUrl ? (`<div class="${cardImageContainerClass} lazy" data-src="${imgUrl}">`) : (`<div class="${cardImageContainerClass}">`);
|
||||||
|
|
||||||
if (!imgUrl) {
|
if (!imgUrl) {
|
||||||
cardImageContainer += '<span class="material-icons cardImageIcon local_movies"></span>';
|
cardImageContainer += '<span class="material-icons cardImageIcon local_movies"></span>';
|
||||||
}
|
}
|
||||||
|
|
||||||
var nameHtml = '';
|
let nameHtml = '';
|
||||||
nameHtml += '<div class="cardText">' + chapter.Name + '</div>';
|
nameHtml += `<div class="cardText">${chapter.Name}</div>`;
|
||||||
nameHtml += '<div class="cardText">' + datetime.getDisplayRunningTime(chapter.StartPositionTicks) + '</div>';
|
nameHtml += `<div class="cardText">${datetime.getDisplayRunningTime(chapter.StartPositionTicks)}</div>`;
|
||||||
|
|
||||||
var cardBoxCssClass = 'cardBox';
|
const cardBoxCssClass = 'cardBox';
|
||||||
var cardScalableClass = 'cardScalable';
|
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;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildChapterCards(item, chapters, options) {
|
export function buildChapterCards(item, chapters, options) {
|
||||||
|
|
||||||
if (options.parentContainer) {
|
if (options.parentContainer) {
|
||||||
// Abort if the container has been disposed
|
// Abort if the container has been disposed
|
||||||
|
@ -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;
|
options.itemsContainer.innerHTML = html;
|
||||||
|
|
||||||
imageLoader.lazyChildren(options.itemsContainer);
|
imageLoader.lazyChildren(options.itemsContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
/* eslint-enable indent */
|
||||||
|
|
||||||
|
export default {
|
||||||
buildChapterCards: buildChapterCards
|
buildChapterCards: buildChapterCards
|
||||||
};
|
};
|
||||||
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
define(['cardBuilder'], function (cardBuilder) {
|
/* eslint-disable indent */
|
||||||
'use strict';
|
|
||||||
|
|
||||||
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 || {}, {
|
options = Object.assign(options || {}, {
|
||||||
cardLayout: false,
|
cardLayout: false,
|
||||||
|
@ -15,8 +21,8 @@ define(['cardBuilder'], function (cardBuilder) {
|
||||||
cardBuilder.buildCards(items, options);
|
cardBuilder.buildCards(items, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
/* eslint-enable indent */
|
||||||
|
|
||||||
|
export default {
|
||||||
buildPeopleCards: buildPeopleCards
|
buildPeopleCards: buildPeopleCards
|
||||||
};
|
};
|
||||||
|
|
||||||
});
|
|
||||||
|
|
|
@ -4,12 +4,8 @@
|
||||||
|
|
||||||
<div class="formDialogContent smoothScrollY">
|
<div class="formDialogContent smoothScrollY">
|
||||||
<div class="dialogContentInner dialog-content-centered" style="padding-top:1em;padding-bottom: 1em; text-align: center;">
|
<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>
|
</div>
|
||||||
|
|
||||||
<div class="formDialogFooter formDialogFooter-clear formDialogFooter-flex" style="padding-bottom: 1.5em;">
|
<div class="formDialogFooter formDialogFooter-clear formDialogFooter-flex" style="margin:1em"></div>
|
||||||
</div>
|
|
||||||
|
|
|
@ -181,6 +181,7 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
|
||||||
context.querySelector('#chkThemeSong').checked = userSettings.enableThemeSongs();
|
context.querySelector('#chkThemeSong').checked = userSettings.enableThemeSongs();
|
||||||
context.querySelector('#chkThemeVideo').checked = userSettings.enableThemeVideos();
|
context.querySelector('#chkThemeVideo').checked = userSettings.enableThemeVideos();
|
||||||
context.querySelector('#chkFadein').checked = userSettings.enableFastFadein();
|
context.querySelector('#chkFadein').checked = userSettings.enableFastFadein();
|
||||||
|
context.querySelector('#chkBlurhash').checked = userSettings.enableBlurhash();
|
||||||
context.querySelector('#chkBackdrops').checked = userSettings.enableBackdrops();
|
context.querySelector('#chkBackdrops').checked = userSettings.enableBackdrops();
|
||||||
context.querySelector('#chkDetailsBanner').checked = userSettings.detailsBanner();
|
context.querySelector('#chkDetailsBanner').checked = userSettings.detailsBanner();
|
||||||
|
|
||||||
|
@ -223,6 +224,7 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
|
||||||
userSettingsInstance.skin(context.querySelector('.selectSkin').value);
|
userSettingsInstance.skin(context.querySelector('.selectSkin').value);
|
||||||
|
|
||||||
userSettingsInstance.enableFastFadein(context.querySelector('#chkFadein').checked);
|
userSettingsInstance.enableFastFadein(context.querySelector('#chkFadein').checked);
|
||||||
|
userSettingsInstance.enableBlurhash(context.querySelector('#chkBlurhash').checked);
|
||||||
userSettingsInstance.enableBackdrops(context.querySelector('#chkBackdrops').checked);
|
userSettingsInstance.enableBackdrops(context.querySelector('#chkBackdrops').checked);
|
||||||
userSettingsInstance.detailsBanner(context.querySelector('#chkDetailsBanner').checked);
|
userSettingsInstance.detailsBanner(context.querySelector('#chkDetailsBanner').checked);
|
||||||
|
|
||||||
|
|
|
@ -143,20 +143,28 @@
|
||||||
<select is="emby-select" class="selectSoundEffects" label="${LabelSoundEffects}"></select>
|
<select is="emby-select" class="selectSoundEffects" label="${LabelSoundEffects}"></select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="inputContainer inputContainer-withDescription fldFadein">
|
<div class="inputContainer inputContainer-withDescription">
|
||||||
<input is="emby-input" type="number" id="txtLibraryPageSize" pattern="[0-9]*" required="required" min="0" max="1000" step="1" label="${LabelLibraryPageSize}" />
|
<input is="emby-input" type="number" id="txtLibraryPageSize" pattern="[0-9]*" required="required" min="0" max="1000" step="1" label="${LabelLibraryPageSize}" />
|
||||||
<div class="fieldDescription">${LabelLibraryPageSizeHelp}</div>
|
<div class="fieldDescription">${LabelLibraryPageSizeHelp}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription fldFadein">
|
<div class="checkboxContainer checkboxContainer-withDescription">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" is="emby-checkbox" id="chkFadein" />
|
<input type="checkbox" is="emby-checkbox" id="chkFadein" />
|
||||||
<span>${EnableFastImageFadeIn}</span>
|
<span>${EnableFasterAnimations}</span>
|
||||||
</label>
|
</label>
|
||||||
<div class="fieldDescription checkboxFieldDescription">${EnableFastImageFadeInHelp}</div>
|
<div class="fieldDescription checkboxFieldDescription">${EnableFasterAnimationsHelp}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription fldDetailsBanner">
|
<div class="checkboxContainer checkboxContainer-withDescription">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" is="emby-checkbox" id="chkBlurhash" />
|
||||||
|
<span>${EnableBlurhash}</span>
|
||||||
|
</label>
|
||||||
|
<div class="fieldDescription checkboxFieldDescription">${EnableBlurhashHelp}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="checkboxContainer checkboxContainer-withDescription">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" is="emby-checkbox" id="chkDetailsBanner" />
|
<input type="checkbox" is="emby-checkbox" id="chkDetailsBanner" />
|
||||||
<span>${EnableDetailsBanner}</span>
|
<span>${EnableDetailsBanner}</span>
|
||||||
|
|
|
@ -1,21 +1,19 @@
|
||||||
define([], function () {
|
/* eslint-disable indent */
|
||||||
'use strict';
|
export function getFetchPromise(request) {
|
||||||
|
|
||||||
function getFetchPromise(request) {
|
const headers = request.headers || {};
|
||||||
|
|
||||||
var headers = request.headers || {};
|
|
||||||
|
|
||||||
if (request.dataType === 'json') {
|
if (request.dataType === 'json') {
|
||||||
headers.accept = 'application/json';
|
headers.accept = 'application/json';
|
||||||
}
|
}
|
||||||
|
|
||||||
var fetchRequest = {
|
const fetchRequest = {
|
||||||
headers: headers,
|
headers: headers,
|
||||||
method: request.type,
|
method: request.type,
|
||||||
credentials: 'same-origin'
|
credentials: 'same-origin'
|
||||||
};
|
};
|
||||||
|
|
||||||
var contentType = request.contentType;
|
let contentType = request.contentType;
|
||||||
|
|
||||||
if (request.data) {
|
if (request.data) {
|
||||||
|
|
||||||
|
@ -33,12 +31,12 @@ define([], function () {
|
||||||
headers['Content-Type'] = contentType;
|
headers['Content-Type'] = contentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = request.url;
|
let url = request.url;
|
||||||
|
|
||||||
if (request.query) {
|
if (request.query) {
|
||||||
var paramString = paramsToString(request.query);
|
const paramString = paramsToString(request.query);
|
||||||
if (paramString) {
|
if (paramString) {
|
||||||
url += '?' + paramString;
|
url += `?${paramString}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,11 +49,11 @@ define([], function () {
|
||||||
|
|
||||||
function fetchWithTimeout(url, options, timeoutMs) {
|
function fetchWithTimeout(url, options, timeoutMs) {
|
||||||
|
|
||||||
console.debug('fetchWithTimeout: timeoutMs: ' + timeoutMs + ', url: ' + url);
|
console.debug(`fetchWithTimeout: timeoutMs: ${timeoutMs}, url: ${url}`);
|
||||||
|
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
|
|
||||||
var timeout = setTimeout(reject, timeoutMs);
|
const timeout = setTimeout(reject, timeoutMs);
|
||||||
|
|
||||||
options = options || {};
|
options = options || {};
|
||||||
options.credentials = 'same-origin';
|
options.credentials = 'same-origin';
|
||||||
|
@ -63,50 +61,47 @@ define([], function () {
|
||||||
fetch(url, options).then(function (response) {
|
fetch(url, options).then(function (response) {
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
|
|
||||||
console.debug('fetchWithTimeout: succeeded connecting to url: ' + url);
|
console.debug(`fetchWithTimeout: succeeded connecting to url: ${url}`);
|
||||||
|
|
||||||
resolve(response);
|
resolve(response);
|
||||||
}, function (error) {
|
}, function (error) {
|
||||||
|
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
|
|
||||||
console.debug('fetchWithTimeout: timed out connecting to url: ' + url);
|
console.debug(`fetchWithTimeout: timed out connecting to url: ${url}`);
|
||||||
|
|
||||||
reject();
|
reject(error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param params {Record<string, string | number | boolean>}
|
||||||
|
* @returns {string} Query string
|
||||||
|
*/
|
||||||
function paramsToString(params) {
|
function paramsToString(params) {
|
||||||
|
return Object.entries(params)
|
||||||
var values = [];
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
.filter(([_, v]) => v !== null && v !== undefined && v !== '')
|
||||||
for (var key in params) {
|
.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
|
||||||
|
.join('&');
|
||||||
var value = params[key];
|
|
||||||
|
|
||||||
if (value !== null && value !== undefined && value !== '') {
|
|
||||||
values.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return values.join('&');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function ajax(request) {
|
export function ajax(request) {
|
||||||
if (!request) {
|
if (!request) {
|
||||||
throw new Error('Request cannot be null');
|
throw new Error('Request cannot be null');
|
||||||
}
|
}
|
||||||
|
|
||||||
request.headers = request.headers || {};
|
request.headers = request.headers || {};
|
||||||
|
|
||||||
console.debug('requesting url: ' + request.url);
|
console.debug(`requesting url: ${request.url}`);
|
||||||
|
|
||||||
return getFetchPromise(request).then(function (response) {
|
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 (response.status < 400) {
|
||||||
if (request.dataType === 'json' || request.headers.accept === 'application/json') {
|
if (request.dataType === 'json' || request.headers.accept === 'application/json') {
|
||||||
return response.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();
|
return response.text();
|
||||||
} else {
|
} else {
|
||||||
return response;
|
return response;
|
||||||
|
@ -115,12 +110,8 @@ define([], function () {
|
||||||
return Promise.reject(response);
|
return Promise.reject(response);
|
||||||
}
|
}
|
||||||
}, function (err) {
|
}, function (err) {
|
||||||
console.error('request failed to url: ' + request.url);
|
console.error(`request failed to url: ${request.url}`);
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return {
|
/* eslint-enable indent */
|
||||||
getFetchPromise: getFetchPromise,
|
|
||||||
ajax: ajax
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
|
@ -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) {
|
import dom from 'dom';
|
||||||
'use strict';
|
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) {
|
function renderOptions(context, selector, cssClass, items, isCheckedFn) {
|
||||||
var elem = context.querySelector(selector);
|
const elem = context.querySelector(selector);
|
||||||
if (items.length) {
|
if (items.length) {
|
||||||
elem.classList.remove('hide');
|
elem.classList.remove('hide');
|
||||||
} else {
|
} else {
|
||||||
elem.classList.add('hide');
|
elem.classList.add('hide');
|
||||||
}
|
}
|
||||||
var html = '';
|
let html = '';
|
||||||
html += '<div class="checkboxList">';
|
html += '<div class="checkboxList">';
|
||||||
html += items.map(function (filter) {
|
html += items.map(function (filter) {
|
||||||
var itemHtml = '';
|
let itemHtml = '';
|
||||||
var checkedHtml = isCheckedFn(filter) ? ' checked' : '';
|
const checkedHtml = isCheckedFn(filter) ? 'checked' : '';
|
||||||
itemHtml += '<label>';
|
itemHtml += '<label>';
|
||||||
itemHtml += '<input is="emby-checkbox" type="checkbox"' + checkedHtml + ' data-filter="' + filter + '" class="' + cssClass + '"/>';
|
itemHtml += `<input is="emby-checkbox" type="checkbox" ${checkedHtml} data-filter="${filter}" class="${cssClass}"/>`;
|
||||||
itemHtml += '<span>' + filter + '</span>';
|
itemHtml += `<span>${filter}</span>`;
|
||||||
itemHtml += '</label>';
|
itemHtml += '</label>';
|
||||||
return itemHtml;
|
return itemHtml;
|
||||||
}).join('');
|
}).join('');
|
||||||
|
@ -24,21 +31,24 @@ define(['dom', 'dialogHelper', 'globalize', 'connectionManager', 'events', 'brow
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderFilters(context, result, query) {
|
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) {
|
renderOptions(context, '.genreFilters', 'chkGenreFilter', result.Genres, function (i) {
|
||||||
var delimeter = '|';
|
const delimeter = '|';
|
||||||
return (delimeter + (query.Genres || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
|
return (delimeter + (query.Genres || '') + delimeter).includes(delimeter + i + delimeter);
|
||||||
});
|
});
|
||||||
renderOptions(context, '.officialRatingFilters', 'chkOfficialRatingFilter', result.OfficialRatings, function (i) {
|
renderOptions(context, '.officialRatingFilters', 'chkOfficialRatingFilter', result.OfficialRatings, function (i) {
|
||||||
var delimeter = '|';
|
const delimeter = '|';
|
||||||
return (delimeter + (query.OfficialRatings || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
|
return (delimeter + (query.OfficialRatings || '') + delimeter).includes(delimeter + i + delimeter);
|
||||||
});
|
});
|
||||||
renderOptions(context, '.tagFilters', 'chkTagFilter', result.Tags, function (i) {
|
renderOptions(context, '.tagFilters', 'chkTagFilter', result.Tags, function (i) {
|
||||||
var delimeter = '|';
|
const delimeter = '|';
|
||||||
return (delimeter + (query.Tags || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
|
return (delimeter + (query.Tags || '') + delimeter).includes(delimeter + i + delimeter);
|
||||||
});
|
});
|
||||||
renderOptions(context, '.yearFilters', 'chkYearFilter', result.Years, function (i) {
|
renderOptions(context, '.yearFilters', 'chkYearFilter', result.Years, function (i) {
|
||||||
var delimeter = ',';
|
const delimeter = ',';
|
||||||
return (delimeter + (query.Years || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
|
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) {
|
function updateFilterControls(context, options) {
|
||||||
var elems;
|
const query = options.query;
|
||||||
var i;
|
|
||||||
var length;
|
|
||||||
var query = options.query;
|
|
||||||
|
|
||||||
if (options.mode == 'livetvchannels') {
|
if (options.mode === 'livetvchannels') {
|
||||||
context.querySelector('.chkFavorite').checked = query.IsFavorite == true;
|
context.querySelector('.chkFavorite').checked = query.IsFavorite === true;
|
||||||
context.querySelector('.chkLikes').checked = query.IsLiked == true;
|
context.querySelector('.chkLikes').checked = query.IsLiked === true;
|
||||||
context.querySelector('.chkDislikes').checked = query.IsDisliked == true;
|
context.querySelector('.chkDislikes').checked = query.IsDisliked === true;
|
||||||
} else {
|
} else {
|
||||||
elems = context.querySelectorAll('.chkStandardFilter');
|
for (const elem of context.querySelectorAll('.chkStandardFilter')) {
|
||||||
for (i = 0, length = elems.length; i < length; i++) {
|
const filters = `,${query.Filters || ''}`;
|
||||||
var chkStandardFilter = elems[i];
|
const filterName = elem.getAttribute('data-filter');
|
||||||
var filters = ',' + (query.Filters || '');
|
elem.checked = filters.includes(`,${filterName}`);
|
||||||
var filterName = chkStandardFilter.getAttribute('data-filter');
|
|
||||||
chkStandardFilter.checked = filters.indexOf(',' + filterName) != -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
elems = context.querySelectorAll('.chkVideoTypeFilter');
|
for (const elem of context.querySelectorAll('.chkVideoTypeFilter')) {
|
||||||
for (i = 0, length = elems.length; i < length; i++) {
|
const filters = `,${query.VideoTypes || ''}`;
|
||||||
var chkVideoTypeFilter = elems[i];
|
const filterName = elem.getAttribute('data-filter');
|
||||||
var filters = ',' + (query.VideoTypes || '');
|
elem.checked = filters.includes(`,${filterName}`);
|
||||||
var filterName = chkVideoTypeFilter.getAttribute('data-filter');
|
|
||||||
chkVideoTypeFilter.checked = filters.indexOf(',' + filterName) != -1;
|
|
||||||
}
|
}
|
||||||
context.querySelector('.chk3DFilter').checked = query.Is3D == true;
|
context.querySelector('.chk3DFilter').checked = query.Is3D === true;
|
||||||
context.querySelector('.chkHDFilter').checked = query.IsHD == true;
|
context.querySelector('.chkHDFilter').checked = query.IsHD === true;
|
||||||
context.querySelector('.chk4KFilter').checked = query.Is4K == true;
|
context.querySelector('.chk4KFilter').checked = query.Is4K === true;
|
||||||
context.querySelector('.chkSDFilter').checked = query.IsHD == true;
|
context.querySelector('.chkSDFilter').checked = query.IsHD === true;
|
||||||
context.querySelector('#chkSubtitle').checked = query.HasSubtitles == true;
|
context.querySelector('#chkSubtitle').checked = query.HasSubtitles === true;
|
||||||
context.querySelector('#chkTrailer').checked = query.HasTrailer == true;
|
context.querySelector('#chkTrailer').checked = query.HasTrailer === true;
|
||||||
context.querySelector('#chkThemeSong').checked = query.HasThemeSong == true;
|
context.querySelector('#chkThemeSong').checked = query.HasThemeSong === true;
|
||||||
context.querySelector('#chkThemeVideo').checked = query.HasThemeVideo == true;
|
context.querySelector('#chkThemeVideo').checked = query.HasThemeVideo === true;
|
||||||
context.querySelector('#chkSpecialFeature').checked = query.HasSpecialFeature == true;
|
context.querySelector('#chkSpecialFeature').checked = query.HasSpecialFeature === true;
|
||||||
context.querySelector('#chkSpecialEpisode').checked = query.ParentIndexNumber == 0;
|
context.querySelector('#chkSpecialEpisode').checked = query.ParentIndexNumber === 0;
|
||||||
context.querySelector('#chkMissingEpisode').checked = query.IsMissing == true;
|
context.querySelector('#chkMissingEpisode').checked = query.IsMissing === true;
|
||||||
context.querySelector('#chkFutureEpisode').checked = query.IsUnaired == true;
|
context.querySelector('#chkFutureEpisode').checked = query.IsUnaired === true;
|
||||||
for (i = 0, length = elems.length; i < length; i++) {
|
for (const elem of context.querySelectorAll('.chkStatus')) {
|
||||||
var chkStatus = elems[i];
|
const filters = `,${query.SeriesStatus || ''}`;
|
||||||
var filters = ',' + (query.SeriesStatus || '');
|
const filterName = elem.getAttribute('data-filter');
|
||||||
var filterName = chkStatus.getAttribute('data-filter');
|
elem.checked = filters.includes(`,${filterName}`);
|
||||||
chkStatus.checked = filters.indexOf(',' + filterName) != -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param instance {FilterDialog} An instance of FilterDialog
|
||||||
|
*/
|
||||||
function triggerChange(instance) {
|
function triggerChange(instance) {
|
||||||
events.trigger(instance, 'filterchange');
|
events.trigger(instance, 'filterchange');
|
||||||
}
|
}
|
||||||
|
|
||||||
function setVisibility(context, options) {
|
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');
|
hideByClass(context, 'videoStandard');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,263 +124,287 @@ define(['dom', 'dialogHelper', 'globalize', 'connectionManager', 'events', 'brow
|
||||||
context.querySelector('.yearFilters').classList.remove('hide');
|
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');
|
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');
|
context.querySelector('.features').classList.remove('hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.mode == 'series') {
|
if (options.mode === 'series') {
|
||||||
context.querySelector('.seriesStatus').classList.remove('hide');
|
context.querySelector('.seriesStatus').classList.remove('hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.mode == 'episodes') {
|
if (options.mode === 'episodes') {
|
||||||
showByClass(context, 'episodeFilter');
|
showByClass(context, 'episodeFilter');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showByClass(context, className) {
|
function showByClass(context, className) {
|
||||||
var elems = context.querySelectorAll('.' + className);
|
for (const elem of context.querySelectorAll(`.${className}`)) {
|
||||||
|
elem.classList.remove('hide');
|
||||||
for (var i = 0, length = elems.length; i < length; i++) {
|
|
||||||
elems[i].classList.remove('hide');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideByClass(context, className) {
|
function hideByClass(context, className) {
|
||||||
var elems = context.querySelectorAll('.' + className);
|
for (const elem of context.querySelectorAll(`.${className}`)) {
|
||||||
|
elem.classList.add('hide');
|
||||||
for (var i = 0, length = elems.length; i < length; i++) {
|
|
||||||
elems[i].classList.add('hide');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function enableDynamicFilters(mode) {
|
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) {
|
class FilterDialog {
|
||||||
function onFavoriteChange() {
|
constructor(options) {
|
||||||
var query = options.query;
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onFavoriteChange(elem) {
|
||||||
|
const query = this.options.query;
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.IsFavorite = !!this.checked || null;
|
query.IsFavorite = !!elem.checked || null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onStandardFilterChange() {
|
/**
|
||||||
var query = options.query;
|
* @private
|
||||||
var filterName = this.getAttribute('data-filter');
|
*/
|
||||||
var filters = query.Filters || '';
|
onStandardFilterChange(elem) {
|
||||||
filters = (',' + filters).replace(',' + filterName, '').substring(1);
|
const query = this.options.query;
|
||||||
|
const filterName = elem.getAttribute('data-filter');
|
||||||
|
let filters = query.Filters || '';
|
||||||
|
filters = (`,${filters}`).replace(`,${filterName}`, '').substring(1);
|
||||||
|
|
||||||
if (this.checked) {
|
if (elem.checked) {
|
||||||
filters = filters ? filters + ',' + filterName : filterName;
|
filters = filters ? `${filters},${filterName}` : filterName;
|
||||||
}
|
}
|
||||||
|
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.Filters = filters;
|
query.Filters = filters;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onVideoTypeFilterChange() {
|
/**
|
||||||
var query = options.query;
|
* @private
|
||||||
var filterName = this.getAttribute('data-filter');
|
*/
|
||||||
var filters = query.VideoTypes || '';
|
onVideoTypeFilterChange(elem) {
|
||||||
filters = (',' + filters).replace(',' + filterName, '').substring(1);
|
const query = this.options.query;
|
||||||
|
const filterName = elem.getAttribute('data-filter');
|
||||||
|
let filters = query.VideoTypes || '';
|
||||||
|
filters = (`,${filters}`).replace(`,${filterName}`, '').substring(1);
|
||||||
|
|
||||||
if (this.checked) {
|
if (elem.checked) {
|
||||||
filters = filters ? filters + ',' + filterName : filterName;
|
filters = filters ? `${filters},${filterName}` : filterName;
|
||||||
}
|
}
|
||||||
|
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.VideoTypes = filters;
|
query.VideoTypes = filters;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onStatusChange() {
|
/**
|
||||||
var query = options.query;
|
* @private
|
||||||
var filterName = this.getAttribute('data-filter');
|
*/
|
||||||
var filters = query.SeriesStatus || '';
|
onStatusChange(elem) {
|
||||||
filters = (',' + filters).replace(',' + filterName, '').substring(1);
|
const query = this.options.query;
|
||||||
|
const filterName = elem.getAttribute('data-filter');
|
||||||
|
let filters = query.SeriesStatus || '';
|
||||||
|
filters = (`,${filters}`).replace(`,${filterName}`, '').substring(1);
|
||||||
|
|
||||||
if (this.checked) {
|
if (elem.checked) {
|
||||||
filters = filters ? filters + ',' + filterName : filterName;
|
filters = filters ? `${filters},${filterName}` : filterName;
|
||||||
}
|
}
|
||||||
|
|
||||||
query.SeriesStatus = filters;
|
query.SeriesStatus = filters;
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
function bindEvents(context) {
|
/**
|
||||||
var elems;
|
* @param context {HTMLDivElement} The dialog
|
||||||
var i;
|
*/
|
||||||
var length;
|
bindEvents(context) {
|
||||||
var query = options.query;
|
const query = this.options.query;
|
||||||
|
|
||||||
if (options.mode == 'livetvchannels') {
|
if (this.options.mode === 'livetvchannels') {
|
||||||
elems = context.querySelectorAll('.chkFavorite');
|
for (const elem of context.querySelectorAll('.chkFavorite')) {
|
||||||
for (i = 0, length = elems.length; i < length; i++) {
|
elem.addEventListener('change', () => this.onFavoriteChange(elem));
|
||||||
elems[i].addEventListener('change', onFavoriteChange);
|
|
||||||
}
|
}
|
||||||
context.querySelector('.chkLikes').addEventListener('change', function () {
|
|
||||||
|
const chkLikes = context.querySelector('.chkLikes');
|
||||||
|
chkLikes.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.IsLiked = this.checked ? true : null;
|
query.IsLiked = chkLikes.checked ? true : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector('.chkDislikes').addEventListener('change', function () {
|
const chkDislikes = context.querySelector('.chkDislikes');
|
||||||
|
chkDislikes.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.IsDisliked = this.checked ? true : null;
|
query.IsDisliked = chkDislikes.checked ? true : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
elems = context.querySelectorAll('.chkStandardFilter');
|
for (const elem of context.querySelectorAll('.chkStandardFilter')) {
|
||||||
for (i = 0, length = elems.length; i < length; i++) {
|
elem.addEventListener('change', () => this.onStandardFilterChange(elem));
|
||||||
elems[i].addEventListener('change', onStandardFilterChange);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elems = context.querySelectorAll('.chkVideoTypeFilter');
|
|
||||||
for (i = 0, length = elems.length; i < length; i++) {
|
for (const elem of context.querySelectorAll('.chkVideoTypeFilter')) {
|
||||||
elems[i].addEventListener('change', onVideoTypeFilterChange);
|
elem.addEventListener('change', () => this.onVideoTypeFilterChange(elem));
|
||||||
}
|
}
|
||||||
context.querySelector('.chk3DFilter').addEventListener('change', function () {
|
const chk3DFilter = context.querySelector('.chk3DFilter');
|
||||||
|
chk3DFilter.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.Is3D = this.checked ? true : null;
|
query.Is3D = chk3DFilter.checked ? true : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector('.chk4KFilter').addEventListener('change', function () {
|
const chk4KFilter = context.querySelector('.chk4KFilter');
|
||||||
|
chk4KFilter.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.Is4K = this.checked ? true : null;
|
query.Is4K = chk4KFilter.checked ? true : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector('.chkHDFilter').addEventListener('change', function () {
|
const chkHDFilter = context.querySelector('.chkHDFilter');
|
||||||
|
chkHDFilter.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.IsHD = this.checked ? true : null;
|
query.IsHD = chkHDFilter.checked ? true : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector('.chkSDFilter').addEventListener('change', function () {
|
const chkSDFilter = context.querySelector('.chkSDFilter');
|
||||||
|
chkSDFilter.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.IsHD = this.checked ? false : null;
|
query.IsHD = chkSDFilter.checked ? false : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
elems = context.querySelectorAll('.chkStatus');
|
for (const elem of context.querySelectorAll('.chkStatus')) {
|
||||||
for (i = 0, length = elems.length; i < length; i++) {
|
elem.addEventListener('change', () => this.onStatusChange(elem));
|
||||||
elems[i].addEventListener('change', onStatusChange);
|
|
||||||
}
|
}
|
||||||
context.querySelector('#chkTrailer').addEventListener('change', function () {
|
const chkTrailer = context.querySelector('#chkTrailer');
|
||||||
|
chkTrailer.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.HasTrailer = this.checked ? true : null;
|
query.HasTrailer = chkTrailer.checked ? true : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector('#chkThemeSong').addEventListener('change', function () {
|
const chkThemeSong = context.querySelector('#chkThemeSong');
|
||||||
|
chkThemeSong.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.HasThemeSong = this.checked ? true : null;
|
query.HasThemeSong = chkThemeSong.checked ? true : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector('#chkSpecialFeature').addEventListener('change', function () {
|
const chkSpecialFeature = context.querySelector('#chkSpecialFeature');
|
||||||
|
chkSpecialFeature.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.HasSpecialFeature = this.checked ? true : null;
|
query.HasSpecialFeature = chkSpecialFeature.checked ? true : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector('#chkThemeVideo').addEventListener('change', function () {
|
const chkThemeVideo = context.querySelector('#chkThemeVideo');
|
||||||
|
chkThemeVideo.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.HasThemeVideo = this.checked ? true : null;
|
query.HasThemeVideo = chkThemeVideo.checked ? true : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector('#chkMissingEpisode').addEventListener('change', function () {
|
const chkMissingEpisode = context.querySelector('#chkMissingEpisode');
|
||||||
|
chkMissingEpisode.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.IsMissing = this.checked ? true : false;
|
query.IsMissing = !!chkMissingEpisode.checked;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector('#chkSpecialEpisode').addEventListener('change', function () {
|
const chkSpecialEpisode = context.querySelector('#chkSpecialEpisode');
|
||||||
|
chkSpecialEpisode.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.ParentIndexNumber = this.checked ? 0 : null;
|
query.ParentIndexNumber = chkSpecialEpisode.checked ? 0 : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector('#chkFutureEpisode').addEventListener('change', function () {
|
const chkFutureEpisode = context.querySelector('#chkFutureEpisode');
|
||||||
|
chkFutureEpisode.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
if (this.checked) {
|
if (chkFutureEpisode.checked) {
|
||||||
query.IsUnaired = true;
|
query.IsUnaired = true;
|
||||||
query.IsVirtualUnaired = null;
|
query.IsVirtualUnaired = null;
|
||||||
} else {
|
} else {
|
||||||
query.IsUnaired = null;
|
query.IsUnaired = null;
|
||||||
query.IsVirtualUnaired = false;
|
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.StartIndex = 0;
|
||||||
query.HasSubtitles = this.checked ? true : null;
|
query.HasSubtitles = chkSubtitle.checked ? true : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.addEventListener('change', function (e) {
|
context.addEventListener('change', (e) => {
|
||||||
var chkGenreFilter = dom.parentWithClass(e.target, 'chkGenreFilter');
|
const chkGenreFilter = dom.parentWithClass(e.target, 'chkGenreFilter');
|
||||||
if (chkGenreFilter) {
|
if (chkGenreFilter) {
|
||||||
var filterName = chkGenreFilter.getAttribute('data-filter');
|
const filterName = chkGenreFilter.getAttribute('data-filter');
|
||||||
var filters = query.Genres || '';
|
let filters = query.Genres || '';
|
||||||
var delimiter = '|';
|
const delimiter = '|';
|
||||||
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
|
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
|
||||||
if (chkGenreFilter.checked) {
|
if (chkGenreFilter.checked) {
|
||||||
filters = filters ? (filters + delimiter + filterName) : filterName;
|
filters = filters ? (filters + delimiter + filterName) : filterName;
|
||||||
}
|
}
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.Genres = filters;
|
query.Genres = filters;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var chkTagFilter = dom.parentWithClass(e.target, 'chkTagFilter');
|
const chkTagFilter = dom.parentWithClass(e.target, 'chkTagFilter');
|
||||||
if (chkTagFilter) {
|
if (chkTagFilter) {
|
||||||
var filterName = chkTagFilter.getAttribute('data-filter');
|
const filterName = chkTagFilter.getAttribute('data-filter');
|
||||||
var filters = query.Tags || '';
|
let filters = query.Tags || '';
|
||||||
var delimiter = '|';
|
const delimiter = '|';
|
||||||
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
|
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
|
||||||
if (chkTagFilter.checked) {
|
if (chkTagFilter.checked) {
|
||||||
filters = filters ? (filters + delimiter + filterName) : filterName;
|
filters = filters ? (filters + delimiter + filterName) : filterName;
|
||||||
}
|
}
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.Tags = filters;
|
query.Tags = filters;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var chkYearFilter = dom.parentWithClass(e.target, 'chkYearFilter');
|
const chkYearFilter = dom.parentWithClass(e.target, 'chkYearFilter');
|
||||||
if (chkYearFilter) {
|
if (chkYearFilter) {
|
||||||
var filterName = chkYearFilter.getAttribute('data-filter');
|
const filterName = chkYearFilter.getAttribute('data-filter');
|
||||||
var filters = query.Years || '';
|
let filters = query.Years || '';
|
||||||
var delimiter = ',';
|
const delimiter = ',';
|
||||||
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
|
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
|
||||||
if (chkYearFilter.checked) {
|
if (chkYearFilter.checked) {
|
||||||
filters = filters ? (filters + delimiter + filterName) : filterName;
|
filters = filters ? (filters + delimiter + filterName) : filterName;
|
||||||
}
|
}
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.Years = filters;
|
query.Years = filters;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var chkOfficialRatingFilter = dom.parentWithClass(e.target, 'chkOfficialRatingFilter');
|
const chkOfficialRatingFilter = dom.parentWithClass(e.target, 'chkOfficialRatingFilter');
|
||||||
if (chkOfficialRatingFilter) {
|
if (chkOfficialRatingFilter) {
|
||||||
var filterName = chkOfficialRatingFilter.getAttribute('data-filter');
|
const filterName = chkOfficialRatingFilter.getAttribute('data-filter');
|
||||||
var filters = query.OfficialRatings || '';
|
let filters = query.OfficialRatings || '';
|
||||||
var delimiter = '|';
|
const delimiter = '|';
|
||||||
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
|
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
|
||||||
if (chkOfficialRatingFilter.checked) {
|
if (chkOfficialRatingFilter.checked) {
|
||||||
filters = filters ? (filters + delimiter + filterName) : filterName;
|
filters = filters ? (filters + delimiter + filterName) : filterName;
|
||||||
}
|
}
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.OfficialRatings = filters;
|
query.OfficialRatings = filters;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
show() {
|
||||||
|
return import('text!./filterdialog.template.html').then(({default: template}) => {
|
||||||
self.show = function () {
|
return new Promise((resolve) => {
|
||||||
return new Promise(function (resolve, reject) {
|
const dlg = dialogHelper.createDialog({
|
||||||
require(['text!./filterdialog.template.html'], function (template) {
|
|
||||||
var dlg = dialogHelper.createDialog({
|
|
||||||
removeOnClose: true,
|
removeOnClose: true,
|
||||||
modal: false
|
modal: false
|
||||||
});
|
});
|
||||||
|
@ -380,18 +413,21 @@ define(['dom', 'dialogHelper', 'globalize', 'connectionManager', 'events', 'brow
|
||||||
dlg.classList.add('formDialog');
|
dlg.classList.add('formDialog');
|
||||||
dlg.classList.add('filterDialog');
|
dlg.classList.add('filterDialog');
|
||||||
dlg.innerHTML = globalize.translateDocument(template);
|
dlg.innerHTML = globalize.translateDocument(template);
|
||||||
setVisibility(dlg, options);
|
setVisibility(dlg, this.options);
|
||||||
dialogHelper.open(dlg);
|
dialogHelper.open(dlg);
|
||||||
dlg.addEventListener('close', resolve);
|
dlg.addEventListener('close', resolve);
|
||||||
updateFilterControls(dlg, options);
|
updateFilterControls(dlg, this.options);
|
||||||
bindEvents(dlg);
|
this.bindEvents(dlg);
|
||||||
if (enableDynamicFilters(options.mode)) {
|
if (enableDynamicFilters(this.options.mode)) {
|
||||||
dlg.classList.add('dynamicFilterDialog');
|
dlg.classList.add('dynamicFilterDialog');
|
||||||
var apiClient = connectionManager.getApiClient(options.serverId);
|
const apiClient = connectionManager.getApiClient(this.options.serverId);
|
||||||
loadDynamicFilters(dlg, apiClient, apiClient.getCurrentUserId(), options.query);
|
loadDynamicFilters(dlg, apiClient, apiClient.getCurrentUserId(), this.options.query);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
});
|
|
||||||
|
/* eslint-enable indent */
|
||||||
|
|
||||||
|
export default FilterDialog;
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
/* Without this emby-checkbox is able to appear on top */
|
/* Without this emby-checkbox is able to appear on top */
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
justify-content: flex-end;
|
justify-content: center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -168,7 +168,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPortraitShape() {
|
function getPortraitShape() {
|
||||||
return enableScrollX() ? 'autooverflow' : 'auto';
|
return enableScrollX() ? 'overflowPortrait' : 'portrait';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLibraryButtonsHtml(items) {
|
function getLibraryButtonsHtml(items) {
|
||||||
|
@ -254,7 +254,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||||
return cardBuilder.getCardsHtml({
|
return cardBuilder.getCardsHtml({
|
||||||
items: items,
|
items: items,
|
||||||
shape: shape,
|
shape: shape,
|
||||||
preferThumb: viewType !== 'movies' && itemType !== 'Channel' && viewType !== 'music' ? 'auto' : null,
|
preferThumb: viewType !== 'movies' && viewType !== 'tvshows' && itemType !== 'Channel' && viewType !== 'music' ? 'auto' : null,
|
||||||
showUnplayedIndicator: false,
|
showUnplayedIndicator: false,
|
||||||
showChildCountIndicator: true,
|
showChildCountIndicator: true,
|
||||||
context: 'home',
|
context: 'home',
|
||||||
|
|
|
@ -58,6 +58,7 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
|
||||||
var html = ['<img style="max-width:100%;max-height:100%;" src="', e.target.result, '" title="', escape(theFile.name), '"/>'].join('');
|
var html = ['<img style="max-width:100%;max-height:100%;" src="', e.target.result, '" title="', escape(theFile.name), '"/>'].join('');
|
||||||
|
|
||||||
page.querySelector('#imageOutput').innerHTML = html;
|
page.querySelector('#imageOutput').innerHTML = html;
|
||||||
|
page.querySelector('#dropImageText').classList.add('hide');
|
||||||
page.querySelector('#fldUpload').classList.remove('hide');
|
page.querySelector('#fldUpload').classList.remove('hide');
|
||||||
};
|
};
|
||||||
})(file);
|
})(file);
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="imageEditor-dropZone fieldDescription">
|
<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>
|
<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;" />
|
<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>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import * as lazyLoader from 'lazyLoader';
|
import * as lazyLoader from 'lazyLoader';
|
||||||
import * as userSettings from 'userSettings';
|
import * as userSettings from 'userSettings';
|
||||||
|
import * as blurhash from 'blurhash';
|
||||||
import 'css!./style';
|
import 'css!./style';
|
||||||
/* eslint-disable indent */
|
/* eslint-disable indent */
|
||||||
|
|
||||||
|
@ -11,47 +12,111 @@ import 'css!./style';
|
||||||
fillImageElement(elem, source);
|
fillImageElement(elem, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function itemBlurhashing(target, blurhashstr) {
|
||||||
|
if (blurhash.isBlurhashValid(blurhashstr)) {
|
||||||
|
// Although the default values recommended by Blurhash developers is 32x32, a size of 18x18 seems to be the sweet spot for us,
|
||||||
|
// improving the performance and reducing the memory usage, while retaining almost full blur quality.
|
||||||
|
// Lower values had more visible pixelation
|
||||||
|
let width = 18;
|
||||||
|
let height = 18;
|
||||||
|
let pixels;
|
||||||
|
try {
|
||||||
|
pixels = blurhash.decode(blurhashstr, width, height);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Blurhash decode error: ', err);
|
||||||
|
target.classList.add('non-blurhashable');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let canvas = document.createElement('canvas');
|
||||||
|
canvas.width = width;
|
||||||
|
canvas.height = height;
|
||||||
|
let ctx = canvas.getContext('2d');
|
||||||
|
let imgData = ctx.createImageData(width, height);
|
||||||
|
|
||||||
|
imgData.data.set(pixels);
|
||||||
|
ctx.putImageData(imgData, 0, 0);
|
||||||
|
|
||||||
|
let child = target.appendChild(canvas);
|
||||||
|
child.classList.add('blurhash-canvas');
|
||||||
|
child.style.opacity = 1;
|
||||||
|
if (userSettings.enableFastFadein()) {
|
||||||
|
child.classList.add('lazy-blurhash-fadein-fast');
|
||||||
|
} else {
|
||||||
|
child.classList.add('lazy-blurhash-fadein');
|
||||||
|
}
|
||||||
|
|
||||||
|
target.classList.add('blurhashed');
|
||||||
|
target.removeAttribute('data-blurhash');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function switchCanvas(elem) {
|
||||||
|
let child = elem.getElementsByClassName('blurhash-canvas')[0];
|
||||||
|
if (child) {
|
||||||
|
child.style.opacity = elem.getAttribute('data-src') ? 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function fillImage(entry) {
|
export function fillImage(entry) {
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
throw new Error('entry cannot be null');
|
throw new Error('entry cannot be null');
|
||||||
}
|
}
|
||||||
|
let target = entry.target;
|
||||||
var source = undefined;
|
var source = undefined;
|
||||||
if (entry.target) {
|
|
||||||
source = entry.target.getAttribute('data-src');
|
if (target) {
|
||||||
|
source = target.getAttribute('data-src');
|
||||||
|
var blurhashstr = target.getAttribute('data-blurhash');
|
||||||
} else {
|
} else {
|
||||||
source = entry;
|
source = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (userSettings.enableBlurhash()) {
|
||||||
|
if (!target.classList.contains('blurhashed', 'non-blurhashable') && blurhashstr) {
|
||||||
|
itemBlurhashing(target, blurhashstr);
|
||||||
|
} else if (!blurhashstr && !target.classList.contains('blurhashed')) {
|
||||||
|
target.classList.add('non-blurhashable');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (entry.intersectionRatio > 0) {
|
if (entry.intersectionRatio > 0) {
|
||||||
if (source) fillImageElement(entry.target, source);
|
if (source) fillImageElement(target, source);
|
||||||
} else if (!source) {
|
} else if (!source) {
|
||||||
emptyImageElement(entry.target);
|
emptyImageElement(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function fillImageElement(elem, url) {
|
function fillImageElement(elem, url) {
|
||||||
if (url === undefined) {
|
if (url === undefined) {
|
||||||
throw new Error('url cannot be undefined');
|
throw new TypeError('url cannot be undefined');
|
||||||
}
|
}
|
||||||
|
|
||||||
let preloaderImg = new Image();
|
let preloaderImg = new Image();
|
||||||
preloaderImg.src = url;
|
preloaderImg.src = url;
|
||||||
|
|
||||||
|
// This is necessary here, so changing blurhash settings without reloading the page works
|
||||||
|
if (!userSettings.enableBlurhash() || elem.classList.contains('non-blurhashable')) {
|
||||||
|
elem.classList.add('lazy-hidden');
|
||||||
|
}
|
||||||
|
|
||||||
preloaderImg.addEventListener('load', () => {
|
preloaderImg.addEventListener('load', () => {
|
||||||
if (elem.tagName !== 'IMG') {
|
if (elem.tagName !== 'IMG') {
|
||||||
elem.style.backgroundImage = "url('" + url + "')";
|
elem.style.backgroundImage = "url('" + url + "')";
|
||||||
} else {
|
} else {
|
||||||
elem.setAttribute('src', url);
|
elem.setAttribute('src', url);
|
||||||
}
|
}
|
||||||
|
elem.removeAttribute('data-src');
|
||||||
|
|
||||||
|
if (elem.classList.contains('non-blurhashable') || !userSettings.enableBlurhash()) {
|
||||||
|
elem.classList.remove('lazy-hidden');
|
||||||
if (userSettings.enableFastFadein()) {
|
if (userSettings.enableFastFadein()) {
|
||||||
elem.classList.add('lazy-image-fadein-fast');
|
elem.classList.add('lazy-image-fadein-fast');
|
||||||
} else {
|
} else {
|
||||||
elem.classList.add('lazy-image-fadein');
|
elem.classList.add('lazy-image-fadein');
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
elem.removeAttribute('data-src');
|
switchCanvas(elem);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,11 +130,14 @@ import 'css!./style';
|
||||||
url = elem.getAttribute('src');
|
url = elem.getAttribute('src');
|
||||||
elem.setAttribute('src', '');
|
elem.setAttribute('src', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
elem.setAttribute('data-src', url);
|
elem.setAttribute('data-src', url);
|
||||||
|
|
||||||
elem.classList.remove('lazy-image-fadein-fast');
|
if (elem.classList.contains('non-blurhashable') || !userSettings.enableBlurhash()) {
|
||||||
elem.classList.remove('lazy-image-fadein');
|
elem.classList.remove('lazy-image-fadein-fast', 'lazy-image-fadein');
|
||||||
|
elem.classList.add('lazy-hidden');
|
||||||
|
} else {
|
||||||
|
switchCanvas(elem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function lazyChildren(elem) {
|
export function lazyChildren(elem) {
|
||||||
|
|
|
@ -1,13 +1,33 @@
|
||||||
.cardImageContainer.lazy {
|
.lazy-image-fadein {
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lazy-image-fadein-fast {
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity 0.1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lazy-hidden {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardImageContainer.lazy.lazy-image-fadein {
|
.lazy-blurhash-fadein-fast {
|
||||||
opacity: 1;
|
transition: opacity 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lazy-blurhash-fadein {
|
||||||
transition: opacity 0.7s;
|
transition: opacity 0.7s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardImageContainer.lazy.lazy-image-fadein-fast {
|
.blurhash-canvas {
|
||||||
opacity: 1;
|
position: absolute;
|
||||||
transition: opacity 0.2s;
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 100;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -403,7 +403,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
||||||
break;
|
break;
|
||||||
case 'moremediainfo':
|
case 'moremediainfo':
|
||||||
require(['itemMediaInfo'], function (itemMediaInfo) {
|
require(['itemMediaInfo'], function (itemMediaInfo) {
|
||||||
itemMediaInfo.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
itemMediaInfo.show(itemId, serverId).then(getResolveFunction(resolve, id), getResolveFunction(resolve, id));
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'refresh':
|
case 'refresh':
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
(entries) => {
|
(entries) => {
|
||||||
entries.forEach(entry => {
|
entries.forEach(entry => {
|
||||||
callback(entry);
|
callback(entry);
|
||||||
},
|
|
||||||
{rootMargin: '50%'});
|
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
{rootMargin: '25%'});
|
||||||
|
|
||||||
this.observer = observer;
|
this.observer = observer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||||
function getImageUrl(item, width) {
|
function getImageUrl(item, width) {
|
||||||
|
|
||||||
var apiClient = connectionManager.getApiClient(item.ServerId);
|
var apiClient = connectionManager.getApiClient(item.ServerId);
|
||||||
|
let itemId;
|
||||||
|
|
||||||
var options = {
|
var options = {
|
||||||
maxWidth: width * 2,
|
maxWidth: width * 2,
|
||||||
|
@ -77,45 +78,45 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||||
};
|
};
|
||||||
|
|
||||||
if (item.ImageTags && item.ImageTags.Primary) {
|
if (item.ImageTags && item.ImageTags.Primary) {
|
||||||
|
|
||||||
options.tag = item.ImageTags.Primary;
|
options.tag = item.ImageTags.Primary;
|
||||||
return apiClient.getScaledImageUrl(item.Id, options);
|
itemId = item.Id;
|
||||||
}
|
} else if (item.AlbumId && item.AlbumPrimaryImageTag) {
|
||||||
|
|
||||||
if (item.AlbumId && item.AlbumPrimaryImageTag) {
|
|
||||||
|
|
||||||
options.tag = item.AlbumPrimaryImageTag;
|
options.tag = item.AlbumPrimaryImageTag;
|
||||||
return apiClient.getScaledImageUrl(item.AlbumId, options);
|
itemId = item.AlbumId;
|
||||||
} else if (item.SeriesId && item.SeriesPrimaryImageTag) {
|
} else if (item.SeriesId && item.SeriesPrimaryImageTag) {
|
||||||
|
|
||||||
options.tag = item.SeriesPrimaryImageTag;
|
options.tag = item.SeriesPrimaryImageTag;
|
||||||
return apiClient.getScaledImageUrl(item.SeriesId, options);
|
itemId = item.SeriesId;
|
||||||
|
|
||||||
} else if (item.ParentPrimaryImageTag) {
|
} else if (item.ParentPrimaryImageTag) {
|
||||||
|
|
||||||
options.tag = item.ParentPrimaryImageTag;
|
options.tag = item.ParentPrimaryImageTag;
|
||||||
return apiClient.getScaledImageUrl(item.ParentPrimaryImageItemId, options);
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getChannelImageUrl(item, width) {
|
function getChannelImageUrl(item, width) {
|
||||||
|
|
||||||
var apiClient = connectionManager.getApiClient(item.ServerId);
|
var apiClient = connectionManager.getApiClient(item.ServerId);
|
||||||
|
|
||||||
var options = {
|
var options = {
|
||||||
maxWidth: width * 2,
|
maxWidth: width * 2,
|
||||||
type: 'Primary'
|
type: 'Primary'
|
||||||
};
|
};
|
||||||
|
|
||||||
if (item.ChannelId && item.ChannelPrimaryImageTag) {
|
if (item.ChannelId && item.ChannelPrimaryImageTag) {
|
||||||
|
|
||||||
options.tag = item.ChannelPrimaryImageTag;
|
options.tag = item.ChannelPrimaryImageTag;
|
||||||
return apiClient.getScaledImageUrl(item.ChannelId, options);
|
|
||||||
}
|
}
|
||||||
|
let blurHashes = item.ImageBlurHashes || {};
|
||||||
|
let blurhashstr = (blurHashes[options.type])[options.tag];
|
||||||
|
|
||||||
return null;
|
if (item.ChannelId) {
|
||||||
|
return { url: apiClient.getScaledImageUrl(item.ChannelId, options), blurhash: blurhashstr };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTextLinesHtml(textlines, isLargeStyle) {
|
function getTextLinesHtml(textlines, isLargeStyle) {
|
||||||
|
@ -268,8 +269,10 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.image !== false) {
|
if (options.image !== false) {
|
||||||
var imgUrl = options.imageSource === 'channel' ? getChannelImageUrl(item, downloadWidth) : getImageUrl(item, downloadWidth);
|
let imgData = options.imageSource === 'channel' ? getChannelImageUrl(item, downloadWidth) : getImageUrl(item, downloadWidth);
|
||||||
var imageClass = isLargeStyle ? 'listItemImage listItemImage-large' : 'listItemImage';
|
let imgUrl = imgData.url;
|
||||||
|
let blurhash = imgData.blurhash;
|
||||||
|
let imageClass = isLargeStyle ? 'listItemImage listItemImage-large' : 'listItemImage';
|
||||||
|
|
||||||
if (isLargeStyle && layoutManager.tv) {
|
if (isLargeStyle && layoutManager.tv) {
|
||||||
imageClass += ' listItemImage-large-tv';
|
imageClass += ' listItemImage-large-tv';
|
||||||
|
@ -283,8 +286,13 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||||
|
|
||||||
var imageAction = playOnImageClick ? 'resume' : action;
|
var imageAction = playOnImageClick ? 'resume' : action;
|
||||||
|
|
||||||
|
let blurhashAttrib = '';
|
||||||
|
if (blurhash && blurhash.length > 0) {
|
||||||
|
blurhashAttrib = 'data-blurhash="' + blurhash + '"';
|
||||||
|
}
|
||||||
|
|
||||||
if (imgUrl) {
|
if (imgUrl) {
|
||||||
html += '<div data-action="' + imageAction + '" class="' + imageClass + ' lazy" data-src="' + imgUrl + '" item-icon>';
|
html += '<div data-action="' + imageAction + '" class="' + imageClass + ' lazy" data-src="' + imgUrl + '" ' + blurhashAttrib + ' item-icon>';
|
||||||
} else {
|
} else {
|
||||||
html += '<div class="' + imageClass + '">';
|
html += '<div class="' + imageClass + '">';
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
});
|
|
|
@ -273,7 +273,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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') {
|
if (item.Type === 'Audio') {
|
||||||
|
|
||||||
|
|
|
@ -308,8 +308,8 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
context.removeEventListener('submit', onEditorClick);
|
context.removeEventListener('click', onEditorClick);
|
||||||
context.addEventListener('submit', onEditorClick);
|
context.addEventListener('click', onEditorClick);
|
||||||
|
|
||||||
var form = context.querySelector('form');
|
var form = context.querySelector('form');
|
||||||
form.removeEventListener('submit', onSubmit);
|
form.removeEventListener('submit', onSubmit);
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
<div class="formDialogContent smoothScrollY" style="padding-top:2em;">
|
<div class="formDialogContent smoothScrollY" style="padding-top:2em;">
|
||||||
<form class="popupEditPersonForm dialogContentInner dialog-content-centered">
|
<form class="popupEditPersonForm dialogContentInner dialog-content-centered">
|
||||||
|
|
||||||
<div class="inputContainer">
|
<div class="inputContainer">
|
||||||
<input type="text" is="emby-input" class="txtPersonName" required="required" label="${LabelName}" />
|
<input type="text" is="emby-input" class="txtPersonName" required="required" label="${LabelName}" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -23,6 +22,7 @@
|
||||||
<option value="Writer">${Writer}</option>
|
<option value="Writer">${Writer}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="inputContainer fldRole hide">
|
<div class="inputContainer fldRole hide">
|
||||||
<input is="emby-input" type="text" class="txtPersonRole" label="${LabelPersonRole}" />
|
<input is="emby-input" type="text" class="txtPersonRole" label="${LabelPersonRole}" />
|
||||||
<div class="fieldDescription">${LabelPersonRoleHelp}</div>
|
<div class="fieldDescription">${LabelPersonRoleHelp}</div>
|
||||||
|
@ -33,6 +33,5 @@
|
||||||
<span>${Save}</span>
|
<span>${Save}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
define(['events', 'playbackManager', 'dom', 'browser', 'css!./iconosd', 'material-icons'], function (events, playbackManager, dom, browser) {
|
import events from 'events';
|
||||||
'use strict';
|
import playbackManager from 'playbackManager';
|
||||||
|
import dom from 'dom';
|
||||||
|
import browser from 'browser';
|
||||||
|
import 'css!./iconosd';
|
||||||
|
import 'material-icons';
|
||||||
|
|
||||||
var currentPlayer;
|
var currentPlayer;
|
||||||
var osdElement;
|
var osdElement;
|
||||||
|
@ -99,9 +103,7 @@ define(['events', 'playbackManager', 'dom', 'browser', 'css!./iconosd', 'materia
|
||||||
}
|
}
|
||||||
|
|
||||||
function setIcon(iconElement, icon) {
|
function setIcon(iconElement, icon) {
|
||||||
iconElement.classList.remove('brightness_high');
|
iconElement.classList.remove('brightness_high', 'brightness_medium', 'brightness_low');
|
||||||
iconElement.classList.remove('brightness_medium');
|
|
||||||
iconElement.classList.remove('brightness_low');
|
|
||||||
iconElement.classList.add(icon);
|
iconElement.classList.add(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,5 +169,3 @@ define(['events', 'playbackManager', 'dom', 'browser', 'css!./iconosd', 'materia
|
||||||
});
|
});
|
||||||
|
|
||||||
bindToPlayer(playbackManager.getCurrentPlayer());
|
bindToPlayer(playbackManager.getCurrentPlayer());
|
||||||
|
|
||||||
});
|
|
||||||
|
|
|
@ -241,6 +241,15 @@ import connectionManager from 'connectionManager';
|
||||||
navigator.mediaSession.setActionHandler('seekforward', function () {
|
navigator.mediaSession.setActionHandler('seekforward', function () {
|
||||||
execute('fastForward');
|
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 () {
|
events.on(playbackManager, 'playerchange', function () {
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
define([], function () {
|
export function getNowPlayingNames(nowPlayingItem, includeNonNameInfo) {
|
||||||
'use strict';
|
|
||||||
|
|
||||||
function getNowPlayingNames(nowPlayingItem, includeNonNameInfo) {
|
|
||||||
|
|
||||||
var topItem = nowPlayingItem;
|
var topItem = nowPlayingItem;
|
||||||
var bottomItem = null;
|
var bottomItem = null;
|
||||||
|
@ -80,7 +77,6 @@ define([], function () {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
export default {
|
||||||
getNowPlayingNames: getNowPlayingNames
|
getNowPlayingNames: getNowPlayingNames
|
||||||
};
|
};
|
||||||
});
|
|
||||||
|
|
|
@ -1907,11 +1907,8 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla
|
||||||
// Setting this to true may cause some incorrect sorting
|
// Setting this to true may cause some incorrect sorting
|
||||||
Recursive: false,
|
Recursive: false,
|
||||||
SortBy: options.shuffle ? 'Random' : 'SortName',
|
SortBy: options.shuffle ? 'Random' : 'SortName',
|
||||||
MediaTypes: 'Photo,Video',
|
MediaTypes: 'Photo,Video'
|
||||||
Limit: 500
|
|
||||||
|
|
||||||
}).then(function (result) {
|
}).then(function (result) {
|
||||||
|
|
||||||
var items = result.Items;
|
var items = result.Items;
|
||||||
|
|
||||||
var index = items.map(function (i) {
|
var index = items.map(function (i) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
define(['playbackManager', 'layoutManager', 'events'], function (playbackManager, layoutManager, events) {
|
import playbackManager from 'playbackManager';
|
||||||
'use strict';
|
import layoutManager from 'layoutManager';
|
||||||
|
import events from 'events';
|
||||||
|
|
||||||
var orientationLocked;
|
var orientationLocked;
|
||||||
|
|
||||||
|
@ -54,4 +55,3 @@ define(['playbackManager', 'layoutManager', 'events'], function (playbackManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
define(['appSettings', 'events', 'browser', 'loading', 'playbackManager', 'appRouter', 'globalize', 'apphost'], function (appSettings, events, browser, loading, playbackManager, appRouter, globalize, appHost) {
|
import appSettings from 'appSettings';
|
||||||
'use strict';
|
import events from 'events';
|
||||||
|
import browser from 'browser';
|
||||||
|
import loading from 'loading';
|
||||||
|
import playbackManager from 'playbackManager';
|
||||||
|
import appRouter from 'appRouter';
|
||||||
|
import globalize from 'globalize';
|
||||||
|
import appHost from 'apphost';
|
||||||
|
|
||||||
function mirrorItem(info, player) {
|
function mirrorItem(info, player) {
|
||||||
|
|
||||||
|
@ -77,7 +83,7 @@ define(['appSettings', 'events', 'browser', 'loading', 'playbackManager', 'appRo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showPlayerSelection(button) {
|
export function show(button) {
|
||||||
|
|
||||||
var currentPlayerInfo = playbackManager.getPlayerInfo();
|
var currentPlayerInfo = playbackManager.getPlayerInfo();
|
||||||
|
|
||||||
|
@ -314,7 +320,6 @@ define(['appSettings', 'events', 'browser', 'loading', 'playbackManager', 'appRo
|
||||||
loading.hide();
|
loading.hide();
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
export default {
|
||||||
show: showPlayerSelection
|
show: show
|
||||||
};
|
};
|
||||||
});
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
define(['connectionManager', 'actionsheet', 'datetime', 'playbackManager', 'globalize', 'appSettings', 'qualityoptions'], function (connectionManager, actionsheet, datetime, playbackManager, globalize, appSettings, qualityoptions) {
|
import connectionManager from 'connectionManager';
|
||||||
'use strict';
|
import actionsheet from 'actionsheet';
|
||||||
|
import playbackManager from 'playbackManager';
|
||||||
|
import globalize from 'globalize';
|
||||||
|
import qualityoptions from 'qualityoptions';
|
||||||
|
|
||||||
function showQualityMenu(player, btn) {
|
function showQualityMenu(player, btn) {
|
||||||
|
|
||||||
|
@ -225,7 +228,7 @@ define(['connectionManager', 'actionsheet', 'datetime', 'playbackManager', 'glob
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function show(options) {
|
export function show(options) {
|
||||||
var player = options.player;
|
var player = options.player;
|
||||||
var currentItem = playbackManager.currentItem(player);
|
var currentItem = playbackManager.currentItem(player);
|
||||||
|
|
||||||
|
@ -264,7 +267,6 @@ define(['connectionManager', 'actionsheet', 'datetime', 'playbackManager', 'glob
|
||||||
return Promise.reject();
|
return Promise.reject();
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
export default {
|
||||||
show: show
|
show: show
|
||||||
};
|
};
|
||||||
});
|
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
define([], function () {
|
export function getDisplayPlayMethod(session) {
|
||||||
'use strict';
|
|
||||||
|
|
||||||
function getDisplayPlayMethod(session) {
|
|
||||||
|
|
||||||
if (!session.NowPlayingItem) {
|
if (!session.NowPlayingItem) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -18,7 +15,6 @@ define([], function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
export default {
|
||||||
getDisplayPlayMethod: getDisplayPlayMethod
|
getDisplayPlayMethod: getDisplayPlayMethod
|
||||||
};
|
};
|
||||||
});
|
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
define(['events', 'playbackManager', 'dom', 'browser', 'css!./iconosd', 'material-icons'], function (events, playbackManager, dom, browser) {
|
import events from 'events';
|
||||||
'use strict';
|
import playbackManager from 'playbackManager';
|
||||||
|
import dom from 'dom';
|
||||||
|
import browser from 'browser';
|
||||||
|
import 'css!./iconosd';
|
||||||
|
import 'material-icons';
|
||||||
|
|
||||||
var currentPlayer;
|
var currentPlayer;
|
||||||
var osdElement;
|
var osdElement;
|
||||||
|
@ -155,5 +159,3 @@ define(['events', 'playbackManager', 'dom', 'browser', 'css!./iconosd', 'materia
|
||||||
});
|
});
|
||||||
|
|
||||||
bindToPlayer(playbackManager.getCurrentPlayer());
|
bindToPlayer(playbackManager.getCurrentPlayer());
|
||||||
|
|
||||||
});
|
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1">
|
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1">
|
||||||
<span class="material-icons arrow_back"></span>
|
<span class="material-icons arrow_back"></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<h3 class="formDialogHeaderTitle"></h3>
|
<h3 class="formDialogHeaderTitle"></h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="formDialogContent smoothScrollY">
|
<div class="formDialogContent smoothScrollY">
|
||||||
<div class="dialogContentInner dialog-content-centered" style="padding-top:2em;">
|
<div class="dialogContentInner dialog-content-centered" style="padding-top:2em;">
|
||||||
|
|
||||||
<form>
|
<form>
|
||||||
<div class="inputContainer">
|
<div class="inputContainer">
|
||||||
<input is="emby-input" type="text" id="txtInput" label="" />
|
<input is="emby-input" type="text" id="txtInput" label="" />
|
||||||
|
@ -19,7 +19,6 @@
|
||||||
<span class="submitText"></span>
|
<span class="submitText"></span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -196,7 +196,7 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
|
||||||
context.querySelector('.nowPlayingPageImage').classList.remove('nowPlayingPageImageAudio');
|
context.querySelector('.nowPlayingPageImage').classList.remove('nowPlayingPageImageAudio');
|
||||||
}
|
}
|
||||||
} else {
|
} 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>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
});
|
|
|
@ -2,9 +2,20 @@
|
||||||
* Image viewer component
|
* Image viewer component
|
||||||
* @module components/slideshow/slideshow
|
* @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';
|
'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.
|
* Retrieves an item's image URL from the API.
|
||||||
* @param {object|string} item - Item used to generate the image URL.
|
* @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.
|
* Initializes the Swiper instance and binds the relevant events.
|
||||||
* @param {HTMLElement} dialog - Element containing the dialog.
|
* @param {HTMLElement} dialog - Element containing the dialog.
|
||||||
|
@ -260,8 +306,7 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f
|
||||||
loop: false,
|
loop: false,
|
||||||
zoom: {
|
zoom: {
|
||||||
minRatio: 1,
|
minRatio: 1,
|
||||||
toggle: true,
|
toggle: true
|
||||||
containerClass: 'slider-zoom-container'
|
|
||||||
},
|
},
|
||||||
autoplay: !options.interactive,
|
autoplay: !options.interactive,
|
||||||
keyboard: {
|
keyboard: {
|
||||||
|
@ -288,6 +333,10 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f
|
||||||
|
|
||||||
swiperInstance.on('autoplayStart', onAutoplayStart);
|
swiperInstance.on('autoplayStart', onAutoplayStart);
|
||||||
swiperInstance.on('autoplayStop', onAutoplayStop);
|
swiperInstance.on('autoplayStop', onAutoplayStop);
|
||||||
|
|
||||||
|
if (useFakeZoomImage) {
|
||||||
|
swiperInstance.on('zoomChange', onZoomChange);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,7 +377,10 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f
|
||||||
function getSwiperSlideHtmlFromSlide(item) {
|
function getSwiperSlideHtmlFromSlide(item) {
|
||||||
var html = '';
|
var html = '';
|
||||||
html += '<div class="swiper-slide" data-original="' + item.originalImage + '" data-itemid="' + item.Id + '" data-serverid="' + item.ServerId + '">';
|
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 += '<img src="' + item.originalImage + '" class="swiper-slide-img">';
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
if (item.title || item.subtitle) {
|
if (item.title || item.subtitle) {
|
||||||
|
|
|
@ -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;
|
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 {
|
.slideshowButtonIcon {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
|
@ -135,13 +125,18 @@
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.swiper-slide {
|
.swiper-zoom-fakeimg {
|
||||||
display: flex;
|
position: absolute;
|
||||||
flex-direction: column;
|
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 {
|
.swiper-zoom-fakeimg-hidden {
|
||||||
margin: auto;
|
display: none;
|
||||||
max-height: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Module that manages the SyncPlay feature.
|
* Module that manages the SyncPlay feature.
|
||||||
* @module components/syncplay/syncPlayManager
|
* @module components/syncPlay/syncPlayManager
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import events from 'events';
|
import events from 'events';
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* Module that manages time syncing with server.
|
* Module that manages time syncing with server.
|
||||||
* @module components/syncplay/timeSyncManager
|
* @module components/syncPlay/timeSyncManager
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import events from 'events';
|
import events from 'events';
|
||||||
|
@ -65,8 +65,6 @@ class TimeSyncManager {
|
||||||
this.pings = 0; // number of pings
|
this.pings = 0; // number of pings
|
||||||
this.measurement = null; // current time sync
|
this.measurement = null; // current time sync
|
||||||
this.measurements = [];
|
this.measurements = [];
|
||||||
|
|
||||||
this.startPing();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -43,10 +43,6 @@ define(['browser', 'dom', 'layoutManager', 'css!components/viewManager/viewConta
|
||||||
var newView = newViewInfo.elem;
|
var newView = newViewInfo.elem;
|
||||||
var modulesToLoad = [];
|
var modulesToLoad = [];
|
||||||
|
|
||||||
if (isPluginpage) {
|
|
||||||
modulesToLoad.push('legacyDashboard');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newViewInfo.hasjQuerySelect) {
|
if (newViewInfo.hasjQuerySelect) {
|
||||||
modulesToLoad.push('legacySelectMenu');
|
modulesToLoad.push('legacySelectMenu');
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,11 @@ define(['viewContainer', 'focusManager', 'queryString', 'layoutManager'], functi
|
||||||
if (!newView.initComplete) {
|
if (!newView.initComplete) {
|
||||||
newView.initComplete = true;
|
newView.initComplete = true;
|
||||||
|
|
||||||
|
var controller;
|
||||||
if (typeof options.controllerFactory === 'function') {
|
if (typeof options.controllerFactory === 'function') {
|
||||||
|
controller = new options.controllerFactory(newView, eventDetail.detail.params);
|
||||||
// Use controller method
|
} else if (options.controllerFactory && typeof options.controllerFactory.default === 'function') {
|
||||||
var controller = new options.controllerFactory(newView, eventDetail.detail.params);
|
controller = new options.controllerFactory.default(newView, eventDetail.detail.params);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.controllerFactory || dispatchPageEvents) {
|
if (!options.controllerFactory || dispatchPageEvents) {
|
||||||
|
|
|
@ -57,7 +57,7 @@ define(['require', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'conne
|
||||||
|
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
|
|
||||||
require(['text!./viewsettings.template.html'], function (template) {
|
require(['text!./viewSettings.template.html'], function (template) {
|
||||||
|
|
||||||
var dialogOptions = {
|
var dialogOptions = {
|
||||||
removeOnClose: true,
|
removeOnClose: true,
|
1
src/config.json
Symbolic link
1
src/config.json
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
config.template.json
|
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"multiserver": true
|
"multiserver": false
|
||||||
}
|
}
|
||||||
|
|
|
@ -252,12 +252,6 @@ define(['datetime', 'events', 'itemHelper', 'serverNotifications', 'dom', 'globa
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
|
||||||
if (session.TranscodingInfo && session.TranscodingInfo.Framerate) {
|
|
||||||
html += '<div class="sessionTranscodingFramerate">' + session.TranscodingInfo.Framerate + ' fps</div>';
|
|
||||||
} else {
|
|
||||||
html += '<div class="sessionTranscodingFramerate"></div>';
|
|
||||||
}
|
|
||||||
|
|
||||||
html += '<div class="sessionNowPlayingDetails">';
|
html += '<div class="sessionNowPlayingDetails">';
|
||||||
var nowPlayingName = DashboardPage.getNowPlayingName(session);
|
var nowPlayingName = DashboardPage.getNowPlayingName(session);
|
||||||
html += '<div class="sessionNowPlayingInfo" data-imgsrc="' + nowPlayingName.image + '">';
|
html += '<div class="sessionNowPlayingInfo" data-imgsrc="' + nowPlayingName.image + '">';
|
||||||
|
@ -573,7 +567,6 @@ define(['datetime', 'events', 'itemHelper', 'serverNotifications', 'dom', 'globa
|
||||||
row.querySelector('.sessionNowPlayingTime').innerHTML = DashboardPage.getSessionNowPlayingTime(session);
|
row.querySelector('.sessionNowPlayingTime').innerHTML = DashboardPage.getSessionNowPlayingTime(session);
|
||||||
row.querySelector('.sessionUserName').innerHTML = DashboardPage.getUsersHtml(session);
|
row.querySelector('.sessionUserName').innerHTML = DashboardPage.getUsersHtml(session);
|
||||||
row.querySelector('.sessionAppSecondaryText').innerHTML = DashboardPage.getAppSecondaryText(session);
|
row.querySelector('.sessionAppSecondaryText').innerHTML = DashboardPage.getAppSecondaryText(session);
|
||||||
row.querySelector('.sessionTranscodingFramerate').innerHTML = session.TranscodingInfo && session.TranscodingInfo.Framerate ? session.TranscodingInfo.Framerate + ' fps' : '';
|
|
||||||
var nowPlayingName = DashboardPage.getNowPlayingName(session);
|
var nowPlayingName = DashboardPage.getNowPlayingName(session);
|
||||||
var nowPlayingInfoElem = row.querySelector('.sessionNowPlayingInfo');
|
var nowPlayingInfoElem = row.querySelector('.sessionNowPlayingInfo');
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,8 @@ define(['jQuery', 'loading', 'globalize', 'emby-select', 'emby-button', 'emby-in
|
||||||
$('.chkMediaType', page).each(function () {
|
$('.chkMediaType', page).each(function () {
|
||||||
this.checked = -1 != (profile.SupportedMediaTypes || '').split(',').indexOf(this.getAttribute('data-value'));
|
this.checked = -1 != (profile.SupportedMediaTypes || '').split(',').indexOf(this.getAttribute('data-value'));
|
||||||
});
|
});
|
||||||
$('#chkEnableAlbumArtInDidl', page).checked = profile.EnableAlbumArtInDidl;
|
$('#chkEnableAlbumArtInDidl', page).prop('checked', profile.EnableAlbumArtInDidl);
|
||||||
$('#chkEnableSingleImageLimit', page).checked = profile.EnableSingleAlbumArtLimit;
|
$('#chkEnableSingleImageLimit', page).prop('checked', profile.EnableSingleAlbumArtLimit);
|
||||||
renderXmlDocumentAttributes(page, profile.XmlRootAttributes || []);
|
renderXmlDocumentAttributes(page, profile.XmlRootAttributes || []);
|
||||||
var idInfo = profile.Identification || {};
|
var idInfo = profile.Identification || {};
|
||||||
renderIdentificationHeaders(page, idInfo.Headers || []);
|
renderIdentificationHeaders(page, idInfo.Headers || []);
|
||||||
|
@ -51,11 +51,11 @@ define(['jQuery', 'loading', 'globalize', 'emby-select', 'emby-button', 'emby-in
|
||||||
$('#txtAlbumArtMaxHeight', page).val(profile.MaxAlbumArtHeight || '');
|
$('#txtAlbumArtMaxHeight', page).val(profile.MaxAlbumArtHeight || '');
|
||||||
$('#txtIconMaxWidth', page).val(profile.MaxIconWidth || '');
|
$('#txtIconMaxWidth', page).val(profile.MaxIconWidth || '');
|
||||||
$('#txtIconMaxHeight', page).val(profile.MaxIconHeight || '');
|
$('#txtIconMaxHeight', page).val(profile.MaxIconHeight || '');
|
||||||
$('#chkIgnoreTranscodeByteRangeRequests', page).checked = profile.IgnoreTranscodeByteRangeRequests;
|
$('#chkIgnoreTranscodeByteRangeRequests', page).prop('checked', profile.IgnoreTranscodeByteRangeRequests);
|
||||||
$('#txtMaxAllowedBitrate', page).val(profile.MaxStreamingBitrate || '');
|
$('#txtMaxAllowedBitrate', page).val(profile.MaxStreamingBitrate || '');
|
||||||
$('#txtMusicStreamingTranscodingBitrate', page).val(profile.MusicStreamingTranscodingBitrate || '');
|
$('#txtMusicStreamingTranscodingBitrate', page).val(profile.MusicStreamingTranscodingBitrate || '');
|
||||||
$('#chkRequiresPlainFolders', page).checked = profile.RequiresPlainFolders;
|
$('#chkRequiresPlainFolders', page).prop('checked', profile.RequiresPlainFolders);
|
||||||
$('#chkRequiresPlainVideoItems', page).checked = profile.RequiresPlainVideoItems;
|
$('#chkRequiresPlainVideoItems', page).prop('checked', profile.RequiresPlainVideoItems);
|
||||||
$('#txtProtocolInfo', page).val(profile.ProtocolInfo || '');
|
$('#txtProtocolInfo', page).val(profile.ProtocolInfo || '');
|
||||||
$('#txtXDlnaCap', page).val(profile.XDlnaCap || '');
|
$('#txtXDlnaCap', page).val(profile.XDlnaCap || '');
|
||||||
$('#txtXDlnaDoc', page).val(profile.XDlnaDoc || '');
|
$('#txtXDlnaDoc', page).val(profile.XDlnaDoc || '');
|
||||||
|
@ -357,9 +357,9 @@ define(['jQuery', 'loading', 'globalize', 'emby-select', 'emby-button', 'emby-in
|
||||||
$('#txtTranscodingAudioCodec', popup).val(transcodingProfile.AudioCodec || '');
|
$('#txtTranscodingAudioCodec', popup).val(transcodingProfile.AudioCodec || '');
|
||||||
$('#txtTranscodingVideoCodec', popup).val(transcodingProfile.VideoCodec || '');
|
$('#txtTranscodingVideoCodec', popup).val(transcodingProfile.VideoCodec || '');
|
||||||
$('#selectTranscodingProtocol', popup).val(transcodingProfile.Protocol || 'Http');
|
$('#selectTranscodingProtocol', popup).val(transcodingProfile.Protocol || 'Http');
|
||||||
$('#chkEnableMpegtsM2TsMode', popup).checked = transcodingProfile.EnableMpegtsM2TsMode || false;
|
$('#chkEnableMpegtsM2TsMode', popup).prop('checked', transcodingProfile.EnableMpegtsM2TsMode || false);
|
||||||
$('#chkEstimateContentLength', popup).checked = transcodingProfile.EstimateContentLength || false;
|
$('#chkEstimateContentLength', popup).prop('checked', transcodingProfile.EstimateContentLength || false);
|
||||||
$('#chkReportByteRangeRequests', popup).checked = 'Bytes' == transcodingProfile.TranscodeSeekInfo;
|
$('#chkReportByteRangeRequests', popup).prop('checked', 'Bytes' == transcodingProfile.TranscodeSeekInfo);
|
||||||
$('.radioTabButton:first', popup).trigger('click');
|
$('.radioTabButton:first', popup).trigger('click');
|
||||||
openPopup(popup[0]);
|
openPopup(popup[0]);
|
||||||
}
|
}
|
||||||
|
@ -376,9 +376,9 @@ define(['jQuery', 'loading', 'globalize', 'emby-select', 'emby-button', 'emby-in
|
||||||
currentSubProfile.VideoCodec = $('#txtTranscodingVideoCodec', page).val();
|
currentSubProfile.VideoCodec = $('#txtTranscodingVideoCodec', page).val();
|
||||||
currentSubProfile.Protocol = $('#selectTranscodingProtocol', page).val();
|
currentSubProfile.Protocol = $('#selectTranscodingProtocol', page).val();
|
||||||
currentSubProfile.Context = 'Streaming';
|
currentSubProfile.Context = 'Streaming';
|
||||||
currentSubProfile.EnableMpegtsM2TsMode = $('#chkEnableMpegtsM2TsMode', page).checked;
|
currentSubProfile.EnableMpegtsM2TsMode = $('#chkEnableMpegtsM2TsMode', page).is(':checked');
|
||||||
currentSubProfile.EstimateContentLength = $('#chkEstimateContentLength', page).checked;
|
currentSubProfile.EstimateContentLength = $('#chkEstimateContentLength', page).is(':checked');
|
||||||
currentSubProfile.TranscodeSeekInfo = $('#chkReportByteRangeRequests', page).checked ? 'Bytes' : 'Auto';
|
currentSubProfile.TranscodeSeekInfo = $('#chkReportByteRangeRequests', page).is(':checked') ? 'Bytes' : 'Auto';
|
||||||
|
|
||||||
if (isSubProfileNew) {
|
if (isSubProfileNew) {
|
||||||
currentProfile.TranscodingProfiles.push(currentSubProfile);
|
currentProfile.TranscodingProfiles.push(currentSubProfile);
|
||||||
|
@ -647,8 +647,8 @@ define(['jQuery', 'loading', 'globalize', 'emby-select', 'emby-button', 'emby-in
|
||||||
|
|
||||||
function updateProfile(page, profile) {
|
function updateProfile(page, profile) {
|
||||||
profile.Name = $('#txtName', page).val();
|
profile.Name = $('#txtName', page).val();
|
||||||
profile.EnableAlbumArtInDidl = $('#chkEnableAlbumArtInDidl', page).checked;
|
profile.EnableAlbumArtInDidl = $('#chkEnableAlbumArtInDidl', page).is(':checked');
|
||||||
profile.EnableSingleAlbumArtLimit = $('#chkEnableSingleImageLimit', page).checked;
|
profile.EnableSingleAlbumArtLimit = $('#chkEnableSingleImageLimit', page).is(':checked');
|
||||||
profile.SupportedMediaTypes = $('.chkMediaType:checked', page).get().map(function (c) {
|
profile.SupportedMediaTypes = $('.chkMediaType:checked', page).get().map(function (c) {
|
||||||
return c.getAttribute('data-value');
|
return c.getAttribute('data-value');
|
||||||
}).join(',');
|
}).join(',');
|
||||||
|
@ -675,9 +675,9 @@ define(['jQuery', 'loading', 'globalize', 'emby-select', 'emby-button', 'emby-in
|
||||||
profile.MaxAlbumArtHeight = $('#txtAlbumArtMaxHeight', page).val();
|
profile.MaxAlbumArtHeight = $('#txtAlbumArtMaxHeight', page).val();
|
||||||
profile.MaxIconWidth = $('#txtIconMaxWidth', page).val();
|
profile.MaxIconWidth = $('#txtIconMaxWidth', page).val();
|
||||||
profile.MaxIconHeight = $('#txtIconMaxHeight', page).val();
|
profile.MaxIconHeight = $('#txtIconMaxHeight', page).val();
|
||||||
profile.RequiresPlainFolders = $('#chkRequiresPlainFolders', page).checked;
|
profile.RequiresPlainFolders = $('#chkRequiresPlainFolders', page).is(':checked');
|
||||||
profile.RequiresPlainVideoItems = $('#chkRequiresPlainVideoItems', page).checked;
|
profile.RequiresPlainVideoItems = $('#chkRequiresPlainVideoItems', page).is(':checked');
|
||||||
profile.IgnoreTranscodeByteRangeRequests = $('#chkIgnoreTranscodeByteRangeRequests', page).checked;
|
profile.IgnoreTranscodeByteRangeRequests = $('#chkIgnoreTranscodeByteRangeRequests', page).is(':checked');
|
||||||
profile.MaxStreamingBitrate = $('#txtMaxAllowedBitrate', page).val();
|
profile.MaxStreamingBitrate = $('#txtMaxAllowedBitrate', page).val();
|
||||||
profile.MusicStreamingTranscodingBitrate = $('#txtMusicStreamingTranscodingBitrate', page).val();
|
profile.MusicStreamingTranscodingBitrate = $('#txtMusicStreamingTranscodingBitrate', page).val();
|
||||||
profile.ProtocolInfo = $('#txtProtocolInfo', page).val();
|
profile.ProtocolInfo = $('#txtProtocolInfo', page).val();
|
||||||
|
|
|
@ -5,8 +5,8 @@ define(['jQuery', 'loading', 'libraryMenu', 'globalize'], function ($, loading,
|
||||||
page.querySelector('#chkEnablePlayTo').checked = config.EnablePlayTo;
|
page.querySelector('#chkEnablePlayTo').checked = config.EnablePlayTo;
|
||||||
page.querySelector('#chkEnableDlnaDebugLogging').checked = config.EnableDebugLog;
|
page.querySelector('#chkEnableDlnaDebugLogging').checked = config.EnableDebugLog;
|
||||||
$('#txtClientDiscoveryInterval', page).val(config.ClientDiscoveryIntervalSeconds);
|
$('#txtClientDiscoveryInterval', page).val(config.ClientDiscoveryIntervalSeconds);
|
||||||
$('#chkEnableServer', page).checked = config.EnableServer;
|
$('#chkEnableServer', page).prop('checked', config.EnableServer);
|
||||||
$('#chkBlastAliveMessages', page).checked = config.BlastAliveMessages;
|
$('#chkBlastAliveMessages', page).prop('checked', config.BlastAliveMessages);
|
||||||
$('#txtBlastInterval', page).val(config.BlastAliveMessageIntervalSeconds);
|
$('#txtBlastInterval', page).val(config.BlastAliveMessageIntervalSeconds);
|
||||||
var usersHtml = users.map(function (u) {
|
var usersHtml = users.map(function (u) {
|
||||||
return '<option value="' + u.Id + '">' + u.Name + '</option>';
|
return '<option value="' + u.Id + '">' + u.Name + '</option>';
|
||||||
|
@ -22,8 +22,8 @@ define(['jQuery', 'loading', 'libraryMenu', 'globalize'], function ($, loading,
|
||||||
config.EnablePlayTo = form.querySelector('#chkEnablePlayTo').checked;
|
config.EnablePlayTo = form.querySelector('#chkEnablePlayTo').checked;
|
||||||
config.EnableDebugLog = form.querySelector('#chkEnableDlnaDebugLogging').checked;
|
config.EnableDebugLog = form.querySelector('#chkEnableDlnaDebugLogging').checked;
|
||||||
config.ClientDiscoveryIntervalSeconds = $('#txtClientDiscoveryInterval', form).val();
|
config.ClientDiscoveryIntervalSeconds = $('#txtClientDiscoveryInterval', form).val();
|
||||||
config.EnableServer = $('#chkEnableServer', form).checked;
|
config.EnableServer = $('#chkEnableServer', form).is(':checked');
|
||||||
config.BlastAliveMessages = $('#chkBlastAliveMessages', form).checked;
|
config.BlastAliveMessages = $('#chkBlastAliveMessages', form).is(':checked');
|
||||||
config.BlastAliveMessageIntervalSeconds = $('#txtBlastInterval', form).val();
|
config.BlastAliveMessageIntervalSeconds = $('#txtBlastInterval', form).val();
|
||||||
config.DefaultUserId = $('#selectUser', form).val();
|
config.DefaultUserId = $('#selectUser', form).val();
|
||||||
ApiClient.updateNamedConfiguration('dlna', config).then(Dashboard.processServerConfigurationUpdateResult);
|
ApiClient.updateNamedConfiguration('dlna', config).then(Dashboard.processServerConfigurationUpdateResult);
|
||||||
|
|
|
@ -5,6 +5,8 @@ define(['jQuery', 'loading', 'globalize', 'dom', 'libraryMenu'], function ($, lo
|
||||||
Array.prototype.forEach.call(page.querySelectorAll('.chkDecodeCodec'), function (c) {
|
Array.prototype.forEach.call(page.querySelectorAll('.chkDecodeCodec'), function (c) {
|
||||||
c.checked = -1 !== (config.HardwareDecodingCodecs || []).indexOf(c.getAttribute('data-codec'));
|
c.checked = -1 !== (config.HardwareDecodingCodecs || []).indexOf(c.getAttribute('data-codec'));
|
||||||
});
|
});
|
||||||
|
page.querySelector('#chkDecodingColorDepth10Hevc').checked = config.EnableDecodingColorDepth10Hevc;
|
||||||
|
page.querySelector('#chkDecodingColorDepth10Vp9').checked = config.EnableDecodingColorDepth10Vp9;
|
||||||
page.querySelector('#chkHardwareEncoding').checked = config.EnableHardwareEncoding;
|
page.querySelector('#chkHardwareEncoding').checked = config.EnableHardwareEncoding;
|
||||||
$('#selectVideoDecoder', page).val(config.HardwareAccelerationType);
|
$('#selectVideoDecoder', page).val(config.HardwareAccelerationType);
|
||||||
$('#selectThreadCount', page).val(config.EncodingThreadCount);
|
$('#selectThreadCount', page).val(config.EncodingThreadCount);
|
||||||
|
@ -67,6 +69,8 @@ define(['jQuery', 'loading', 'globalize', 'dom', 'libraryMenu'], function ($, lo
|
||||||
}), function (c) {
|
}), function (c) {
|
||||||
return c.getAttribute('data-codec');
|
return c.getAttribute('data-codec');
|
||||||
});
|
});
|
||||||
|
config.EnableDecodingColorDepth10Hevc = form.querySelector('#chkDecodingColorDepth10Hevc').checked;
|
||||||
|
config.EnableDecodingColorDepth10Vp9 = form.querySelector('#chkDecodingColorDepth10Vp9').checked;
|
||||||
config.EnableHardwareEncoding = form.querySelector('#chkHardwareEncoding').checked;
|
config.EnableHardwareEncoding = form.querySelector('#chkHardwareEncoding').checked;
|
||||||
ApiClient.updateNamedConfiguration('encoding', config).then(function () {
|
ApiClient.updateNamedConfiguration('encoding', config).then(function () {
|
||||||
updateEncoder(form);
|
updateEncoder(form);
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
define(['datetime', 'loading', 'apphost', 'listViewStyle', 'emby-button', 'flexStyles'], function(datetime, loading, appHost) {
|
import datetime from 'datetime';
|
||||||
'use strict';
|
import loading from 'loading';
|
||||||
return function(view, params) {
|
import 'emby-button';
|
||||||
|
import 'listViewStyle';
|
||||||
|
import 'flexStyles';
|
||||||
|
|
||||||
|
/* eslint-disable indent */
|
||||||
|
|
||||||
|
export default function(view, params) {
|
||||||
view.addEventListener('viewbeforeshow', function() {
|
view.addEventListener('viewbeforeshow', function() {
|
||||||
loading.show();
|
loading.show();
|
||||||
var apiClient = ApiClient;
|
var apiClient = ApiClient;
|
||||||
|
@ -29,5 +35,6 @@ define(['datetime', 'loading', 'apphost', 'listViewStyle', 'emby-button', 'flexS
|
||||||
loading.hide();
|
loading.hide();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
});
|
|
||||||
|
/* eslint-enable indent */
|
||||||
|
|
|
@ -50,7 +50,7 @@ define(['jQuery', 'emby-checkbox'], function ($) {
|
||||||
fillItems($('.monitorUsersList', page), users, 'chkMonitor', 'chkMonitor', notificationConfig.DisabledMonitorUsers);
|
fillItems($('.monitorUsersList', page), users, 'chkMonitor', 'chkMonitor', notificationConfig.DisabledMonitorUsers);
|
||||||
fillItems($('.sendToUsersList', page), users, 'chkSendTo', 'chkSendTo', notificationConfig.SendToUsers, true);
|
fillItems($('.sendToUsersList', page), users, 'chkSendTo', 'chkSendTo', notificationConfig.SendToUsers, true);
|
||||||
fillItems($('.servicesList', page), services, 'chkService', 'chkService', notificationConfig.DisabledServices);
|
fillItems($('.servicesList', page), services, 'chkService', 'chkService', notificationConfig.DisabledServices);
|
||||||
$('#chkEnabled', page).checked = notificationConfig.Enabled || false;
|
$('#chkEnabled', page).prop('checked', notificationConfig.Enabled || false);
|
||||||
$('#selectUsers', page).val(notificationConfig.SendToUserMode).trigger('change');
|
$('#selectUsers', page).val(notificationConfig.SendToUserMode).trigger('change');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ define(['jQuery', 'emby-checkbox'], function ($) {
|
||||||
notificationOptions.Options.push(notificationConfig);
|
notificationOptions.Options.push(notificationConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
notificationConfig.Enabled = $('#chkEnabled', page).checked;
|
notificationConfig.Enabled = $('#chkEnabled', page).is(':checked');
|
||||||
notificationConfig.SendToUserMode = $('#selectUsers', page).val();
|
notificationConfig.SendToUserMode = $('#selectUsers', page).val();
|
||||||
notificationConfig.DisabledMonitorUsers = $('.chkMonitor', page).get().filter(function (c) {
|
notificationConfig.DisabledMonitorUsers = $('.chkMonitor', page).get().filter(function (c) {
|
||||||
return !c.checked;
|
return !c.checked;
|
||||||
|
|
|
@ -123,6 +123,9 @@ define(['loading', 'libraryMenu', 'globalize', 'cardStyle', 'emby-button', 'emby
|
||||||
}, {
|
}, {
|
||||||
href: 'availableplugins.html',
|
href: 'availableplugins.html',
|
||||||
name: globalize.translate('TabCatalog')
|
name: globalize.translate('TabCatalog')
|
||||||
|
}, {
|
||||||
|
href: 'repositories.html',
|
||||||
|
name: globalize.translate('TabRepositories')
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,20 +37,24 @@ define(['loading', 'libraryMenu', 'dom', 'globalize', 'cardStyle', 'emby-button'
|
||||||
})[0];
|
})[0];
|
||||||
var configPageUrl = configPage ? Dashboard.getConfigurationPageUrl(configPage.Name) : null;
|
var configPageUrl = configPage ? Dashboard.getConfigurationPageUrl(configPage.Name) : null;
|
||||||
var html = '';
|
var html = '';
|
||||||
html += "<div data-id='" + plugin.Id + "' data-name='" + plugin.Name + "' class='card backdropCard'>";
|
html += "<div data-id='" + plugin.Id + "' data-name='" + plugin.Name + "' data-removable='" + plugin.CanUninstall + "' class='card backdropCard'>";
|
||||||
html += '<div class="cardBox visualCardBox">';
|
html += '<div class="cardBox visualCardBox">';
|
||||||
html += '<div class="cardScalable">';
|
html += '<div class="cardScalable">';
|
||||||
html += '<div class="cardPadder cardPadder-backdrop"></div>';
|
html += '<div class="cardPadder cardPadder-backdrop"></div>';
|
||||||
html += configPageUrl ? '<a class="cardContent cardImageContainer" is="emby-linkbutton" href="' + configPageUrl + '">' : '<div class="cardContent noConfigPluginCard noHoverEffect cardImageContainer">';
|
html += configPageUrl ? '<a class="cardContent cardImageContainer" is="emby-linkbutton" href="' + configPageUrl + '">' : '<div class="cardContent noConfigPluginCard noHoverEffect cardImageContainer emby-button">';
|
||||||
html += '<span class="cardImageIcon material-icons folder"></span>';
|
html += '<span class="cardImageIcon material-icons folder"></span>';
|
||||||
html += configPageUrl ? '</a>' : '</div>';
|
html += configPageUrl ? '</a>' : '</div>';
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
html += '<div class="cardFooter">';
|
html += '<div class="cardFooter">';
|
||||||
|
|
||||||
|
if (configPage || plugin.CanUninstall) {
|
||||||
html += '<div style="text-align:right; float:right;padding-top:5px;">';
|
html += '<div style="text-align:right; float:right;padding-top:5px;">';
|
||||||
html += '<button type="button" is="paper-icon-button-light" class="btnCardMenu autoSize"><span class="material-icons more_vert"></span></button>';
|
html += '<button type="button" is="paper-icon-button-light" class="btnCardMenu autoSize"><span class="material-icons more_vert"></span></button>';
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
html += "<div class='cardText'>";
|
html += "<div class='cardText'>";
|
||||||
html += configPage.DisplayName || plugin.Name;
|
html += configPage && configPage.DisplayName ? configPage.DisplayName : plugin.Name;
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
html += "<div class='cardText cardText-secondary'>";
|
html += "<div class='cardText cardText-secondary'>";
|
||||||
html += plugin.Version;
|
html += plugin.Version;
|
||||||
|
@ -104,6 +108,7 @@ define(['loading', 'libraryMenu', 'dom', 'globalize', 'cardStyle', 'emby-button'
|
||||||
var card = dom.parentWithClass(elem, 'card');
|
var card = dom.parentWithClass(elem, 'card');
|
||||||
var id = card.getAttribute('data-id');
|
var id = card.getAttribute('data-id');
|
||||||
var name = card.getAttribute('data-name');
|
var name = card.getAttribute('data-name');
|
||||||
|
var removable = card.getAttribute('data-removable');
|
||||||
var configHref = card.querySelector('.cardContent').getAttribute('href');
|
var configHref = card.querySelector('.cardContent').getAttribute('href');
|
||||||
var menuItems = [];
|
var menuItems = [];
|
||||||
|
|
||||||
|
@ -115,11 +120,13 @@ define(['loading', 'libraryMenu', 'dom', 'globalize', 'cardStyle', 'emby-button'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (removable === 'true') {
|
||||||
menuItems.push({
|
menuItems.push({
|
||||||
name: globalize.translate('ButtonUninstall'),
|
name: globalize.translate('ButtonUninstall'),
|
||||||
id: 'delete',
|
id: 'delete',
|
||||||
icon: 'delete'
|
icon: 'delete'
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
require(['actionsheet'], function (actionsheet) {
|
require(['actionsheet'], function (actionsheet) {
|
||||||
actionsheet.show({
|
actionsheet.show({
|
||||||
|
@ -153,6 +160,9 @@ define(['loading', 'libraryMenu', 'dom', 'globalize', 'cardStyle', 'emby-button'
|
||||||
}, {
|
}, {
|
||||||
href: 'availableplugins.html',
|
href: 'availableplugins.html',
|
||||||
name: globalize.translate('TabCatalog')
|
name: globalize.translate('TabCatalog')
|
||||||
|
}, {
|
||||||
|
href: 'repositories.html',
|
||||||
|
name: globalize.translate('TabRepositories')
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
153
src/controllers/dashboard/plugins/repositories.js
Normal file
153
src/controllers/dashboard/plugins/repositories.js
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
import loading from 'loading';
|
||||||
|
import libraryMenu from 'libraryMenu';
|
||||||
|
import globalize from 'globalize';
|
||||||
|
import dialogHelper from 'dialogHelper';
|
||||||
|
import 'emby-button';
|
||||||
|
import 'emby-checkbox';
|
||||||
|
import 'emby-select';
|
||||||
|
import 'formDialogStyle';
|
||||||
|
import 'listViewStyle';
|
||||||
|
|
||||||
|
let repositories = [];
|
||||||
|
|
||||||
|
function reloadList(page) {
|
||||||
|
loading.show();
|
||||||
|
ApiClient.getJSON(ApiClient.getUrl('Repositories')).then(list => {
|
||||||
|
repositories = list;
|
||||||
|
populateList({
|
||||||
|
listElement: page.querySelector('#repositories'),
|
||||||
|
noneElement: page.querySelector('#none'),
|
||||||
|
repositories: repositories
|
||||||
|
});
|
||||||
|
}).catch(error => {
|
||||||
|
console.error('error loading repositories');
|
||||||
|
page.querySelector('#none').classList.remove('hide');
|
||||||
|
loading.hide();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveList(page) {
|
||||||
|
loading.show();
|
||||||
|
ApiClient.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: ApiClient.getUrl('Repositories'),
|
||||||
|
data: JSON.stringify(repositories),
|
||||||
|
contentType: 'application/json'
|
||||||
|
}).then(response => {
|
||||||
|
reloadList(page);
|
||||||
|
}).catch(error => {
|
||||||
|
console.error('error saving repositories');
|
||||||
|
loading.hide();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function populateList(options) {
|
||||||
|
var html = '';
|
||||||
|
|
||||||
|
html += '<div class="paperList">';
|
||||||
|
for (var i = 0; i < options.repositories.length; i++) {
|
||||||
|
html += getRepositoryHtml(options.repositories[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '</div>';
|
||||||
|
if (!options.repositories.length) {
|
||||||
|
options.noneElement.classList.remove('hide');
|
||||||
|
}
|
||||||
|
|
||||||
|
options.listElement.innerHTML = html;
|
||||||
|
loading.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRepositoryHtml(repository) {
|
||||||
|
var html = '';
|
||||||
|
|
||||||
|
html += '<div class="listItem listItem-border">';
|
||||||
|
html += `<a is="emby-linkbutton" style="margin:0;padding:0" class="clearLink listItemIconContainer" href="${repository.Url}">`;
|
||||||
|
html += '<span class="material-icons listItemIcon open_in_new"></span>';
|
||||||
|
html += '</a>';
|
||||||
|
html += '<div class="listItemBody two-line">';
|
||||||
|
html += `<h3 class="listItemBodyText">${repository.Name}</h3>`;
|
||||||
|
html += `<div class="listItemBodyText secondary">${repository.Url}</div>`;
|
||||||
|
html += '</div>';
|
||||||
|
html += `<button type="button" is="paper-icon-button-light" id="${repository.Url}" class="btnDelete" title="${globalize.translate('ButtonDelete')}"><span class="material-icons delete"></span></button>`;
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTabs() {
|
||||||
|
return [{
|
||||||
|
href: 'installedplugins.html',
|
||||||
|
name: globalize.translate('TabMyPlugins')
|
||||||
|
}, {
|
||||||
|
href: 'availableplugins.html',
|
||||||
|
name: globalize.translate('TabCatalog')
|
||||||
|
}, {
|
||||||
|
href: 'repositories.html',
|
||||||
|
name: globalize.translate('TabRepositories')
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function(view, params) {
|
||||||
|
view.addEventListener('viewshow', function () {
|
||||||
|
libraryMenu.setTabs('plugins', 2, getTabs);
|
||||||
|
reloadList(this);
|
||||||
|
|
||||||
|
var save = this;
|
||||||
|
$('#repositories', view).on('click', '.btnDelete', function() {
|
||||||
|
var button = this;
|
||||||
|
repositories = repositories.filter(function (r) {
|
||||||
|
return r.Url !== button.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
saveList(save);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
view.querySelector('.btnNewRepository').addEventListener('click', () => {
|
||||||
|
let dialog = dialogHelper.createDialog({
|
||||||
|
scrollY: false,
|
||||||
|
size: 'large',
|
||||||
|
modal: false,
|
||||||
|
removeOnClose: true
|
||||||
|
});
|
||||||
|
|
||||||
|
let html = '';
|
||||||
|
|
||||||
|
html += '<div class="formDialogHeader">';
|
||||||
|
html += '<button type="button" is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
|
||||||
|
html += `<h3 class="formDialogHeaderTitle">${globalize.translate('HeaderNewRepository')}</h3>`;
|
||||||
|
html += '</div>';
|
||||||
|
html += '<form class="newPluginForm" style="margin:4em">';
|
||||||
|
html += '<div class="inputContainer">';
|
||||||
|
html += `<input is="emby-input" id="txtRepositoryName" label="${globalize.translate('LabelRepositoryName')}" type="text" required />`;
|
||||||
|
html += `<div class="fieldDescription">${globalize.translate('LabelRepositoryNameHelp')}</div>`;
|
||||||
|
html += '</div>';
|
||||||
|
html += '<div class="inputContainer">';
|
||||||
|
html += `<input is="emby-input" id="txtRepositoryUrl" label="${globalize.translate('LabelRepositoryUrl')}" type="url" required />`;
|
||||||
|
html += `<div class="fieldDescription">${globalize.translate('LabelRepositoryUrlHelp')}</div>`;
|
||||||
|
html += '</div>';
|
||||||
|
html += `<button is="emby-button" type="submit" class="raised button-submit block"><span>${globalize.translate('ButtonSave')}</span></button>`;
|
||||||
|
html += '</div>';
|
||||||
|
html += '</form>';
|
||||||
|
|
||||||
|
dialog.innerHTML = html;
|
||||||
|
dialog.querySelector('.btnCancel').addEventListener('click', () => {
|
||||||
|
dialogHelper.close(dialog);
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.querySelector('.newPluginForm').addEventListener('submit', () => {
|
||||||
|
repositories.push({
|
||||||
|
Name: dialog.querySelector('#txtRepositoryName').value,
|
||||||
|
Url: dialog.querySelector('#txtRepositoryUrl').value,
|
||||||
|
Enabled: true
|
||||||
|
});
|
||||||
|
|
||||||
|
saveList(view);
|
||||||
|
dialogHelper.close(dialog);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
dialogHelper.open(dialog);
|
||||||
|
});
|
||||||
|
}
|
|
@ -27,7 +27,7 @@ define(['jQuery', 'loading', 'libraryMenu', 'globalize'], function ($, loading,
|
||||||
}
|
}
|
||||||
|
|
||||||
$('.deleteAccess', page).html(html).trigger('create');
|
$('.deleteAccess', page).html(html).trigger('create');
|
||||||
$('#chkEnableDeleteAllFolders', page).checked = user.Policy.EnableContentDeletion;
|
$('#chkEnableDeleteAllFolders', page).prop('checked', user.Policy.EnableContentDeletion);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,23 +85,23 @@ define(['jQuery', 'loading', 'libraryMenu', 'globalize'], function ($, loading,
|
||||||
libraryMenu.setTitle(user.Name);
|
libraryMenu.setTitle(user.Name);
|
||||||
page.querySelector('.username').innerHTML = user.Name;
|
page.querySelector('.username').innerHTML = user.Name;
|
||||||
$('#txtUserName', page).val(user.Name);
|
$('#txtUserName', page).val(user.Name);
|
||||||
$('#chkIsAdmin', page).checked = user.Policy.IsAdministrator;
|
$('#chkIsAdmin', page).prop('checked', user.Policy.IsAdministrator);
|
||||||
$('#chkDisabled', page).checked = user.Policy.IsDisabled;
|
$('#chkDisabled', page).prop('checked', user.Policy.IsDisabled);
|
||||||
$('#chkIsHidden', page).checked = user.Policy.IsHidden;
|
$('#chkIsHidden', page).prop('checked', user.Policy.IsHidden);
|
||||||
$('#chkRemoteControlSharedDevices', page).checked = user.Policy.EnableSharedDeviceControl;
|
$('#chkRemoteControlSharedDevices', page).prop('checked', user.Policy.EnableSharedDeviceControl);
|
||||||
$('#chkEnableRemoteControlOtherUsers', page).checked = user.Policy.EnableRemoteControlOfOtherUsers;
|
$('#chkEnableRemoteControlOtherUsers', page).prop('checked', user.Policy.EnableRemoteControlOfOtherUsers);
|
||||||
$('#chkEnableDownloading', page).checked = user.Policy.EnableContentDownloading;
|
$('#chkEnableDownloading', page).prop('checked', user.Policy.EnableContentDownloading);
|
||||||
$('#chkManageLiveTv', page).checked = user.Policy.EnableLiveTvManagement;
|
$('#chkManageLiveTv', page).prop('checked', user.Policy.EnableLiveTvManagement);
|
||||||
$('#chkEnableLiveTvAccess', page).checked = user.Policy.EnableLiveTvAccess;
|
$('#chkEnableLiveTvAccess', page).prop('checked', user.Policy.EnableLiveTvAccess);
|
||||||
$('#chkEnableMediaPlayback', page).checked = user.Policy.EnableMediaPlayback;
|
$('#chkEnableMediaPlayback', page).prop('checked', user.Policy.EnableMediaPlayback);
|
||||||
$('#chkEnableAudioPlaybackTranscoding', page).checked = user.Policy.EnableAudioPlaybackTranscoding;
|
$('#chkEnableAudioPlaybackTranscoding', page).prop('checked', user.Policy.EnableAudioPlaybackTranscoding);
|
||||||
$('#chkEnableVideoPlaybackTranscoding', page).checked = user.Policy.EnableVideoPlaybackTranscoding;
|
$('#chkEnableVideoPlaybackTranscoding', page).prop('checked', user.Policy.EnableVideoPlaybackTranscoding);
|
||||||
$('#chkEnableVideoPlaybackRemuxing', page).checked = user.Policy.EnablePlaybackRemuxing;
|
$('#chkEnableVideoPlaybackRemuxing', page).prop('checked', user.Policy.EnablePlaybackRemuxing);
|
||||||
$('#chkForceRemoteSourceTranscoding', page).checked = user.Policy.ForceRemoteSourceTranscoding;
|
$('#chkForceRemoteSourceTranscoding', page).prop('checked', user.Policy.ForceRemoteSourceTranscoding);
|
||||||
$('#chkRemoteAccess', page).checked = null == user.Policy.EnableRemoteAccess || user.Policy.EnableRemoteAccess;
|
$('#chkRemoteAccess', page).prop('checked', null == user.Policy.EnableRemoteAccess || user.Policy.EnableRemoteAccess);
|
||||||
$('#chkEnableSyncTranscoding', page).checked = user.Policy.EnableSyncTranscoding;
|
$('#chkEnableSyncTranscoding', page).prop('checked', user.Policy.EnableSyncTranscoding);
|
||||||
$('#chkEnableConversion', page).checked = user.Policy.EnableMediaConversion || false;
|
$('#chkEnableConversion', page).prop('checked', user.Policy.EnableMediaConversion || false);
|
||||||
$('#chkEnableSharing', page).checked = user.Policy.EnablePublicSharing;
|
$('#chkEnableSharing', page).prop('checked', user.Policy.EnablePublicSharing);
|
||||||
$('#txtRemoteClientBitrateLimit', page).val(user.Policy.RemoteClientBitrateLimit / 1e6 || '');
|
$('#txtRemoteClientBitrateLimit', page).val(user.Policy.RemoteClientBitrateLimit / 1e6 || '');
|
||||||
$('#txtLoginAttemptsBeforeLockout', page).val(user.Policy.LoginAttemptsBeforeLockout || '0');
|
$('#txtLoginAttemptsBeforeLockout', page).val(user.Policy.LoginAttemptsBeforeLockout || '0');
|
||||||
$('#selectSyncPlayAccess').val(user.Policy.SyncPlayAccess);
|
$('#selectSyncPlayAccess').val(user.Policy.SyncPlayAccess);
|
||||||
|
@ -119,28 +119,28 @@ define(['jQuery', 'loading', 'libraryMenu', 'globalize'], function ($, loading,
|
||||||
|
|
||||||
function saveUser(user, page) {
|
function saveUser(user, page) {
|
||||||
user.Name = $('#txtUserName', page).val();
|
user.Name = $('#txtUserName', page).val();
|
||||||
user.Policy.IsAdministrator = $('#chkIsAdmin', page).checked;
|
user.Policy.IsAdministrator = $('#chkIsAdmin', page).is(':checked');
|
||||||
user.Policy.IsHidden = $('#chkIsHidden', page).checked;
|
user.Policy.IsHidden = $('#chkIsHidden', page).is(':checked');
|
||||||
user.Policy.IsDisabled = $('#chkDisabled', page).checked;
|
user.Policy.IsDisabled = $('#chkDisabled', page).is(':checked');
|
||||||
user.Policy.EnableRemoteControlOfOtherUsers = $('#chkEnableRemoteControlOtherUsers', page).checked;
|
user.Policy.EnableRemoteControlOfOtherUsers = $('#chkEnableRemoteControlOtherUsers', page).is(':checked');
|
||||||
user.Policy.EnableLiveTvManagement = $('#chkManageLiveTv', page).checked;
|
user.Policy.EnableLiveTvManagement = $('#chkManageLiveTv', page).is(':checked');
|
||||||
user.Policy.EnableLiveTvAccess = $('#chkEnableLiveTvAccess', page).checked;
|
user.Policy.EnableLiveTvAccess = $('#chkEnableLiveTvAccess', page).is(':checked');
|
||||||
user.Policy.EnableSharedDeviceControl = $('#chkRemoteControlSharedDevices', page).checked;
|
user.Policy.EnableSharedDeviceControl = $('#chkRemoteControlSharedDevices', page).is(':checked');
|
||||||
user.Policy.EnableMediaPlayback = $('#chkEnableMediaPlayback', page).checked;
|
user.Policy.EnableMediaPlayback = $('#chkEnableMediaPlayback', page).is(':checked');
|
||||||
user.Policy.EnableAudioPlaybackTranscoding = $('#chkEnableAudioPlaybackTranscoding', page).checked;
|
user.Policy.EnableAudioPlaybackTranscoding = $('#chkEnableAudioPlaybackTranscoding', page).is(':checked');
|
||||||
user.Policy.EnableVideoPlaybackTranscoding = $('#chkEnableVideoPlaybackTranscoding', page).checked;
|
user.Policy.EnableVideoPlaybackTranscoding = $('#chkEnableVideoPlaybackTranscoding', page).is(':checked');
|
||||||
user.Policy.EnablePlaybackRemuxing = $('#chkEnableVideoPlaybackRemuxing', page).checked;
|
user.Policy.EnablePlaybackRemuxing = $('#chkEnableVideoPlaybackRemuxing', page).is(':checked');
|
||||||
user.Policy.ForceRemoteSourceTranscoding = $('#chkForceRemoteSourceTranscoding', page).checked;
|
user.Policy.ForceRemoteSourceTranscoding = $('#chkForceRemoteSourceTranscoding', page).is(':checked');
|
||||||
user.Policy.EnableContentDownloading = $('#chkEnableDownloading', page).checked;
|
user.Policy.EnableContentDownloading = $('#chkEnableDownloading', page).is(':checked');
|
||||||
user.Policy.EnableSyncTranscoding = $('#chkEnableSyncTranscoding', page).checked;
|
user.Policy.EnableSyncTranscoding = $('#chkEnableSyncTranscoding', page).is(':checked');
|
||||||
user.Policy.EnableMediaConversion = $('#chkEnableConversion', page).checked;
|
user.Policy.EnableMediaConversion = $('#chkEnableConversion', page).is(':checked');
|
||||||
user.Policy.EnablePublicSharing = $('#chkEnableSharing', page).checked;
|
user.Policy.EnablePublicSharing = $('#chkEnableSharing', page).is(':checked');
|
||||||
user.Policy.EnableRemoteAccess = $('#chkRemoteAccess', page).checked;
|
user.Policy.EnableRemoteAccess = $('#chkRemoteAccess', page).is(':checked');
|
||||||
user.Policy.RemoteClientBitrateLimit = parseInt(1e6 * parseFloat($('#txtRemoteClientBitrateLimit', page).val() || '0'));
|
user.Policy.RemoteClientBitrateLimit = parseInt(1e6 * parseFloat($('#txtRemoteClientBitrateLimit', page).val() || '0'));
|
||||||
user.Policy.LoginAttemptsBeforeLockout = parseInt($('#txtLoginAttemptsBeforeLockout', page).val() || '0');
|
user.Policy.LoginAttemptsBeforeLockout = parseInt($('#txtLoginAttemptsBeforeLockout', page).val() || '0');
|
||||||
user.Policy.AuthenticationProviderId = page.querySelector('.selectLoginProvider').value;
|
user.Policy.AuthenticationProviderId = page.querySelector('.selectLoginProvider').value;
|
||||||
user.Policy.PasswordResetProviderId = page.querySelector('.selectPasswordResetProvider').value;
|
user.Policy.PasswordResetProviderId = page.querySelector('.selectPasswordResetProvider').value;
|
||||||
user.Policy.EnableContentDeletion = $('#chkEnableDeleteAllFolders', page).checked;
|
user.Policy.EnableContentDeletion = $('#chkEnableDeleteAllFolders', page).is(':checked');
|
||||||
user.Policy.EnableContentDeletionFromFolders = user.Policy.EnableContentDeletion ? [] : $('.chkFolder', page).get().filter(function (c) {
|
user.Policy.EnableContentDeletionFromFolders = user.Policy.EnableContentDeletion ? [] : $('.chkFolder', page).get().filter(function (c) {
|
||||||
return c.checked;
|
return c.checked;
|
||||||
}).map(function (c) {
|
}).map(function (c) {
|
||||||
|
|
|
@ -47,7 +47,7 @@ define(['jQuery', 'loading', 'libraryMenu', 'globalize'], function ($, loading,
|
||||||
$('.channelAccessContainer', page).hide();
|
$('.channelAccessContainer', page).hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#chkEnableAllChannels', page).checked = user.Policy.EnableAllChannels;
|
$('#chkEnableAllChannels', page).prop('checked', user.Policy.EnableAllChannels);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadDevices(page, user, devices) {
|
function loadDevices(page, user, devices) {
|
||||||
|
@ -63,7 +63,7 @@ define(['jQuery', 'loading', 'libraryMenu', 'globalize'], function ($, loading,
|
||||||
|
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
$('.deviceAccess', page).show().html(html);
|
$('.deviceAccess', page).show().html(html);
|
||||||
$('#chkEnableAllDevices', page).checked = user.Policy.EnableAllDevices;
|
$('#chkEnableAllDevices', page).prop('checked', user.Policy.EnableAllDevices);
|
||||||
|
|
||||||
if (user.Policy.IsAdministrator) {
|
if (user.Policy.IsAdministrator) {
|
||||||
page.querySelector('.deviceAccessContainer').classList.add('hide');
|
page.querySelector('.deviceAccessContainer').classList.add('hide');
|
||||||
|
@ -90,19 +90,19 @@ define(['jQuery', 'loading', 'libraryMenu', 'globalize'], function ($, loading,
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveUser(user, page) {
|
function saveUser(user, page) {
|
||||||
user.Policy.EnableAllFolders = $('#chkEnableAllFolders', page).checked;
|
user.Policy.EnableAllFolders = $('#chkEnableAllFolders', page).is(':checked');
|
||||||
user.Policy.EnabledFolders = user.Policy.EnableAllFolders ? [] : $('.chkFolder', page).get().filter(function (c) {
|
user.Policy.EnabledFolders = user.Policy.EnableAllFolders ? [] : $('.chkFolder', page).get().filter(function (c) {
|
||||||
return c.checked;
|
return c.checked;
|
||||||
}).map(function (c) {
|
}).map(function (c) {
|
||||||
return c.getAttribute('data-id');
|
return c.getAttribute('data-id');
|
||||||
});
|
});
|
||||||
user.Policy.EnableAllChannels = $('#chkEnableAllChannels', page).checked;
|
user.Policy.EnableAllChannels = $('#chkEnableAllChannels', page).is(':checked');
|
||||||
user.Policy.EnabledChannels = user.Policy.EnableAllChannels ? [] : $('.chkChannel', page).get().filter(function (c) {
|
user.Policy.EnabledChannels = user.Policy.EnableAllChannels ? [] : $('.chkChannel', page).get().filter(function (c) {
|
||||||
return c.checked;
|
return c.checked;
|
||||||
}).map(function (c) {
|
}).map(function (c) {
|
||||||
return c.getAttribute('data-id');
|
return c.getAttribute('data-id');
|
||||||
});
|
});
|
||||||
user.Policy.EnableAllDevices = $('#chkEnableAllDevices', page).checked;
|
user.Policy.EnableAllDevices = $('#chkEnableAllDevices', page).is(':checked');
|
||||||
user.Policy.EnabledDevices = user.Policy.EnableAllDevices ? [] : $('.chkDevice', page).get().filter(function (c) {
|
user.Policy.EnabledDevices = user.Policy.EnableAllDevices ? [] : $('.chkDevice', page).get().filter(function (c) {
|
||||||
return c.checked;
|
return c.checked;
|
||||||
}).map(function (c) {
|
}).map(function (c) {
|
||||||
|
|
|
@ -13,7 +13,7 @@ define(['jQuery', 'loading', 'globalize', 'emby-checkbox'], function ($, loading
|
||||||
|
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
$('.folderAccess', page).html(html).trigger('create');
|
$('.folderAccess', page).html(html).trigger('create');
|
||||||
$('#chkEnableAllFolders', page).checked = false;
|
$('#chkEnableAllFolders', page).prop('checked', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadChannels(page, channels) {
|
function loadChannels(page, channels) {
|
||||||
|
@ -35,7 +35,7 @@ define(['jQuery', 'loading', 'globalize', 'emby-checkbox'], function ($, loading
|
||||||
$('.channelAccessContainer', page).hide();
|
$('.channelAccessContainer', page).hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#chkEnableAllChannels', page).checked = false;
|
$('#chkEnableAllChannels', page).prop('checked', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadUser(page) {
|
function loadUser(page) {
|
||||||
|
@ -58,7 +58,7 @@ define(['jQuery', 'loading', 'globalize', 'emby-checkbox'], function ($, loading
|
||||||
user.Name = $('#txtUsername', page).val();
|
user.Name = $('#txtUsername', page).val();
|
||||||
user.Password = $('#txtPassword', page).val();
|
user.Password = $('#txtPassword', page).val();
|
||||||
ApiClient.createUser(user).then(function (user) {
|
ApiClient.createUser(user).then(function (user) {
|
||||||
user.Policy.EnableAllFolders = $('#chkEnableAllFolders', page).checked;
|
user.Policy.EnableAllFolders = $('#chkEnableAllFolders', page).is(':checked');
|
||||||
user.Policy.EnabledFolders = [];
|
user.Policy.EnabledFolders = [];
|
||||||
|
|
||||||
if (!user.Policy.EnableAllFolders) {
|
if (!user.Policy.EnableAllFolders) {
|
||||||
|
@ -69,7 +69,7 @@ define(['jQuery', 'loading', 'globalize', 'emby-checkbox'], function ($, loading
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
user.Policy.EnableAllChannels = $('#chkEnableAllChannels', page).checked;
|
user.Policy.EnableAllChannels = $('#chkEnableAllChannels', page).is(':checked');
|
||||||
user.Policy.EnabledChannels = [];
|
user.Policy.EnabledChannels = [];
|
||||||
|
|
||||||
if (!user.Policy.EnableAllChannels) {
|
if (!user.Policy.EnableAllChannels) {
|
||||||
|
|
|
@ -141,7 +141,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
playbackManager.getPlaybackMediaSources(item).then(function (mediaSources) {
|
var mediaSources = item.MediaSources;
|
||||||
instance._currentPlaybackMediaSources = mediaSources;
|
instance._currentPlaybackMediaSources = mediaSources;
|
||||||
page.querySelector('.trackSelections').classList.remove('hide');
|
page.querySelector('.trackSelections').classList.remove('hide');
|
||||||
select.setLabel(globalize.translate('LabelVersion'));
|
select.setLabel(globalize.translate('LabelVersion'));
|
||||||
|
@ -163,7 +163,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
|
||||||
renderAudioSelections(page, mediaSources);
|
renderAudioSelections(page, mediaSources);
|
||||||
renderSubtitleSelections(page, mediaSources);
|
renderSubtitleSelections(page, mediaSources);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderVideoSelections(page, mediaSources) {
|
function renderVideoSelections(page, mediaSources) {
|
||||||
|
@ -400,6 +400,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
|
||||||
} else if (item.Album) {
|
} else if (item.Album) {
|
||||||
parentNameHtml.push(item.Album);
|
parentNameHtml.push(item.Album);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This whole section needs some refactoring, so it becames easier to scale across all form factors. See GH #1022
|
// FIXME: This whole section needs some refactoring, so it becames easier to scale across all form factors. See GH #1022
|
||||||
var html = '';
|
var html = '';
|
||||||
var tvShowHtml = parentNameHtml[0];
|
var tvShowHtml = parentNameHtml[0];
|
||||||
|
@ -415,9 +416,9 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (layoutManager.mobile) {
|
if (layoutManager.mobile) {
|
||||||
html = '<h1 class="parentName" style="margin: .1em 0 .25em;">' + parentNameHtml.join('</br>') + '</h1>';
|
html = '<h1 class="parentName" style="margin: 0.2em 0 0">' + parentNameHtml.join('</br>') + '</h1>';
|
||||||
} else {
|
} else {
|
||||||
html = '<h1 class="parentName" style="margin: .1em 0 .25em;">' + tvShowHtml + '</h1>';
|
html = '<h1 class="parentName" style="margin: 0.2em 0 0">' + tvShowHtml + '</h1>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -425,20 +426,19 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
|
||||||
var name = itemHelper.getDisplayName(item, {
|
var name = itemHelper.getDisplayName(item, {
|
||||||
includeParentInfo: false
|
includeParentInfo: false
|
||||||
});
|
});
|
||||||
var offset = parentNameLast ? '.25em' : '.5em';
|
|
||||||
|
|
||||||
if (html && !parentNameLast) {
|
if (html && !parentNameLast) {
|
||||||
if (!layoutManager.mobile && tvSeasonHtml) {
|
if (!layoutManager.mobile && tvSeasonHtml) {
|
||||||
html += '<h3 class="itemName infoText" style="margin: .25em 0 .5em;">' + tvSeasonHtml + ' - ' + name + '</h3>';
|
html += '<h3 class="itemName infoText" style="margin: 0.2em 0 0">' + tvSeasonHtml + ' - ' + name + '</h3>';
|
||||||
} else {
|
} else {
|
||||||
html += '<h3 class="itemName infoText" style="margin: .25em 0 .5em;">' + name + '</h3>';
|
html += '<h3 class="itemName infoText" style="margin: 0.2em 0 0">' + name + '</h3>';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
html = '<h1 class="itemName infoText" style="margin: .1em 0 ' + offset + ';">' + name + '</h1>' + html;
|
html = '<h1 class="itemName infoText" style="margin: 0.4em 0 0">' + name + '</h1>' + html;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.OriginalTitle && item.OriginalTitle != item.Name) {
|
if (item.OriginalTitle && item.OriginalTitle != item.Name) {
|
||||||
html += '<h4 class="itemName infoText" style="margin: -' + offset + ' 0 0;">' + item.OriginalTitle + '</h4>';
|
html += '<h4 class="itemName infoText" style="margin: 0 0 0;">' + item.OriginalTitle + '</h4>';
|
||||||
}
|
}
|
||||||
|
|
||||||
container.innerHTML = html;
|
container.innerHTML = html;
|
||||||
|
@ -1106,10 +1106,10 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
|
||||||
var externalLinksElem = page.querySelector('.itemExternalLinks');
|
var externalLinksElem = page.querySelector('.itemExternalLinks');
|
||||||
|
|
||||||
renderOverview([overview], item);
|
renderOverview([overview], item);
|
||||||
|
|
||||||
var i;
|
var i;
|
||||||
var itemMiscInfo;
|
var itemMiscInfo;
|
||||||
itemMiscInfo = page.querySelectorAll('.itemMiscInfo-primary');
|
itemMiscInfo = page.querySelectorAll('.itemMiscInfo-primary');
|
||||||
|
|
||||||
for (i = 0; i < itemMiscInfo.length; i++) {
|
for (i = 0; i < itemMiscInfo.length; i++) {
|
||||||
mediaInfo.fillPrimaryMediaInfo(itemMiscInfo[i], item, {
|
mediaInfo.fillPrimaryMediaInfo(itemMiscInfo[i], item, {
|
||||||
interactive: true,
|
interactive: true,
|
||||||
|
@ -1125,7 +1125,6 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
|
||||||
}
|
}
|
||||||
|
|
||||||
itemMiscInfo = page.querySelectorAll('.itemMiscInfo-secondary');
|
itemMiscInfo = page.querySelectorAll('.itemMiscInfo-secondary');
|
||||||
|
|
||||||
for (i = 0; i < itemMiscInfo.length; i++) {
|
for (i = 0; i < itemMiscInfo.length; i++) {
|
||||||
mediaInfo.fillSecondaryMediaInfo(itemMiscInfo[i], item, {
|
mediaInfo.fillSecondaryMediaInfo(itemMiscInfo[i], item, {
|
||||||
interactive: true
|
interactive: true
|
||||||
|
@ -1840,7 +1839,8 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
|
||||||
chaptercardbuilder.buildChapterCards(item, chapters, {
|
chaptercardbuilder.buildChapterCards(item, chapters, {
|
||||||
itemsContainer: scenesContent,
|
itemsContainer: scenesContent,
|
||||||
backdropShape: 'overflowBackdrop',
|
backdropShape: 'overflowBackdrop',
|
||||||
squareShape: 'overflowSquare'
|
squareShape: 'overflowSquare',
|
||||||
|
imageBlurhashes: item.ImageBlurHashes
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -1891,7 +1891,8 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti
|
||||||
itemsContainer: castContent,
|
itemsContainer: castContent,
|
||||||
coverImage: true,
|
coverImage: true,
|
||||||
serverId: item.ServerId,
|
serverId: item.ServerId,
|
||||||
shape: 'overflowPortrait'
|
shape: 'overflowPortrait',
|
||||||
|
imageBlurhashes: item.ImageBlurHashes
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ define(['cardBuilder', 'imageLoader', 'libraryBrowser', 'loading', 'events', 'us
|
||||||
}
|
}
|
||||||
|
|
||||||
function showFilterMenu(context) {
|
function showFilterMenu(context) {
|
||||||
require(['components/filterdialog/filterdialog'], function (filterDialogFactory) {
|
require(['components/filterdialog/filterdialog'], function ({default: filterDialogFactory}) {
|
||||||
var filterDialog = new filterDialogFactory({
|
var filterDialog = new filterDialogFactory({
|
||||||
query: getQuery(),
|
query: getQuery(),
|
||||||
mode: 'livetvchannels',
|
mode: 'livetvchannels',
|
||||||
|
|
|
@ -171,7 +171,12 @@ define(['loading', 'events', 'libraryBrowser', 'imageLoader', 'listView', 'cardB
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.Items.length) {
|
if (!result.Items.length) {
|
||||||
html = '<p style="text-align:center;">' + globalize.translate('MessageNoCollectionsAvailable') + '</p>';
|
html = '';
|
||||||
|
|
||||||
|
html += '<div class="noItemsMessage centerMessage">';
|
||||||
|
html += '<h1>' + globalize.translate('MessageNothingHere') + '</h1>';
|
||||||
|
html += '<p>' + globalize.translate('MessageNoCollectionsAvailable') + '</p>';
|
||||||
|
html += '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
var itemsContainer = tabContent.querySelector('.itemsContainer');
|
var itemsContainer = tabContent.querySelector('.itemsContainer');
|
||||||
|
|
|
@ -165,6 +165,15 @@ define(['layoutManager', 'loading', 'libraryBrowser', 'cardBuilder', 'lazyLoader
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!result.Items.length) {
|
||||||
|
html = '';
|
||||||
|
|
||||||
|
html += '<div class="noItemsMessage centerMessage">';
|
||||||
|
html += '<h1>' + globalize.translate('MessageNothingHere') + '</h1>';
|
||||||
|
html += '<p>' + globalize.translate('MessageNoGenresAvailable') + '</p>';
|
||||||
|
html += '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
elem.innerHTML = html;
|
elem.innerHTML = html;
|
||||||
lazyLoader.lazyChildren(elem, fillItemsContainer);
|
lazyLoader.lazyChildren(elem, fillItemsContainer);
|
||||||
libraryBrowser.saveQueryValues(getSavedQueryKey(), query);
|
libraryBrowser.saveQueryValues(getSavedQueryKey(), query);
|
||||||
|
|
|
@ -270,7 +270,7 @@ define(['loading', 'layoutManager', 'userSettings', 'events', 'libraryBrowser',
|
||||||
query = userSettings.loadQuerySettings(savedQueryKey, query);
|
query = userSettings.loadQuerySettings(savedQueryKey, query);
|
||||||
|
|
||||||
self.showFilterMenu = function () {
|
self.showFilterMenu = function () {
|
||||||
require(['components/filterdialog/filterdialog'], function (filterDialogFactory) {
|
require(['components/filterdialog/filterdialog'], function ({default: filterDialogFactory}) {
|
||||||
var filterDialog = new filterDialogFactory({
|
var filterDialog = new filterDialogFactory({
|
||||||
query: query,
|
query: query,
|
||||||
mode: 'movies',
|
mode: 'movies',
|
||||||
|
|
|
@ -158,7 +158,12 @@ define(['layoutManager', 'loading', 'events', 'libraryBrowser', 'imageLoader', '
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.Items.length) {
|
if (!result.Items.length) {
|
||||||
html = '<p style="text-align:center;">' + globalize.translate('MessageNoTrailersFound') + '</p>';
|
html = '';
|
||||||
|
|
||||||
|
html += '<div class="noItemsMessage centerMessage">';
|
||||||
|
html += '<h1>' + globalize.translate('MessageNothingHere') + '</h1>';
|
||||||
|
html += '<p>' + globalize.translate('MessageNoTrailersFound') + '</p>';
|
||||||
|
html += '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
var itemsContainer = tabContent.querySelector('.itemsContainer');
|
var itemsContainer = tabContent.querySelector('.itemsContainer');
|
||||||
|
@ -180,7 +185,7 @@ define(['layoutManager', 'loading', 'events', 'libraryBrowser', 'imageLoader', '
|
||||||
var isLoading = false;
|
var isLoading = false;
|
||||||
|
|
||||||
self.showFilterMenu = function () {
|
self.showFilterMenu = function () {
|
||||||
require(['components/filterdialog/filterdialog'], function (filterDialogFactory) {
|
require(['components/filterdialog/filterdialog'], function ({default: filterDialogFactory}) {
|
||||||
var filterDialog = new filterDialogFactory({
|
var filterDialog = new filterDialogFactory({
|
||||||
query: getQuery(tabContent),
|
query: getQuery(tabContent),
|
||||||
mode: 'movies',
|
mode: 'movies',
|
||||||
|
|
|
@ -186,7 +186,7 @@ define(['layoutManager', 'playbackManager', 'loading', 'events', 'libraryBrowser
|
||||||
var isLoading = false;
|
var isLoading = false;
|
||||||
|
|
||||||
self.showFilterMenu = function () {
|
self.showFilterMenu = function () {
|
||||||
require(['components/filterdialog/filterdialog'], function (filterDialogFactory) {
|
require(['components/filterdialog/filterdialog'], function ({default: filterDialogFactory}) {
|
||||||
var filterDialog = new filterDialogFactory({
|
var filterDialog = new filterDialogFactory({
|
||||||
query: getQuery(),
|
query: getQuery(),
|
||||||
mode: 'albums',
|
mode: 'albums',
|
||||||
|
|
|
@ -170,7 +170,7 @@ define(['layoutManager', 'loading', 'events', 'libraryBrowser', 'imageLoader', '
|
||||||
var isLoading = false;
|
var isLoading = false;
|
||||||
|
|
||||||
self.showFilterMenu = function () {
|
self.showFilterMenu = function () {
|
||||||
require(['components/filterdialog/filterdialog'], function (filterDialogFactory) {
|
require(['components/filterdialog/filterdialog'], function ({default: filterDialogFactory}) {
|
||||||
var filterDialog = new filterDialogFactory({
|
var filterDialog = new filterDialogFactory({
|
||||||
query: getQuery(tabContent),
|
query: getQuery(tabContent),
|
||||||
mode: self.mode,
|
mode: self.mode,
|
||||||
|
|
|
@ -124,7 +124,7 @@ define(['events', 'libraryBrowser', 'imageLoader', 'listView', 'loading', 'userS
|
||||||
var isLoading = false;
|
var isLoading = false;
|
||||||
|
|
||||||
self.showFilterMenu = function () {
|
self.showFilterMenu = function () {
|
||||||
require(['components/filterdialog/filterdialog'], function (filterDialogFactory) {
|
require(['components/filterdialog/filterdialog'], function ({default: filterDialogFactory}) {
|
||||||
var filterDialog = new filterDialogFactory({
|
var filterDialog = new filterDialogFactory({
|
||||||
query: getQuery(tabContent),
|
query: getQuery(tabContent),
|
||||||
mode: 'songs',
|
mode: 'songs',
|
||||||
|
|
|
@ -164,7 +164,7 @@ define(['loading', 'events', 'libraryBrowser', 'imageLoader', 'listView', 'cardB
|
||||||
var isLoading = false;
|
var isLoading = false;
|
||||||
|
|
||||||
self.showFilterMenu = function () {
|
self.showFilterMenu = function () {
|
||||||
require(['components/filterdialog/filterdialog'], function (filterDialogFactory) {
|
require(['components/filterdialog/filterdialog'], function ({default: filterDialogFactory}) {
|
||||||
var filterDialog = new filterDialogFactory({
|
var filterDialog = new filterDialogFactory({
|
||||||
query: getQuery(tabContent),
|
query: getQuery(tabContent),
|
||||||
mode: 'episodes',
|
mode: 'episodes',
|
||||||
|
|
|
@ -161,6 +161,15 @@ define(['layoutManager', 'loading', 'libraryBrowser', 'cardBuilder', 'lazyLoader
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!result.Items.length) {
|
||||||
|
html = '';
|
||||||
|
|
||||||
|
html += '<div class="noItemsMessage centerMessage">';
|
||||||
|
html += '<h1>' + globalize.translate('MessageNothingHere') + '</h1>';
|
||||||
|
html += '<p>' + globalize.translate('MessageNoGenresAvailable') + '</p>';
|
||||||
|
html += '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
elem.innerHTML = html;
|
elem.innerHTML = html;
|
||||||
lazyLoader.lazyChildren(elem, fillItemsContainer);
|
lazyLoader.lazyChildren(elem, fillItemsContainer);
|
||||||
libraryBrowser.saveQueryValues(getSavedQueryKey(), query);
|
libraryBrowser.saveQueryValues(getSavedQueryKey(), query);
|
||||||
|
|
|
@ -197,7 +197,7 @@ define(['layoutManager', 'loading', 'events', 'libraryBrowser', 'imageLoader', '
|
||||||
var isLoading = false;
|
var isLoading = false;
|
||||||
|
|
||||||
self.showFilterMenu = function () {
|
self.showFilterMenu = function () {
|
||||||
require(['components/filterdialog/filterdialog'], function (filterDialogFactory) {
|
require(['components/filterdialog/filterdialog'], function ({default: filterDialogFactory}) {
|
||||||
var filterDialog = new filterDialogFactory({
|
var filterDialog = new filterDialogFactory({
|
||||||
query: getQuery(tabContent),
|
query: getQuery(tabContent),
|
||||||
mode: 'series',
|
mode: 'series',
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
define(['displaySettings', 'userSettings', 'autoFocuser'], function (DisplaySettings, userSettings, autoFocuser) {
|
define(['displaySettings', 'userSettings', 'autoFocuser'], function (DisplaySettings, userSettings, autoFocuser) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
// Shortcuts
|
||||||
|
const UserSettings = userSettings.UserSettings;
|
||||||
|
|
||||||
return function (view, params) {
|
return function (view, params) {
|
||||||
function onBeforeUnload(e) {
|
function onBeforeUnload(e) {
|
||||||
if (hasChanges) {
|
if (hasChanges) {
|
||||||
|
@ -11,7 +14,7 @@ define(['displaySettings', 'userSettings', 'autoFocuser'], function (DisplaySett
|
||||||
var settingsInstance;
|
var settingsInstance;
|
||||||
var hasChanges;
|
var hasChanges;
|
||||||
var userId = params.userId || ApiClient.getCurrentUserId();
|
var userId = params.userId || ApiClient.getCurrentUserId();
|
||||||
var currentSettings = userId === ApiClient.getCurrentUserId() ? userSettings : new userSettings();
|
var currentSettings = userId === ApiClient.getCurrentUserId() ? userSettings : new UserSettings();
|
||||||
view.addEventListener('viewshow', function () {
|
view.addEventListener('viewshow', function () {
|
||||||
window.addEventListener('beforeunload', onBeforeUnload);
|
window.addEventListener('beforeunload', onBeforeUnload);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
define(['homescreenSettings', 'dom', 'globalize', 'loading', 'userSettings', 'autoFocuser', 'listViewStyle'], function (HomescreenSettings, dom, globalize, loading, userSettings, autoFocuser) {
|
define(['homescreenSettings', 'dom', 'globalize', 'loading', 'userSettings', 'autoFocuser', 'listViewStyle'], function (HomescreenSettings, dom, globalize, loading, userSettings, autoFocuser) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
// Shortcuts
|
||||||
|
const UserSettings = userSettings.UserSettings;
|
||||||
|
|
||||||
return function (view, params) {
|
return function (view, params) {
|
||||||
function onBeforeUnload(e) {
|
function onBeforeUnload(e) {
|
||||||
if (hasChanges) {
|
if (hasChanges) {
|
||||||
|
@ -11,7 +14,7 @@ define(['homescreenSettings', 'dom', 'globalize', 'loading', 'userSettings', 'au
|
||||||
var homescreenSettingsInstance;
|
var homescreenSettingsInstance;
|
||||||
var hasChanges;
|
var hasChanges;
|
||||||
var userId = params.userId || ApiClient.getCurrentUserId();
|
var userId = params.userId || ApiClient.getCurrentUserId();
|
||||||
var currentSettings = userId === ApiClient.getCurrentUserId() ? userSettings : new userSettings();
|
var currentSettings = userId === ApiClient.getCurrentUserId() ? userSettings : new UserSettings();
|
||||||
view.addEventListener('viewshow', function () {
|
view.addEventListener('viewshow', function () {
|
||||||
window.addEventListener('beforeunload', onBeforeUnload);
|
window.addEventListener('beforeunload', onBeforeUnload);
|
||||||
|
|
||||||
|
|
|
@ -43,12 +43,6 @@ define(['apphost', 'connectionManager', 'layoutManager', 'listViewStyle', 'emby-
|
||||||
page.querySelector('.adminSection').classList.add('hide');
|
page.querySelector('.adminSection').classList.add('hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layoutManager.mobile) {
|
|
||||||
page.querySelector('.headerUsername').classList.add('hide');
|
|
||||||
page.querySelector('.adminSection').classList.add('hide');
|
|
||||||
page.querySelector('.userSection').classList.add('hide');
|
|
||||||
}
|
|
||||||
|
|
||||||
ApiClient.getUser(userId).then(function(user) {
|
ApiClient.getUser(userId).then(function(user) {
|
||||||
page.querySelector('.headerUsername').innerHTML = user.Name;
|
page.querySelector('.headerUsername').innerHTML = user.Name;
|
||||||
if (!user.Policy.IsAdministrator) {
|
if (!user.Policy.IsAdministrator) {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue