Merge branch 'master' into fix-subtitlesync-textfield

This commit is contained in:
redSpoutnik 2020-05-08 09:25:46 +02:00 committed by GitHub
commit b0a245867c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
422 changed files with 15895 additions and 16833 deletions

View file

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

1
.copr/Makefile Symbolic link
View file

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

5
.dependabot/config.yml Normal file
View file

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

View file

@ -7,3 +7,6 @@ charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf
[json]
indent_size = 2

View file

@ -1 +1,5 @@
libraries/
node_modules
dist
.idea
.vscode
src/libraries

193
.eslintrc.js Normal file
View file

@ -0,0 +1,193 @@
module.exports = {
root: true,
plugins: [
'promise',
'import',
'eslint-comments'
],
env: {
node: true,
es6: true,
es2017: true,
es2020: true
},
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
ecmaFeatures: {
impliedStrict: true
}
},
extends: [
'eslint:recommended',
// 'plugin:promise/recommended',
'plugin:import/errors',
'plugin:import/warnings',
'plugin:eslint-comments/recommended',
'plugin:compat/recommended'
],
rules: {
'block-spacing': ["error"],
'brace-style': ["error"],
'comma-dangle': ["error", "never"],
'comma-spacing': ["error"],
'eol-last': ["error"],
'indent': ["error", 4, { "SwitchCase": 1 }],
'keyword-spacing': ["error"],
'max-statements-per-line': ["error"],
'no-floating-decimal': ["error"],
'no-multi-spaces': ["error"],
'no-multiple-empty-lines': ["error", { "max": 1 }],
'no-trailing-spaces': ["error"],
'one-var': ["error", "never"],
'quotes': ["error", "single", { "avoidEscape": true, "allowTemplateLiterals": false }],
'semi': ["error"],
'space-before-blocks': ["error"]
},
overrides: [
{
files: [
'./src/**/*.js'
],
env: {
node: false,
amd: true,
browser: true,
es6: true,
es2017: true,
es2020: true
},
globals: {
// Browser globals
'MediaMetadata': 'readonly',
// Tizen globals
'tizen': 'readonly',
'webapis': 'readonly',
// WebOS globals
'webOS': 'readonly',
// Dependency globals
'$': 'readonly',
'jQuery': 'readonly',
'requirejs': 'readonly',
// Jellyfin globals
'ApiClient': 'writable',
'AppInfo': 'writable',
'chrome': 'writable',
'ConnectionManager': 'writable',
'DlnaProfilePage': 'writable',
'Dashboard': 'writable',
'DashboardPage': 'writable',
'Emby': 'readonly',
'Events': 'writable',
'getParameterByName': 'writable',
'getWindowLocationSearch': 'writable',
'Globalize': 'writable',
'Hls': 'writable',
'dfnshelper': 'writable',
'LibraryMenu': 'writable',
'LinkParser': 'writable',
'LiveTvHelpers': 'writable',
'MetadataEditor': 'writable',
'pageClassOn': 'writable',
'pageIdOn': 'writable',
'PlaylistViewer': 'writable',
'UserParentalControlPage': 'writable',
'Windows': 'readonly'
},
rules: {
// TODO: Fix warnings and remove these rules
'no-redeclare': ["warn"],
'no-unused-vars': ["warn"],
'no-useless-escape': ["warn"],
// TODO: Remove after ES6 migration is complete
'import/no-unresolved': ["off"]
},
settings: {
polyfills: [
// Native Promises Only
'Promise',
// whatwg-fetch
'fetch',
// document-register-element
'document.registerElement',
// resize-observer-polyfill
'ResizeObserver',
// fast-text-encoding
'TextEncoder',
// intersection-observer
'IntersectionObserver',
// Core-js
'Object.assign',
'Object.is',
'Object.setPrototypeOf',
'Object.toString',
'Object.freeze',
'Object.seal',
'Object.preventExtensions',
'Object.isFrozen',
'Object.isSealed',
'Object.isExtensible',
'Object.getOwnPropertyDescriptor',
'Object.getPrototypeOf',
'Object.keys',
'Object.getOwnPropertyNames',
'Function.name',
'Function.hasInstance',
'Array.from',
'Array.arrayOf',
'Array.copyWithin',
'Array.fill',
'Array.find',
'Array.findIndex',
'Array.iterator',
'String.fromCodePoint',
'String.raw',
'String.iterator',
'String.codePointAt',
'String.endsWith',
'String.includes',
'String.repeat',
'String.startsWith',
'String.trim',
'String.anchor',
'String.big',
'String.blink',
'String.bold',
'String.fixed',
'String.fontcolor',
'String.fontsize',
'String.italics',
'String.link',
'String.small',
'String.strike',
'String.sub',
'String.sup',
'RegExp',
'Number',
'Math',
'Date',
'async',
'Symbol',
'Map',
'Set',
'WeakMap',
'WeakSet',
'ArrayBuffer',
'DataView',
'Int8Array',
'Uint8Array',
'Uint8ClampedArray',
'Int16Array',
'Uint16Array',
'Int32Array',
'Uint32Array',
'Float32Array',
'Float64Array',
'Reflect',
// Temporary while eslint-compat-plugin is buggy
'document.querySelector'
]
}
}
]
}

View file

@ -1,171 +0,0 @@
env:
amd: true
browser: true
es6: true
es2017: true
es2020: true
parserOptions:
ecmaVersion: 2020
sourceType: module
ecmaFeatures:
impliedStrict: true
plugins:
- promise
- import
- eslint-comments
extends:
- eslint:recommended
- plugin:promise/recommended
- plugin:import/errors
- plugin:import/warnings
- plugin:eslint-comments/recommended
- plugin:compat/recommended
globals:
# Browser globals
MediaMetadata: readonly
# Tizen globals
tizen: readonly
webapis: readonly
# WebOS globals
webOS: readonly
# Dependency globals
$: readonly
jQuery: readonly
requirejs: readonly
# Jellyfin globals
ApiClient: writable
AppInfo: writable
chrome: writable
ConnectionManager: writable
DlnaProfilePage: writable
Dashboard: writable
DashboardPage: writable
Emby: readonly
Events: writable
getParameterByName: writable
getWindowLocationSearch: writable
Globalize: writable
Hls: writable
dfnshelper: writable
LibraryMenu: writable
LinkParser: writable
LiveTvHelpers: writable
MetadataEditor: writable
pageClassOn: writable
pageIdOn: writable
PlaylistViewer: writable
UserParentalControlPage: writable
Windows: readonly
rules:
block-spacing: ["error"]
brace-style: ["error"]
comma-dangle: ["error", "never"]
comma-spacing: ["error"]
eol-last: ["error"]
indent: ["error", 4, { "SwitchCase": 1 }]
keyword-spacing: ["error"]
max-statements-per-line: ["error"]
no-floating-decimal: ["error"]
no-multi-spaces: ["error"]
no-multiple-empty-lines: ["error", { "max": 1 }]
no-trailing-spaces: ["error"]
one-var: ["error", "never"]
semi: ["error"]
space-before-blocks: ["error"]
# TODO: Fix warnings and remove these rules
no-redeclare: ["warn"]
no-unused-vars: ["warn"]
no-useless-escape: ["warn"]
promise/catch-or-return: ["warn"]
promise/always-return: ["warn"]
promise/no-return-wrap: ["warn"]
# TODO: Remove after ES6 migration is complete
import/no-unresolved: ["warn"]
settings:
polyfills:
# Native Promises Only
- Promise
# whatwg-fetch
- fetch
# document-register-element
- document.registerElement
# resize-observer-polyfill
- ResizeObserver
# fast-text-encoding
- TextEncoder
# intersection-observer
- IntersectionObserver
# Core-js
- Object.assign
- Object.is
- Object.setPrototypeOf
- Object.toString
- Object.freeze
- Object.seal
- Object.preventExtensions
- Object.isFrozen
- Object.isSealed
- Object.isExtensible
- Object.getOwnPropertyDescriptor
- Object.getPrototypeOf
- Object.keys
- Object.getOwnPropertyNames
- Function.name
- Function.hasInstance
- Array.from
- Array.arrayOf
- Array.copyWithin
- Array.fill
- Array.find
- Array.findIndex
- Array.iterator
- String.fromCodePoint
- String.raw
- String.iterator
- String.codePointAt
- String.endsWith
- String.includes
- String.repeat
- String.startsWith
- String.trim
- String.anchor
- String.big
- String.blink
- String.bold
- String.fixed
- String.fontcolor
- String.fontsize
- String.italics
- String.link
- String.small
- String.strike
- String.sub
- String.sup
- RegExp
- Number
- Math
- Date
- async
- Symbol
- Map
- Set
- WeakMap
- WeakSet
- ArrayBuffer
- DataView
- Int8Array
- Uint8Array
- Uint8ClampedArray
- Int16Array
- Uint16Array
- Int32Array
- Uint32Array
- Float32Array
- Float64Array
- Reflect

36
.gitattributes vendored
View file

@ -1 +1,35 @@
/CONTRIBUTORS.md merge=union
* text=auto
CONTRIBUTORS.md merge=union
README.md text
LICENSE text
*.css text
*.eot binary
*.gif binary
*.html text diff=html
*.ico binary
*.*ignore text
*.jpg binary
*.js text
*.json text
*.lock text -diff
*.map text -diff
*.md text
*.otf binary
*.png binary
*.py text diff=python
*.svg binary
*.ts text
*.ttf binary
*.sass text
*.vue text
*.webp binary
*.woff binary
*.woff2 binary
.editorconfig text
.gitattributes export-ignore
.gitignore export-ignore
*.gitattributes linguist-language=gitattributes

4
.github/CODEOWNERS vendored Normal file
View file

@ -0,0 +1,4 @@
.ci @dkanada @EraYaN
.github @jellyfin/core
build.sh @joshuaboniface
deployment @joshuaboniface

3
.gitignore vendored
View file

@ -3,8 +3,9 @@ config.json
# npm
dist
web
node_modules
# ide
.idea
.vscode
.vscode

View file

@ -34,6 +34,7 @@
- [Ryan Hartzell](https://github.com/ryan-hartzell)
- [Thibault Nocchi](https://github.com/ThibaultNocchi)
- [MrTimscampi](https://github.com/MrTimscampi)
- [Sarab Singh](https://github.com/sarab97)
# Emby Contributors

View file

@ -1,3 +0,0 @@
{
"presets": ["@babel/preset-env"]
}

110
build.sh Executable file
View file

@ -0,0 +1,110 @@
#!/usr/bin/env bash
# build.sh - Build Jellyfin binary packages
# Part of the Jellyfin Project
set -o errexit
set -o pipefail
usage() {
echo -e "build.sh - Build Jellyfin binary packages"
echo -e "Usage:"
echo -e " $0 -t/--type <BUILD_TYPE> -p/--platform <PLATFORM> [-k/--keep-artifacts] [-l/--list-platforms]"
echo -e "Notes:"
echo -e " * BUILD_TYPE can be one of: [native, docker] and must be specified"
echo -e " * native: Build using the build script in the host OS"
echo -e " * docker: Build using the build script in a standardized Docker container"
echo -e " * PLATFORM can be any platform shown by -l/--list-platforms and must be specified"
echo -e " * If -k/--keep-artifacts is specified, transient artifacts (e.g. Docker containers) will be"
echo -e " retained after the build is finished; the source directory will still be cleaned"
echo -e " * If -l/--list-platforms is specified, all other arguments are ignored; the script will print"
echo -e " the list of supported platforms and exit"
}
list_platforms() {
declare -a platforms
platforms=(
$( find deployment -maxdepth 1 -mindepth 1 -name "build.*" | awk -F'.' '{ $1=""; printf $2; if ($3 != ""){ printf "." $3; }; if ($4 != ""){ printf "." $4; }; print ""; }' | sort )
)
echo -e "Valid platforms:"
echo
for platform in ${platforms[@]}; do
echo -e "* ${platform} : $( grep '^#=' deployment/build.${platform} | sed 's/^#= //' )"
done
}
do_build_native() {
export IS_DOCKER=NO
deployment/build.${PLATFORM}
}
do_build_docker() {
if ! dpkg --print-architecture | grep -q 'amd64'; then
echo "Docker-based builds only support amd64-based cross-building; use a 'native' build instead."
exit 1
fi
if [[ ! -f deployment/Dockerfile.${PLATFORM} ]]; then
echo "Missing Dockerfile for platform ${PLATFORM}"
exit 1
fi
if [[ ${KEEP_ARTIFACTS} == YES ]]; then
docker_args=""
else
docker_args="--rm"
fi
docker build . -t "jellyfin-builder.${PLATFORM}" -f deployment/Dockerfile.${PLATFORM}
mkdir -p ${ARTIFACT_DIR}
docker run $docker_args -v "${SOURCE_DIR}:/jellyfin" -v "${ARTIFACT_DIR}:/dist" "jellyfin-builder.${PLATFORM}"
}
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
-t|--type)
BUILD_TYPE="$2"
shift
shift
;;
-p|--platform)
PLATFORM="$2"
shift
shift
;;
-k|--keep-artifacts)
KEEP_ARTIFACTS=YES
shift
;;
-l|--list-platforms)
list_platforms
exit 0
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown option $1"
usage
exit 1
;;
esac
done
if [[ -z ${BUILD_TYPE} || -z ${PLATFORM} ]]; then
usage
exit 1
fi
export SOURCE_DIR="$( pwd )"
export ARTIFACT_DIR="${SOURCE_DIR}/../bin/${PLATFORM}"
# Determine build type
case ${BUILD_TYPE} in
native)
do_build_native
;;
docker)
do_build_docker
;;
esac

9
build.yaml Normal file
View file

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

96
bump_version Executable file
View file

@ -0,0 +1,96 @@
#!/usr/bin/env bash
# bump_version - increase the shared version and generate changelogs
set -o errexit
set -o pipefail
usage() {
echo -e "bump_version - increase the shared version and generate changelogs"
echo -e ""
echo -e "Usage:"
echo -e " $ bump_version <new_version>"
}
if [[ -z $1 ]]; then
usage
exit 1
fi
shared_version_file="src/components/apphost.js"
build_file="./build.yaml"
new_version="$1"
# Parse the version from shared version file
old_version="$(
grep "appVersion" ${shared_version_file} | head -1 \
| sed -E 's/var appVersion = "([0-9\.]+)";/\1/'
)"
echo "Old version in appHost is: $old_version"
# Set the shared version to the specified new_version
old_version_sed="$( sed 's/\./\\./g' <<<"${old_version}" )" # Escape the '.' chars
new_version_sed="$( cut -f1 -d'-' <<<"${new_version}" )"
sed -i "s/${old_version_sed}/${new_version_sed}/g" ${shared_version_file}
old_version="$(
grep "version:" ${build_file} \
| sed -E 's/version: "([0-9\.]+[-a-z0-9]*)"/\1/'
)"
echo "Old version in ${build_file}: $old_version`"
# Set the build.yaml version to the specified new_version
old_version_sed="$( sed 's/\./\\./g' <<<"${old_version}" )" # Escape the '.' chars
sed -i "s/${old_version_sed}/${new_version}/g" ${build_file}
if [[ ${new_version} == *"-"* ]]; then
new_version_deb="$( sed 's/-/~/g' <<<"${new_version}" )"
else
new_version_deb="${new_version}-1"
fi
# Write out a temporary Debian changelog with our new stuff appended and some templated formatting
debian_changelog_file="debian/changelog"
debian_changelog_temp="$( mktemp )"
# Create new temp file with our changelog
echo -e "jellyfin (${new_version_deb}) unstable; urgency=medium
* New upstream version ${new_version}; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v${new_version}
-- Jellyfin Packaging Team <packaging@jellyfin.org> $( date --rfc-2822 )
" >> ${debian_changelog_temp}
cat ${debian_changelog_file} >> ${debian_changelog_temp}
# Move into place
mv ${debian_changelog_temp} ${debian_changelog_file}
# Write out a temporary Yum changelog with our new stuff prepended and some templated formatting
fedora_spec_file="fedora/jellyfin.spec"
fedora_changelog_temp="$( mktemp )"
fedora_spec_temp_dir="$( mktemp -d )"
fedora_spec_temp="${fedora_spec_temp_dir}/jellyfin.spec.tmp"
# Make a copy of our spec file for hacking
cp ${fedora_spec_file} ${fedora_spec_temp_dir}/
pushd ${fedora_spec_temp_dir}
# Split out the stuff before and after changelog
csplit jellyfin.spec "/^%changelog/" # produces xx00 xx01
# Update the version in xx00
sed -i "s/${old_version_sed}/${new_version_sed}/g" xx00
# Remove the header from xx01
sed -i '/^%changelog/d' xx01
# Create new temp file with our changelog
echo -e "%changelog
* $( LANG=C date '+%a %b %d %Y' ) Jellyfin Packaging Team <packaging@jellyfin.org>
- New upstream version ${new_version}; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v${new_version}" >> ${fedora_changelog_temp}
cat xx01 >> ${fedora_changelog_temp}
# Reassembble
cat xx00 ${fedora_changelog_temp} > ${fedora_spec_temp}
popd
# Move into place
mv ${fedora_spec_temp} ${fedora_spec_file}
# Clean up
rm -rf ${fedora_changelog_temp} ${fedora_spec_temp_dir}
# Stage the changed files for commit
git add ${shared_version_file} ${build_file} ${debian_changelog_file} ${fedora_spec_file} Dockerfile*
git status

5
debian/changelog vendored Normal file
View file

@ -0,0 +1,5 @@
jellyfin-web (10.6.0-1) unstable; urgency=medium
* New upstream version 10.6.0; release changelog at https://github.com/jellyfin/jellyfin-web/releases/tag/v10.6.0
-- Jellyfin Packaging Team <packaging@jellyfin.org> Mon, 16 Mar 2020 11:15:00 -0400

1
debian/compat vendored Normal file
View file

@ -0,0 +1 @@
8

16
debian/control vendored Normal file
View file

@ -0,0 +1,16 @@
Source: jellyfin-web
Section: misc
Priority: optional
Maintainer: Jellyfin Team <team@jellyfin.org>
Build-Depends: debhelper (>= 9),
npm | nodejs
Standards-Version: 3.9.4
Homepage: https://jellyfin.org/
Vcs-Git: https://github.org/jellyfin/jellyfin-web.git
Vcs-Browser: https://github.org/jellyfin/jellyfin-web
Package: jellyfin-web
Recommends: jellyfin-server
Architecture: all
Description: Jellyfin is the Free Software Media System.
This package provides the Jellyfin web client.

28
debian/copyright vendored Normal file
View file

@ -0,0 +1,28 @@
Format: http://dep.debian.net/deps/dep5
Upstream-Name: jellyfin-web
Source: https://github.com/jellyfin/jellyfin-web
Files: *
Copyright: 2018-2020 Jellyfin Team
License: GPL-3.0
Files: debian/*
Copyright: 2020 Joshua Boniface <joshua@boniface.me>
License: GPL-3.0
License: GPL-3.0
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
.
On Debian systems, the complete text of the GNU General
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".

6
debian/gbp.conf vendored Normal file
View file

@ -0,0 +1,6 @@
[DEFAULT]
pristine-tar = False
cleaner = fakeroot debian/rules clean
[import-orig]
filter = [ ".git*", ".hg*", ".vs*", ".vscode*" ]

1
debian/install vendored Normal file
View file

@ -0,0 +1 @@
web usr/share/jellyfin/

1
debian/po/POTFILES.in vendored Normal file
View file

@ -0,0 +1 @@
[type: gettext/rfc822deb] templates

57
debian/po/templates.pot vendored Normal file
View file

@ -0,0 +1,57 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: jellyfin-server\n"
"Report-Msgid-Bugs-To: jellyfin-server@packages.debian.org\n"
"POT-Creation-Date: 2015-06-12 20:51-0600\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#. Type: note
#. Description
#: ../templates:1001
msgid "Jellyfin permission info:"
msgstr ""
#. Type: note
#. Description
#: ../templates:1001
msgid ""
"Jellyfin by default runs under a user named \"jellyfin\". Please ensure that the "
"user jellyfin has read and write access to any folders you wish to add to your "
"library. Otherwise please run jellyfin under a different user."
msgstr ""
#. Type: string
#. Description
#: ../templates:2001
msgid "Username to run Jellyfin as:"
msgstr ""
#. Type: string
#. Description
#: ../templates:2001
msgid "The user that jellyfin will run as."
msgstr ""
#. Type: note
#. Description
#: ../templates:3001
msgid "Jellyfin still running"
msgstr ""
#. Type: note
#. Description
#: ../templates:3001
msgid "Jellyfin is currently running. Please close it and try again."
msgstr ""

20
debian/rules vendored Executable file
View file

@ -0,0 +1,20 @@
#! /usr/bin/make -f
export DH_VERBOSE=1
%:
dh $@
# disable "make check"
override_dh_auto_test:
# disable stripping debugging symbols
override_dh_clistrip:
override_dh_auto_build:
npx yarn install
mv $(CURDIR)/dist $(CURDIR)/web
override_dh_auto_clean:
test -d $(CURDIR)/dist && rm -rf '$(CURDIR)/dist' || true
test -d $(CURDIR)/web && rm -rf '$(CURDIR)/web' || true
test -d $(CURDIR)/node_modules && rm -rf '$(CURDIR)/node_modules' || true

1
debian/source/format vendored Normal file
View file

@ -0,0 +1 @@
1.0

7
debian/source/options vendored Normal file
View file

@ -0,0 +1,7 @@
tar-ignore='.git*'
tar-ignore='**/.git'
tar-ignore='**/.hg'
tar-ignore='**/.vs'
tar-ignore='**/.vscode'
tar-ignore='deployment'
tar-ignore='*.deb'

View file

@ -0,0 +1,27 @@
FROM centos:7
# Docker build arguments
ARG SOURCE_DIR=/jellyfin
ARG ARTIFACT_DIR=/dist
# Docker run environment
ENV SOURCE_DIR=/jellyfin
ENV ARTIFACT_DIR=/dist
ENV IS_DOCKER=YES
# Prepare CentOS environment
RUN yum update -y \
&& yum install -y epel-release \
&& yum install -y @buildsys-build rpmdevtools git yum-plugins-core nodejs-yarn autoconf automake glibc-devel
# Install recent NodeJS and Yarn
RUN curl -fSsLo /etc/yum.repos.d/yarn.repo https://dl.yarnpkg.com/rpm/yarn.repo \
&& rpm -i https://rpm.nodesource.com/pub_10.x/el/7/x86_64/nodesource-release-el7-1.noarch.rpm \
&& yum install -y yarn
# Link to build script
RUN ln -sf ${SOURCE_DIR}/deployment/build.centos.all /build.sh
VOLUME ${SOURCE_DIR}/
VOLUME ${ARTIFACT_DIR}/
ENTRYPOINT ["/build.sh"]

View file

@ -0,0 +1,25 @@
FROM debian:10
# Docker build arguments
ARG SOURCE_DIR=/jellyfin
ARG ARTIFACT_DIR=/dist
# Docker run environment
ENV SOURCE_DIR=/jellyfin
ENV ARTIFACT_DIR=/dist
ENV DEB_BUILD_OPTIONS=noddebs
ENV IS_DOCKER=YES
# Prepare Debian build environment
RUN apt-get update \
&& apt-get install -y debhelper mmv npm git
# Prepare Yarn
RUN npm install -g yarn
# Link to build script
RUN ln -sf ${SOURCE_DIR}/deployment/build.debian.all /build.sh
VOLUME ${SOURCE_DIR}/
VOLUME ${ARTIFACT_DIR}/
ENTRYPOINT ["/build.sh"]

View file

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

View file

@ -0,0 +1,25 @@
FROM debian:10
# Docker build arguments
ARG SOURCE_DIR=/jellyfin
ARG ARTIFACT_DIR=/dist
# Docker run environment
ENV SOURCE_DIR=/jellyfin
ENV ARTIFACT_DIR=/dist
ENV DEB_BUILD_OPTIONS=noddebs
ENV IS_DOCKER=YES
# Prepare Debian build environment
RUN apt-get update \
&& apt-get install -y mmv npm git
# Prepare Yarn
RUN npm install -g yarn
# Link to build script
RUN ln -sf ${SOURCE_DIR}/deployment/build.portable /build.sh
VOLUME ${SOURCE_DIR}/
VOLUME ${ARTIFACT_DIR}/
ENTRYPOINT ["/build.sh"]

27
deployment/build.centos.all Executable file
View file

@ -0,0 +1,27 @@
#!/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

25
deployment/build.debian.all Executable file
View file

@ -0,0 +1,25 @@
#!/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

27
deployment/build.fedora.all Executable file
View file

@ -0,0 +1,27 @@
#!/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

28
deployment/build.portable Executable file
View file

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

21
fedora/Makefile Normal file
View file

@ -0,0 +1,21 @@
VERSION := $(shell sed -ne '/^Version:/s/.* *//p' fedora/jellyfin-web.spec)
srpm:
cd fedora/; \
SOURCE_DIR=.. \
WORKDIR="$${PWD}"; \
tar \
--transform "s,^\.,jellyfin-web-$(VERSION)," \
--exclude='.git*' \
--exclude='**/.git' \
--exclude='**/.hg' \
--exclude='deployment' \
--exclude='*.deb' \
--exclude='*.rpm' \
--exclude='jellyfin-web-$(VERSION).tar.gz' \
-czf "jellyfin-web-$(VERSION).tar.gz" \
-C $${SOURCE_DIR} ./
cd fedora/; \
rpmbuild -bs jellyfin-web.spec \
--define "_sourcedir $$PWD/" \
--define "_srcrpmdir $(outdir)"

43
fedora/jellyfin-web.spec Normal file
View file

@ -0,0 +1,43 @@
%global debug_package %{nil}
Name: jellyfin-web
Version: 10.6.0
Release: 1%{?dist}
Summary: The Free Software Media System web client
License: GPLv3
URL: https://jellyfin.org
# Jellyfin Server tarball created by `make -f .copr/Makefile srpm`, real URL ends with `v%{version}.tar.gz`
Source0: jellyfin-web-%{version}.tar.gz
%if 0%{?centos}
BuildRequires: yarn
%else
BuildRequires nodejs-yarn
%endif
BuildArch: noarch
# Disable Automatic Dependency Processing
AutoReqProv: no
%description
Jellyfin is a free software media system that puts you in control of managing and streaming your media.
%prep
%autosetup -n jellyfin-web-%{version} -b 0
%build
%install
yarn install
%{__mkdir} -p %{buildroot}%{_datadir}
mv dist %{buildroot}%{_datadir}/jellyfin-web
%{__install} -D -m 0644 LICENSE %{buildroot}%{_datadir}/licenses/jellyfin/LICENSE
%files
%attr(755,root,root) %{_datadir}/jellyfin-web
%{_datadir}/licenses/jellyfin/LICENSE
%changelog
* Mon Mar 23 2020 Jellyfin Packaging Team <packaging@jellyfin.org>
- Forthcoming stable release

View file

@ -1,5 +1,3 @@
'use strict';
const { src, dest, series, parallel, watch } = require('gulp');
const browserSync = require('browser-sync').create();
const del = require('del');
@ -10,8 +8,8 @@ const htmlmin = require('gulp-htmlmin');
const imagemin = require('gulp-imagemin');
const sourcemaps = require('gulp-sourcemaps');
const mode = require('gulp-mode')({
modes: ["development", "production"],
default: "development",
modes: ['development', 'production'],
default: 'development',
verbose: false
});
const stream = require('webpack-stream');
@ -57,7 +55,7 @@ const options = {
function serve() {
browserSync.init({
server: {
baseDir: "./dist"
baseDir: './dist'
},
port: 8080
});
@ -183,6 +181,12 @@ function copy(query) {
.pipe(browserSync.stream());
}
function copyIndex() {
return src(options.injectBundle.query, { base: './src/' })
.pipe(dest('dist/'))
.pipe(browserSync.stream());
}
function injectBundle() {
return src(options.injectBundle.query, { base: './src/' })
.pipe(inject(
@ -193,9 +197,9 @@ function injectBundle() {
}
function build(standalone) {
return series(clean, parallel(javascript, apploader(standalone), webpack, css, html, images, copy), injectBundle);
return series(clean, parallel(javascript, apploader(standalone), webpack, css, html, images, copy));
}
exports.default = build(false);
exports.standalone = build(true);
exports.default = series(build(false), copyIndex);
exports.standalone = series(build(true), injectBundle);
exports.serve = series(exports.standalone, serve);

View file

@ -5,11 +5,11 @@
"repository": "https://github.com/jellyfin/jellyfin-web",
"license": "GPL-2.0-or-later",
"devDependencies": {
"@babel/core": "^7.8.6",
"@babel/plugin-transform-modules-amd": "^7.8.3",
"@babel/core": "^7.9.6",
"@babel/plugin-transform-modules-amd": "^7.9.6",
"@babel/polyfill": "^7.8.7",
"@babel/preset-env": "^7.8.6",
"autoprefixer": "^9.7.4",
"autoprefixer": "^9.7.6",
"babel-loader": "^8.0.6",
"browser-sync": "^2.26.7",
"clean-webpack-plugin": "^3.0.0",
@ -36,13 +36,13 @@
"gulp-sass": "^4.0.2",
"gulp-sourcemaps": "^2.6.5",
"gulp-terser": "^1.2.0",
"html-webpack-plugin": "^4.0.2",
"html-webpack-plugin": "^4.3.0",
"lazypipe": "^1.0.2",
"node-sass": "^4.13.1",
"postcss-loader": "^3.0.0",
"postcss-preset-env": "^6.7.0",
"style-loader": "^1.1.3",
"stylelint": "^13.1.0",
"stylelint": "^13.3.3",
"stylelint-config-rational-order": "^0.1.2",
"stylelint-no-browser-hacks": "^1.2.1",
"stylelint-order": "^4.0.0",
@ -56,26 +56,29 @@
"dependencies": {
"alameda": "^1.4.0",
"classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz",
"core-js": "^3.6.4",
"date-fns": "^2.11.1",
"core-js": "^3.6.5",
"date-fns": "^2.12.0",
"document-register-element": "^1.14.3",
"fast-text-encoding": "^1.0.1",
"flv.js": "^1.5.0",
"headroom.js": "^0.11.0",
"hls.js": "^0.13.1",
"howler": "^2.1.3",
"intersection-observer": "^0.7.0",
"intersection-observer": "^0.10.0",
"jellyfin-apiclient": "^1.1.1",
"jellyfin-noto": "https://github.com/jellyfin/jellyfin-noto",
"jquery": "^3.4.1",
"jquery": "^3.5.0",
"jstree": "^3.3.7",
"libass-wasm": "https://github.com/jellyfin/JavascriptSubtitlesOctopus#4.0.0-jf-cordova",
"libass-wasm": "https://github.com/jellyfin/JavascriptSubtitlesOctopus#4.0.0-jf-smarttv",
"material-design-icons-iconfont": "^5.0.1",
"native-promise-only": "^0.8.0-a",
"page": "^1.11.5",
"page": "^1.11.6",
"query-string": "^6.11.1",
"resize-observer-polyfill": "^1.5.1",
"screenfull": "^5.0.2",
"shaka-player": "^2.5.10",
"sortablejs": "^1.10.2",
"swiper": "^5.3.1",
"swiper": "^5.3.7",
"webcomponents.js": "^0.7.24",
"whatwg-fetch": "^3.0.0"
},
@ -88,18 +91,21 @@
"test": [
"src/components/autoFocuser.js",
"src/components/cardbuilder/cardBuilder.js",
"src/components/dom.js",
"src/components/filedownloader.js",
"src/components/filesystem.js",
"src/components/input/keyboardnavigation.js",
"src/components/images/imageLoader.js",
"src/components/lazyloader/lazyloader-intersectionobserver.js",
"src/components/playback/mediasession.js",
"src/components/sanatizefilename.js",
"src/components/scrollManager.js",
"src/scripts/dfnshelper.js",
"src/scripts/dom.js",
"src/scripts/filesystem.js",
"src/scripts/imagehelper.js",
"src/scripts/inputManager.js",
"src/scripts/keyboardnavigation.js",
"src/scripts/settings/appSettings.js",
"src/scripts/settings/userSettings.js",
"src/scripts/settings/webSettings.js",
"src/scripts/dfnshelper.js",
"src/scripts/imagehelper.js",
"src/scripts/inputManager.js"
"src/scripts/settings/webSettings.js"
],
"plugins": [
"@babel/plugin-transform-modules-amd"
@ -128,7 +134,7 @@
"build:development": "gulp --development",
"build:production": "gulp --production",
"build:standalone": "gulp standalone --development",
"lint": "eslint \"src\"",
"lint": "eslint \".\"",
"stylelint": "stylelint \"src/**/*.css\""
}
}

View file

@ -1,11 +1,14 @@
const packageConfig = require('./package.json');
const postcssPresetEnv = require('postcss-preset-env');
const autoprefixer = require('autoprefixer');
const cssnano = require('cssnano');
const config = () => ({
plugins: [
postcssPresetEnv(),
cssnano()
]
plugins: [
postcssPresetEnv({browsers: packageConfig.browserslist}),
autoprefixer(),
cssnano()
]
});
module.exports = config
module.exports = config;

View file

@ -8,9 +8,8 @@
<a is="emby-linkbutton" class="raised button-alt headerHelpButton" target="_blank" href="https://docs.jellyfin.org/general/server/plugins/index.html">${Help}</a>
</div>
<p id="tagline" style="font-style: italic;"></p>
<p id="pPreviewImage"></p>
<p id="overview"></p>
<p id="overview" style="font-style: italic;"></p>
<p id="description"></p>
</div>
<div class="verticalSection">
@ -28,7 +27,6 @@
</button>
<div class="fieldDescription">${ServerRestartNeededAfterPluginInstall}</div>
</div>
<p id="nonServerMsg"></p>
</form>
</div>
</div>
@ -37,9 +35,6 @@
<div is="emby-collapse" title="${HeaderDeveloperInfo}">
<div class="collapseContent">
<p id="developer"></p>
<p id="pViewWebsite" style="display: none;">
<a is="emby-linkbutton" class="button-link" href="#" target="_blank">${ButtonViewWebsite}</a>
</p>
</div>
</div>

View file

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

View file

@ -21,7 +21,11 @@
}
.libraryPage {
padding-top: 7em;
padding-top: 7em !important;
}
.layout-mobile .libraryPage {
padding-top: 4em !important;
}
.itemDetailPage {
@ -128,10 +132,6 @@
margin-top: 0;
}
.layout-mobile .pageTitleWithDefaultLogo {
background-image: url(../img/icon-transparent.png);
}
.headerLeft,
.skinHeader {
display: -webkit-box;
@ -242,10 +242,11 @@
}
.mainDrawer-scrollContainer {
margin-bottom: 10vh;
padding-bottom: 10vh;
}
@media all and (min-width: 40em) {
.dashboardDocument .adminDrawerLogo,
.dashboardDocument .mainDrawerButton {
display: none !important;
}
@ -313,7 +314,7 @@
}
.dashboardDocument .mainDrawer-scrollContainer {
margin-top: 4.6em !important;
margin-top: 4.65em !important;
}
}
@ -516,6 +517,13 @@
.itemName {
margin: 0.5em 0;
font-weight: 600;
}
.nameContainer {
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.itemMiscInfo {
@ -533,7 +541,6 @@
.layout-mobile .itemName,
.layout-mobile .itemMiscInfo,
.layout-mobile .mainDetailButtons {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
@ -575,7 +582,6 @@
.infoText {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: left;
}
@ -606,12 +612,11 @@
}
.detailLogo {
width: 67.25vw;
height: 14.5vh;
width: 30vw;
height: 25vh;
position: absolute;
top: 15vh;
right: 0;
-webkit-background-size: contain;
top: 10vh;
right: 20vw;
background-size: contain;
}
@ -619,26 +624,8 @@
display: none;
}
@media all and (max-width: 87.5em) {
.detailLogo {
right: 5%;
}
}
@media all and (max-width: 75em) {
.detailLogo {
right: 2%;
}
}
@media all and (max-width: 68.75em) {
.detailLogo {
width: 14.91em;
height: 3.5em;
right: 5%;
bottom: 5%;
top: auto;
background-position: center right;
display: none;
}
}
@ -657,12 +644,7 @@ div.itemDetailGalleryLink.defaultCardBackground {
height: 23vw; /* Dirty hack to get it to look somewhat square. Less than ideal. */
}
.btnSyncComplete i {
-webkit-border-radius: 100em;
border-radius: 100em;
}
.itemDetailGalleryLink.defaultCardBackground > i {
.itemDetailGalleryLink.defaultCardBackground > .material-icons {
font-size: 15vw;
margin-top: 50%;
transform: translateY(-50%);
@ -694,10 +676,6 @@ div.itemDetailGalleryLink.defaultCardBackground {
}
}
.btnSyncComplete {
background: #673ab7 !important;
}
.emby-button.detailFloatingButton {
position: absolute;
background-color: rgba(0, 0, 0, 0.5) !important;
@ -709,7 +687,7 @@ div.itemDetailGalleryLink.defaultCardBackground {
color: rgba(255, 255, 255, 0.76);
}
.emby-button.detailFloatingButton i {
.emby-button.detailFloatingButton .material-icons {
font-size: 3.5em;
}

View file

@ -96,3 +96,16 @@ div[data-role=page] {
margin-right: auto;
width: 85%;
}
.headroom {
will-change: transform;
transition: transform 200ms linear;
}
.headroom--pinned {
transform: translateY(0%);
}
.headroom--unpinned {
transform: translateY(-100%);
}

View file

@ -5,137 +5,174 @@
var _define = window.define;
// document-register-element
var docRegister = require("document-register-element");
_define("document-register-element", function() {
var docRegister = require('document-register-element');
_define('document-register-element', function() {
return docRegister;
});
// fetch
var fetch = require("whatwg-fetch");
_define("fetch", function() {
var fetch = require('whatwg-fetch');
_define('fetch', function() {
return fetch;
});
// query-string
var query = require("query-string");
_define("queryString", function() {
var query = require('query-string');
_define('queryString', function() {
return query;
});
// flvjs
var flvjs = require("flv.js/dist/flv").default;
_define("flvjs", function() {
var flvjs = require('flv.js/dist/flv').default;
_define('flvjs', function() {
return flvjs;
});
// jstree
var jstree = require("jstree");
require("jstree/dist/themes/default/style.css");
_define("jstree", function() {
var jstree = require('jstree');
require('jstree/dist/themes/default/style.css');
_define('jstree', function() {
return jstree;
});
// jquery
var jquery = require("jquery");
_define("jQuery", function() {
var jquery = require('jquery');
_define('jQuery', function() {
return jquery;
});
// hlsjs
var hlsjs = require("hls.js");
_define("hlsjs", function() {
var hlsjs = require('hls.js');
_define('hlsjs', function() {
return hlsjs;
});
// howler
var howler = require("howler");
_define("howler", function() {
var howler = require('howler');
_define('howler', function() {
return howler;
});
// resize-observer-polyfill
var resize = require("resize-observer-polyfill").default;
_define("resize-observer-polyfill", function() {
var resize = require('resize-observer-polyfill').default;
_define('resize-observer-polyfill', function() {
return resize;
});
// shaka
var shaka = require("shaka-player");
_define("shaka", function() {
var shaka = require('shaka-player');
_define('shaka', function() {
return shaka;
});
// swiper
var swiper = require("swiper/js/swiper");
require("swiper/css/swiper.min.css");
_define("swiper", function() {
var swiper = require('swiper/js/swiper');
require('swiper/css/swiper.min.css');
_define('swiper', function() {
return swiper;
});
// sortable
var sortable = require("sortablejs").default;
_define("sortable", function() {
var sortable = require('sortablejs').default;
_define('sortable', function() {
return sortable;
});
// webcomponents
var webcomponents = require("webcomponents.js/webcomponents-lite");
_define("webcomponents", function() {
var webcomponents = require('webcomponents.js/webcomponents-lite');
_define('webcomponents', function() {
return webcomponents;
});
// libass-wasm
var libassWasm = require("libass-wasm");
_define("JavascriptSubtitlesOctopus", function() {
var libassWasm = require('libass-wasm');
_define('JavascriptSubtitlesOctopus', function() {
return libassWasm;
});
// material-icons
var materialIcons = require("material-design-icons-iconfont/dist/material-design-icons.css");
_define("material-icons", function() {
var materialIcons = require('material-design-icons-iconfont/dist/material-design-icons.css');
_define('material-icons', function() {
return materialIcons;
});
// noto font
var noto = require("jellyfin-noto");
_define("jellyfin-noto", function () {
var noto = require('jellyfin-noto');
_define('jellyfin-noto', function () {
return noto;
});
// page.js
var page = require("page");
_define("page", function() {
var page = require('page');
_define('page', function() {
return page;
});
var polyfill = require("@babel/polyfill/dist/polyfill");
_define("polyfill", function () {
// core-js
var polyfill = require('@babel/polyfill/dist/polyfill');
_define('polyfill', function () {
return polyfill;
});
// domtokenlist-shim
var classlist = require("classlist.js");
_define("classlist-polyfill", function () {
var classlist = require('classlist.js');
_define('classlist-polyfill', function () {
return classlist;
});
// Date-FNS
var dateFns = require("date-fns");
_define("date-fns", function () {
var dateFns = require('date-fns');
_define('date-fns', function () {
return dateFns;
});
var dateFnsLocale = require("date-fns/locale");
_define("date-fns/locale", function () {
var dateFnsLocale = require('date-fns/locale');
_define('date-fns/locale', function () {
return dateFnsLocale;
});
var fast_text_encoding = require("fast-text-encoding");
_define("fast-text-encoding", function () {
var fast_text_encoding = require('fast-text-encoding');
_define('fast-text-encoding', function () {
return fast_text_encoding;
});
var intersection_observer = require("intersection-observer");
_define("intersection-observer", function () {
// intersection-observer
var intersection_observer = require('intersection-observer');
_define('intersection-observer', function () {
return intersection_observer;
});
// screenfull
var screenfull = require('screenfull');
_define('screenfull', function () {
return screenfull;
});
// headroom.js
var headroom = require('headroom.js/dist/headroom');
_define('headroom', function () {
return headroom;
});
// apiclient
var apiclient = require('jellyfin-apiclient');
_define('apiclient', function () {
return apiclient.ApiClient;
});
_define('events', function () {
return apiclient.Events;
});
_define('credentialprovider', function () {
return apiclient.Credentials;
});
_define('connectionManagerFactory', function () {
return apiclient.ConnectionManager;
});
_define('appStorage', function () {
return apiclient.AppStorage;
});

View file

@ -1,5 +1,5 @@
define(["dialogHelper", "datetime", "emby-select", "paper-icon-button-light", "formDialogStyle"], function (dialogHelper, datetime) {
"use strict";
define(['dialogHelper', 'datetime', 'globalize', 'emby-select', 'paper-icon-button-light', 'formDialogStyle'], function (dialogHelper, datetime, globalize) {
'use strict';
function getDisplayTime(hours) {
var minutes = 0;
@ -13,32 +13,32 @@ define(["dialogHelper", "datetime", "emby-select", "paper-icon-button-light", "f
}
function populateHours(context) {
var html = "";
var html = '';
for (var 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>";
context.querySelector("#selectStart").innerHTML = html;
context.querySelector("#selectEnd").innerHTML = html;
html += '<option value="24">' + getDisplayTime(0) + '</option>';
context.querySelector('#selectStart').innerHTML = html;
context.querySelector('#selectEnd').innerHTML = html;
}
function loadSchedule(context, schedule) {
context.querySelector("#selectDay").value = schedule.DayOfWeek || "Sunday";
context.querySelector("#selectStart").value = schedule.StartHour || 0;
context.querySelector("#selectEnd").value = schedule.EndHour || 0;
context.querySelector('#selectDay').value = schedule.DayOfWeek || 'Sunday';
context.querySelector('#selectStart').value = schedule.StartHour || 0;
context.querySelector('#selectEnd').value = schedule.EndHour || 0;
}
function submitSchedule(context, options) {
var updatedSchedule = {
DayOfWeek: context.querySelector("#selectDay").value,
StartHour: context.querySelector("#selectStart").value,
EndHour: context.querySelector("#selectEnd").value
DayOfWeek: context.querySelector('#selectDay').value,
StartHour: context.querySelector('#selectStart').value,
EndHour: context.querySelector('#selectEnd').value
};
if (parseFloat(updatedSchedule.StartHour) >= parseFloat(updatedSchedule.EndHour)) {
return void alert(Globalize.translate("ErrorMessageStartHourGreaterThanEnd"));
return void alert(globalize.translate('ErrorMessageStartHourGreaterThanEnd'));
}
context.submitted = true;
@ -50,32 +50,32 @@ define(["dialogHelper", "datetime", "emby-select", "paper-icon-button-light", "f
show: function (options) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open("GET", "components/accessschedule/accessschedule.template.html", true);
xhr.open('GET', 'components/accessschedule/accessschedule.template.html', true);
xhr.onload = function (e) {
var template = this.response;
var dlg = dialogHelper.createDialog({
removeOnClose: true,
size: "small"
size: 'small'
});
dlg.classList.add("formDialog");
var html = "";
html += Globalize.translateDocument(template);
dlg.classList.add('formDialog');
var html = '';
html += globalize.translateDocument(template);
dlg.innerHTML = html;
populateHours(dlg);
loadSchedule(dlg, options.schedule);
dialogHelper.open(dlg);
dlg.addEventListener("close", function () {
dlg.addEventListener('close', function () {
if (dlg.submitted) {
resolve(options.schedule);
} else {
reject();
}
});
dlg.querySelector(".btnCancel").addEventListener("click", function (e) {
dlg.querySelector('.btnCancel').addEventListener('click', function (e) {
dialogHelper.close(dlg);
});
dlg.querySelector("form").addEventListener("submit", function (e) {
dlg.querySelector('form').addEventListener('submit', function (e) {
submitSchedule(dlg, options);
e.preventDefault();
return false;

View file

@ -1,6 +1,6 @@
<div class="formDialogHeader">
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1">
<i class="material-icons arrow_back"></i>
<span class="material-icons arrow_back"></span>
</button>
<h3 class="formDialogHeaderTitle">
${HeaderAccessSchedule}

View file

@ -136,7 +136,7 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'browser', 'dom', 'emby-bu
// Admittedly a hack but right now the scrollbar is being factored into the width which is causing truncation
if (options.items.length > 20) {
var minWidth = dom.getWindowSize().innerWidth >= 300 ? 240 : 200;
style += "min-width:" + minWidth + "px;";
style += 'min-width:' + minWidth + 'px;';
}
var i;
@ -158,7 +158,7 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'browser', 'dom', 'emby-bu
}
if (layoutManager.tv) {
html += '<button is="paper-icon-button-light" class="btnCloseActionSheet hide-mouse-idle-tv" tabindex="-1"><i class="material-icons arrow_back"></i></button>';
html += '<button is="paper-icon-button-light" class="btnCloseActionSheet hide-mouse-idle-tv" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
}
// If any items have an icon, give them all an icon just to make sure they're all lined up evenly
@ -226,9 +226,9 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'browser', 'dom', 'emby-bu
if (itemIcon) {
html += '<i class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons">' + itemIcon + '</i>';
html += '<span class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons ' + itemIcon + '"></span>';
} else if (renderIcon && !center) {
html += '<i class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons" style="visibility:hidden;">check</i>';
html += '<span class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons check" style="visibility:hidden;"></span>';
}
html += '<div class="listItemBody actionsheetListItemBody">';

View file

@ -1,59 +1,59 @@
define(["events", "globalize", "dom", "date-fns", "dfnshelper", "userSettings", "serverNotifications", "connectionManager", "emby-button", "listViewStyle"], function (events, globalize, dom, datefns, dfnshelper, userSettings, serverNotifications, connectionManager) {
"use strict";
define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings', 'serverNotifications', 'connectionManager', 'emby-button', 'listViewStyle'], function (events, globalize, dom, datefns, dfnshelper, userSettings, serverNotifications, connectionManager) {
'use strict';
function getEntryHtml(entry, apiClient) {
var html = "";
var html = '';
html += '<div class="listItem listItem-border">';
var color = "#00a4dc";
var icon = "notifications";
var color = '#00a4dc';
var icon = 'notifications';
if ("Error" == entry.Severity || "Fatal" == entry.Severity || "Warn" == entry.Severity) {
color = "#cc0000";
icon = "notification_important";
if ('Error' == entry.Severity || 'Fatal' == entry.Severity || 'Warn' == entry.Severity) {
color = '#cc0000';
icon = 'notification_important';
}
if (entry.UserId && entry.UserPrimaryImageTag) {
html += '<i class="listItemIcon material-icons" style="width:2em!important;height:2em!important;padding:0;color:transparent;background-color:' + color + ";background-image:url('" + apiClient.getUserImageUrl(entry.UserId, {
type: "Primary",
html += '<span class="listItemIcon material-icons dvr" style="width:2em!important;height:2em!important;padding:0;color:transparent;background-color:' + color + ";background-image:url('" + apiClient.getUserImageUrl(entry.UserId, {
type: 'Primary',
tag: entry.UserPrimaryImageTag
}) + "');background-repeat:no-repeat;background-position:center center;background-size: cover;\">dvr</i>";
}) + "');background-repeat:no-repeat;background-position:center center;background-size: cover;\"></span>";
} else {
html += '<i class="listItemIcon material-icons" style="background-color:' + color + '">' + icon + '</i>';
html += '<span class="listItemIcon material-icons ' + icon + '" style="background-color:' + color + '"></span>';
}
html += '<div class="listItemBody three-line">';
html += '<div class="listItemBodyText">';
html += entry.Name;
html += "</div>";
html += '</div>';
html += '<div class="listItemBodyText secondary">';
html += datefns.formatRelative(Date.parse(entry.Date), Date.parse(new Date()), { locale: dfnshelper.getLocale() });
html += "</div>";
html += '</div>';
html += '<div class="listItemBodyText secondary listItemBodyText-nowrap">';
html += entry.ShortOverview || "";
html += "</div>";
html += "</div>";
html += entry.ShortOverview || '';
html += '</div>';
html += '</div>';
if (entry.Overview) {
html += '<button type="button" is="paper-icon-button-light" class="btnEntryInfo" data-id="' + entry.Id + '" title="' + globalize.translate("Info") + '"><i class="material-icons">info</i></button>';
html += '<button type="button" is="paper-icon-button-light" class="btnEntryInfo" data-id="' + entry.Id + '" title="' + globalize.translate('Info') + '"><span class="material-icons info"></span></button>';
}
return html += "</div>";
return html += '</div>';
}
function renderList(elem, apiClient, result, startIndex, limit) {
elem.innerHTML = result.Items.map(function (i) {
return getEntryHtml(i, apiClient);
}).join("");
}).join('');
}
function reloadData(instance, elem, apiClient, startIndex, limit) {
if (null == startIndex) {
startIndex = parseInt(elem.getAttribute("data-activitystartindex") || "0");
startIndex = parseInt(elem.getAttribute('data-activitystartindex') || '0');
}
limit = limit || parseInt(elem.getAttribute("data-activitylimit") || "7");
limit = limit || parseInt(elem.getAttribute('data-activitylimit') || '7');
var minDate = new Date();
var hasUserId = "false" !== elem.getAttribute("data-useractivity");
var hasUserId = 'false' !== elem.getAttribute('data-useractivity');
if (hasUserId) {
minDate.setTime(minDate.getTime() - 24 * 60 * 60 * 1000); // one day back
@ -61,22 +61,22 @@ define(["events", "globalize", "dom", "date-fns", "dfnshelper", "userSettings",
minDate.setTime(minDate.getTime() - 7 * 24 * 60 * 60 * 1000); // one week back
}
ApiClient.getJSON(ApiClient.getUrl("System/ActivityLog/Entries", {
ApiClient.getJSON(ApiClient.getUrl('System/ActivityLog/Entries', {
startIndex: startIndex,
limit: limit,
minDate: minDate.toISOString(),
hasUserId: hasUserId
})).then(function (result) {
elem.setAttribute("data-activitystartindex", startIndex);
elem.setAttribute("data-activitylimit", limit);
elem.setAttribute('data-activitystartindex', startIndex);
elem.setAttribute('data-activitylimit', limit);
if (!startIndex) {
var activityContainer = dom.parentWithClass(elem, "activityContainer");
var activityContainer = dom.parentWithClass(elem, 'activityContainer');
if (activityContainer) {
if (result.Items.length) {
activityContainer.classList.remove("hide");
activityContainer.classList.remove('hide');
} else {
activityContainer.classList.add("hide");
activityContainer.classList.add('hide');
}
}
}
@ -95,10 +95,10 @@ define(["events", "globalize", "dom", "date-fns", "dfnshelper", "userSettings",
}
function onListClick(e) {
var btnEntryInfo = dom.parentWithClass(e.target, "btnEntryInfo");
var btnEntryInfo = dom.parentWithClass(e.target, 'btnEntryInfo');
if (btnEntryInfo) {
var id = btnEntryInfo.getAttribute("data-id");
var id = btnEntryInfo.getAttribute('data-id');
var items = this.items;
if (items) {
@ -114,7 +114,7 @@ define(["events", "globalize", "dom", "date-fns", "dfnshelper", "userSettings",
}
function showItemOverview(item) {
require(["alert"], function (alert) {
require(['alert'], function (alert) {
alert({
text: item.Overview
});
@ -124,28 +124,28 @@ define(["events", "globalize", "dom", "date-fns", "dfnshelper", "userSettings",
function ActivityLog(options) {
this.options = options;
var element = options.element;
element.classList.add("activityLogListWidget");
element.addEventListener("click", onListClick.bind(this));
element.classList.add('activityLogListWidget');
element.addEventListener('click', onListClick.bind(this));
var apiClient = connectionManager.getApiClient(options.serverId);
reloadData(this, element, apiClient);
var onUpdate = onActivityLogUpdate.bind(this);
this.updateFn = onUpdate;
events.on(serverNotifications, "ActivityLogEntry", onUpdate);
apiClient.sendMessage("ActivityLogEntryStart", "0,1500");
events.on(serverNotifications, 'ActivityLogEntry', onUpdate);
apiClient.sendMessage('ActivityLogEntryStart', '0,1500');
}
ActivityLog.prototype.destroy = function () {
var options = this.options;
if (options) {
options.element.classList.remove("activityLogListWidget");
connectionManager.getApiClient(options.serverId).sendMessage("ActivityLogEntryStop", "0,1500");
options.element.classList.remove('activityLogListWidget');
connectionManager.getApiClient(options.serverId).sendMessage('ActivityLogEntryStop', '0,1500');
}
var onUpdate = this.updateFn;
if (onUpdate) {
events.off(serverNotifications, "ActivityLogEntry", onUpdate);
events.off(serverNotifications, 'ActivityLogEntry', onUpdate);
}
this.items = null;

View file

@ -67,7 +67,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
html += '<div class="' + rowClassName + '">';
if (options.mode === 'keyboard') {
html += '<button data-value=" " is="paper-icon-button-light" class="' + alphaPickerButtonClassName + '"><i class="material-icons alphaPickerButtonIcon space_bar"></i></button>';
html += '<button data-value=" " is="paper-icon-button-light" class="' + alphaPickerButtonClassName + '"><span class="material-icons alphaPickerButtonIcon space_bar"></span></button>';
} else {
letters = ['#'];
html += mapLetters(letters, vertical).join('');
@ -77,7 +77,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
html += mapLetters(letters, vertical).join('');
if (options.mode === 'keyboard') {
html += '<button data-value="backspace" is="paper-icon-button-light" class="' + alphaPickerButtonClassName + '"><i class="material-icons alphaPickerButtonIcon">backspace</i></button>';
html += '<button data-value="backspace" is="paper-icon-button-light" class="' + alphaPickerButtonClassName + '"><span class="material-icons alphaPickerButtonIcon backspace"></span></button>';
html += '</div>';
letters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
@ -132,7 +132,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
if (alphaPickerButton) {
var value = alphaPickerButton.getAttribute('data-value');
element.dispatchEvent(new CustomEvent("alphavalueclicked", {
element.dispatchEvent(new CustomEvent('alphavalueclicked', {
cancelable: false,
detail: {
value: value
@ -262,7 +262,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
}
if (applyValue) {
element.dispatchEvent(new CustomEvent("alphavaluechanged", {
element.dispatchEvent(new CustomEvent('alphavaluechanged', {
cancelable: false,
detail: {
value: value

View file

@ -16,7 +16,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
show('/settings/settings.html');
},
showNowPlaying: function () {
show("/nowplaying.html");
show('/nowplaying.html');
}
};
@ -200,8 +200,8 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
var apiClient = this;
if (data.status === 401) {
if (data.errorCode === "ParentalControl") {
if (data.status === 403) {
if (data.errorCode === 'ParentalControl') {
var isCurrentAllowed = currentRouteInfo ? (currentRouteInfo.route.anonymous || currentRouteInfo.route.startup) : true;
@ -541,15 +541,15 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
}
function param(name, url) {
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS, "i");
name = name.replace(/[\[]/, '\\\[').replace(/[\]]/, '\\\]');
var regexS = '[\\?&]' + name + '=([^&#]*)';
var regex = new RegExp(regexS, 'i');
var results = regex.exec(url || getWindowLocationSearch());
if (results == null) {
return "";
return '';
} else {
return decodeURIComponent(results[1].replace(/\+/g, " "));
return decodeURIComponent(results[1].replace(/\+/g, ' '));
}
}

View file

@ -1,17 +1,17 @@
define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], function (appSettings, browser, events, htmlMediaHelper, webSettings) {
"use strict";
define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'globalize'], function (appSettings, browser, events, htmlMediaHelper, webSettings, globalize) {
'use strict';
function getBaseProfileOptions(item) {
var disableHlsVideoAudioCodecs = [];
if (item && htmlMediaHelper.enableHlsJsPlayer(item.RunTimeTicks, item.MediaType)) {
if (browser.edge || browser.msie) {
disableHlsVideoAudioCodecs.push("mp3");
disableHlsVideoAudioCodecs.push('mp3');
}
disableHlsVideoAudioCodecs.push("ac3");
disableHlsVideoAudioCodecs.push("eac3");
disableHlsVideoAudioCodecs.push("opus");
disableHlsVideoAudioCodecs.push('ac3');
disableHlsVideoAudioCodecs.push('eac3');
disableHlsVideoAudioCodecs.push('opus');
}
return {
@ -22,7 +22,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
function getDeviceProfileForWindowsUwp(item) {
return new Promise(function (resolve, reject) {
require(["browserdeviceprofile", "environments/windows-uwp/mediacaps"], function (profileBuilder, uwpMediaCaps) {
require(['browserdeviceprofile', 'environments/windows-uwp/mediacaps'], function (profileBuilder, uwpMediaCaps) {
var profileOptions = getBaseProfileOptions(item);
profileOptions.supportsDts = uwpMediaCaps.supportsDTS();
profileOptions.supportsTrueHd = uwpMediaCaps.supportsDolby();
@ -40,26 +40,15 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
}
return new Promise(function (resolve) {
require(["browserdeviceprofile"], function (profileBuilder) {
require(['browserdeviceprofile'], function (profileBuilder) {
var profile;
if (window.NativeShell) {
profile = window.NativeShell.AppHost.getDeviceProfile(profileBuilder);
} else {
profile = profileBuilder(getBaseProfileOptions(item));
if (item && !options.isRetry && "allcomplexformats" !== appSettings.get("subtitleburnin")) {
if (!browser.orsay && !browser.tizen) {
profile.SubtitleProfiles.push({
Format: "ass",
Method: "External"
});
profile.SubtitleProfiles.push({
Format: "ssa",
Method: "External"
});
}
}
var builderOpts = getBaseProfileOptions(item);
builderOpts.enableSsaRender = (item && !options.isRetry && 'allcomplexformats' !== appSettings.get('subtitleburnin'));
profile = profileBuilder(builderOpts);
}
resolve(profile);
@ -68,12 +57,12 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
}
function escapeRegExp(str) {
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1');
}
function replaceAll(originalString, strReplace, strWith) {
var strReplace2 = escapeRegExp(strReplace);
var reg = new RegExp(strReplace2, "ig");
var reg = new RegExp(strReplace2, 'ig');
return originalString.replace(reg, strWith);
}
@ -81,7 +70,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
var keys = [];
if (keys.push(navigator.userAgent), keys.push(new Date().getTime()), self.btoa) {
var result = replaceAll(btoa(keys.join("|")), "=", "1");
var result = replaceAll(btoa(keys.join('|')), '=', '1');
return Promise.resolve(result);
}
@ -89,7 +78,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
}
function getDeviceId() {
var key = "_deviceId2";
var key = '_deviceId2';
var deviceId = appSettings.get(key);
if (deviceId) {
@ -104,16 +93,16 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
function getDeviceName() {
var deviceName;
deviceName = browser.tizen ? "Samsung Smart TV" : browser.web0s ? "LG Smart TV" : browser.operaTv ? "Opera TV" : browser.xboxOne ? "Xbox One" : browser.ps4 ? "Sony PS4" : browser.chrome ? "Chrome" : browser.edge ? "Edge" : browser.firefox ? "Firefox" : browser.msie ? "Internet Explorer" : browser.opera ? "Opera" : browser.safari ? "Safari" : "Web Browser";
deviceName = browser.tizen ? 'Samsung Smart TV' : browser.web0s ? 'LG Smart TV' : browser.operaTv ? 'Opera TV' : browser.xboxOne ? 'Xbox One' : browser.ps4 ? 'Sony PS4' : browser.chrome ? 'Chrome' : browser.edge ? 'Edge' : browser.firefox ? 'Firefox' : browser.msie ? 'Internet Explorer' : browser.opera ? 'Opera' : browser.safari ? 'Safari' : 'Web Browser';
if (browser.ipad) {
deviceName += " iPad";
deviceName += ' iPad';
} else {
if (browser.iphone) {
deviceName += " iPhone";
deviceName += ' iPhone';
} else {
if (browser.android) {
deviceName += " Android";
deviceName += ' Android';
}
}
}
@ -135,12 +124,12 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
}
var element = document.documentElement;
return (element.requestFullscreen || element.mozRequestFullScreen || element.webkitRequestFullscreen || element.msRequestFullscreen) || document.createElement("video").webkitEnterFullscreen;
return (element.requestFullscreen || element.mozRequestFullScreen || element.webkitRequestFullscreen || element.msRequestFullscreen) || document.createElement('video').webkitEnterFullscreen;
}
function getSyncProfile() {
return new Promise(function (resolve) {
require(["browserdeviceprofile", "appSettings"], function (profileBuilder, appSettings) {
require(['browserdeviceprofile', 'appSettings'], function (profileBuilder, appSettings) {
var profile;
if (window.NativeShell) {
@ -156,7 +145,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
}
function getDefaultLayout() {
return "desktop";
return 'desktop';
}
function supportsHtmlMediaAutoplay() {
@ -173,20 +162,20 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
function supportsCue() {
try {
var video = document.createElement("video");
var style = document.createElement("style");
var video = document.createElement('video');
var style = document.createElement('style');
style.textContent = "video::cue {background: inherit}";
style.textContent = 'video::cue {background: inherit}';
document.body.appendChild(style);
document.body.appendChild(video);
var cue = window.getComputedStyle(video, "::cue").background;
var cue = window.getComputedStyle(video, '::cue').background;
document.body.removeChild(style);
document.body.removeChild(video);
return !!cue.length;
} catch (err) {
console.error("error detecting cue support: " + err);
console.error('error detecting cue support: ' + err);
return false;
}
}
@ -194,15 +183,15 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
function onAppVisible() {
if (isHidden) {
isHidden = false;
console.debug("triggering app resume event");
events.trigger(appHost, "resume");
console.debug('triggering app resume event');
events.trigger(appHost, 'resume');
}
}
function onAppHidden() {
if (!isHidden) {
isHidden = true;
console.debug("app is hidden");
console.debug('app is hidden');
}
}
@ -210,92 +199,88 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
var features = [];
if (navigator.share) {
features.push("sharing");
features.push('sharing');
}
if (!browser.edgeUwp && !browser.tv && !browser.xboxOne && !browser.ps4) {
features.push("filedownload");
features.push('filedownload');
}
if (browser.operaTv || browser.tizen || browser.orsay || browser.web0s) {
features.push("exit");
features.push('exit');
} else {
features.push("exitmenu");
features.push("plugins");
features.push('exitmenu');
features.push('plugins');
}
if (!browser.operaTv && !browser.tizen && !browser.orsay && !browser.web0s && !browser.ps4) {
features.push("externallinks");
features.push("externalpremium");
features.push('externallinks');
features.push('externalpremium');
}
if (!browser.operaTv) {
features.push("externallinkdisplay");
features.push('externallinkdisplay');
}
if (supportsVoiceInput()) {
features.push("voiceinput");
}
if (!browser.tv && !browser.xboxOne) {
browser.ps4;
features.push('voiceinput');
}
if (supportsHtmlMediaAutoplay()) {
features.push("htmlaudioautoplay");
features.push("htmlvideoautoplay");
features.push('htmlaudioautoplay');
features.push('htmlvideoautoplay');
}
if (browser.edgeUwp) {
features.push("sync");
features.push('sync');
}
if (supportsFullscreen()) {
features.push("fullscreenchange");
features.push('fullscreenchange');
}
if (browser.chrome || browser.edge && !browser.slow) {
if (!browser.noAnimation && !browser.edgeUwp && !browser.xboxOne) {
features.push("imageanalysis");
features.push('imageanalysis');
}
}
if (browser.tv || browser.xboxOne || browser.ps4 || browser.mobile) {
features.push("physicalvolumecontrol");
features.push('physicalvolumecontrol');
}
if (!browser.tv && !browser.xboxOne && !browser.ps4) {
features.push("remotecontrol");
features.push('remotecontrol');
}
if (!browser.operaTv && !browser.tizen && !browser.orsay && !browser.web0s && !browser.edgeUwp) {
features.push("remotevideo");
features.push('remotevideo');
}
features.push("displaylanguage");
features.push("otherapppromotions");
features.push("displaymode");
features.push("targetblank");
features.push("screensaver");
features.push('displaylanguage');
features.push('otherapppromotions');
features.push('displaymode');
features.push('targetblank');
features.push('screensaver');
webSettings.enableMultiServer().then(enabled => {
if (enabled) features.push("multiserver");
if (enabled) features.push('multiserver');
});
if (!browser.orsay && !browser.msie && (browser.firefox || browser.ps4 || browser.edge || supportsCue())) {
features.push("subtitleappearancesettings");
features.push('subtitleappearancesettings');
}
if (!browser.orsay) {
features.push("subtitleburnsettings");
features.push('subtitleburnsettings');
}
if (!browser.tv && !browser.ps4 && !browser.xboxOne) {
features.push("fileinput");
features.push('fileinput');
}
if (browser.chrome) {
features.push("chromecast");
features.push('chromecast');
}
return features;
@ -316,7 +301,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
window.close();
}
} catch (err) {
console.error("error closing application: " + err);
console.error('error closing application: ' + err);
}
}
@ -330,15 +315,15 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
return;
}
require(["actionsheet"], function (actionsheet) {
require(['actionsheet'], function (actionsheet) {
exitPromise = actionsheet.show({
title: Globalize.translate("MessageConfirmAppExit"),
title: globalize.translate('MessageConfirmAppExit'),
items: [
{id: "yes", name: Globalize.translate("Yes")},
{id: "no", name: Globalize.translate("No")}
{id: 'yes', name: globalize.translate('Yes')},
{id: 'no', name: globalize.translate('No')}
]
}).then(function (value) {
if (value === "yes") {
if (value === 'yes') {
doExit();
}
}).finally(function () {
@ -349,15 +334,15 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
var deviceId;
var deviceName;
var appName = "Jellyfin Web";
var appVersion = "10.5.0";
var appName = 'Jellyfin Web';
var appVersion = '10.6.0';
var appHost = {
getWindowState: function () {
return document.windowState || "Normal";
return document.windowState || 'Normal';
},
setWindowState: function (state) {
alert("setWindowState is not supported and should not be called");
alert('setWindowState is not supported and should not be called');
},
exit: function () {
if (!!window.appMode && browser.tizen) {
@ -374,7 +359,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
return -1 !== supportedFeatures.indexOf(command.toLowerCase());
},
preferVisualCards: browser.android || browser.chrome,
moreIcon: browser.android ? "more_vert" : "more_horiz",
moreIcon: browser.android ? 'more_vert' : 'more_horiz',
getSyncProfile: getSyncProfile,
getDefaultLayout: function () {
if (window.NativeShell) {
@ -410,16 +395,16 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
return {};
},
setThemeColor: function (color) {
var metaThemeColor = document.querySelector("meta[name=theme-color]");
var metaThemeColor = document.querySelector('meta[name=theme-color]');
if (metaThemeColor) {
metaThemeColor.setAttribute("content", color);
metaThemeColor.setAttribute('content', color);
}
},
setUserScalable: function (scalable) {
if (!browser.tv) {
var att = scalable ? "width=device-width, initial-scale=1, minimum-scale=1, user-scalable=yes" : "width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no";
document.querySelector("meta[name=viewport]").setAttribute("content", att);
var att = scalable ? 'width=device-width, initial-scale=1, minimum-scale=1, user-scalable=yes' : 'width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no';
document.querySelector('meta[name=viewport]').setAttribute('content', att);
}
}
};
@ -428,12 +413,12 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
var hidden;
var visibilityChange;
if (typeof document.hidden !== "undefined") { /* eslint-disable-line compat/compat */
hidden = "hidden";
visibilityChange = "visibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
if (typeof document.hidden !== 'undefined') { /* eslint-disable-line compat/compat */
hidden = 'hidden';
visibilityChange = 'visibilitychange';
} else if (typeof document.webkitHidden !== 'undefined') {
hidden = 'webkitHidden';
visibilityChange = 'webkitvisibilitychange';
}
document.addEventListener(visibilityChange, function () {
@ -446,8 +431,8 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
}, false);
if (self.addEventListener) {
self.addEventListener("focus", onAppVisible);
self.addEventListener("blur", onAppHidden);
self.addEventListener('focus', onAppVisible);
self.addEventListener('blur', onAppHidden);
}
return appHost;

View file

@ -5,8 +5,8 @@
* @module components/autoFocuser
*/
import focusManager from "focusManager";
import layoutManager from "layoutManager";
import focusManager from 'focusManager';
import layoutManager from 'layoutManager';
/**
* Previously selected element.
@ -28,11 +28,11 @@ import layoutManager from "layoutManager";
return;
}
window.addEventListener("focusin", function (e) {
window.addEventListener('focusin', function (e) {
activeElement = e.target;
});
console.debug("AutoFocuser enabled");
console.debug('AutoFocuser enabled');
}
/**
@ -51,21 +51,21 @@ import layoutManager from "layoutManager";
if (activeElement) {
// These elements are recreated
if (activeElement.classList.contains("btnPreviousPage")) {
candidates.push(container.querySelector(".btnPreviousPage"));
candidates.push(container.querySelector(".btnNextPage"));
} else if (activeElement.classList.contains("btnNextPage")) {
candidates.push(container.querySelector(".btnNextPage"));
candidates.push(container.querySelector(".btnPreviousPage"));
} else if (activeElement.classList.contains("btnSelectView")) {
candidates.push(container.querySelector(".btnSelectView"));
if (activeElement.classList.contains('btnPreviousPage')) {
candidates.push(container.querySelector('.btnPreviousPage'));
candidates.push(container.querySelector('.btnNextPage'));
} else if (activeElement.classList.contains('btnNextPage')) {
candidates.push(container.querySelector('.btnNextPage'));
candidates.push(container.querySelector('.btnPreviousPage'));
} else if (activeElement.classList.contains('btnSelectView')) {
candidates.push(container.querySelector('.btnSelectView'));
}
candidates.push(activeElement);
}
candidates = candidates.concat(Array.from(container.querySelectorAll(".btnResume")));
candidates = candidates.concat(Array.from(container.querySelectorAll(".btnPlay")));
candidates = candidates.concat(Array.from(container.querySelectorAll('.btnResume')));
candidates = candidates.concat(Array.from(container.querySelectorAll('.btnPlay')));
let focusedElement;
@ -81,7 +81,7 @@ import layoutManager from "layoutManager";
if (!focusedElement) {
// FIXME: Multiple itemsContainers
const itemsContainer = container.querySelector(".itemsContainer");
const itemsContainer = container.querySelector('.itemsContainer');
if (itemsContainer) {
focusedElement = focusManager.autoFocus(itemsContainer);

View file

@ -1,4 +1,4 @@
define(['browser', 'connectionManager', 'playbackManager', 'dom', "userSettings", 'css!./backdrop'], function (browser, connectionManager, playbackManager, dom, userSettings) {
define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings', 'css!./backdrop'], function (browser, connectionManager, playbackManager, dom, userSettings) {
'use strict';
function enableAnimation(elem) {
@ -180,7 +180,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', "userSettings"
if (item.BackdropImageTags && item.BackdropImageTags.length > 0) {
return item.BackdropImageTags.map(function (imgTag, index) {
return apiClient.getScaledImageUrl(item.BackdropItemId || item.Id, Object.assign(imageOptions, {
type: "Backdrop",
type: 'Backdrop',
tag: imgTag,
maxWidth: dom.getScreenWidth(),
index: index
@ -191,7 +191,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', "userSettings"
if (item.ParentBackdropItemId && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) {
return item.ParentBackdropImageTags.map(function (imgTag, index) {
return apiClient.getScaledImageUrl(item.ParentBackdropItemId, Object.assign(imageOptions, {
type: "Backdrop",
type: 'Backdrop',
tag: imgTag,
maxWidth: dom.getScreenWidth(),
index: index

View file

@ -1,12 +1,12 @@
define(["connectionManager"], function (connectionManager) {
define(['connectionManager'], function (connectionManager) {
return function () {
var self = this;
self.name = "Backdrop ScreenSaver";
self.type = "screensaver";
self.id = "backdropscreensaver";
self.name = 'Backdrop ScreenSaver';
self.type = 'screensaver';
self.id = 'backdropscreensaver';
self.supportsAnonymous = false;
var currentSlideshow;
@ -14,12 +14,12 @@ define(["connectionManager"], function (connectionManager) {
self.show = function () {
var query = {
ImageTypes: "Backdrop",
EnableImageTypes: "Backdrop",
IncludeItemTypes: "Movie,Series,MusicArtist",
SortBy: "Random",
ImageTypes: 'Backdrop',
EnableImageTypes: 'Backdrop',
IncludeItemTypes: 'Movie,Series,MusicArtist',
SortBy: 'Random',
Recursive: true,
Fields: "Taglines",
Fields: 'Taglines',
ImageTypeLimit: 1,
StartIndex: 0,
Limit: 200
@ -30,7 +30,7 @@ define(["connectionManager"], function (connectionManager) {
if (result.Items.length) {
require(["slideshow"], function (slideshow) {
require(['slideshow'], function (slideshow) {
var newSlideShow = new slideshow({
showTitle: true,

View file

@ -286,7 +286,7 @@ import 'programStyles';
* @param {Object} options - Options for handling the items.
*/
function setCardData(items, options) {
options.shape = options.shape || "auto";
options.shape = options.shape || 'auto';
const primaryImageAspectRatio = imageLoader.getPrimaryImageAspectRatio(items);
@ -509,7 +509,7 @@ import 'programStyles';
if (options.preferThumb && item.ImageTags && item.ImageTags.Thumb) {
imgUrl = apiClient.getScaledImageUrl(item.Id, {
type: "Thumb",
type: 'Thumb',
maxWidth: width,
tag: item.ImageTags.Thumb
});
@ -517,7 +517,7 @@ import 'programStyles';
} else if ((options.preferBanner || shape === 'banner') && item.ImageTags && item.ImageTags.Banner) {
imgUrl = apiClient.getScaledImageUrl(item.Id, {
type: "Banner",
type: 'Banner',
maxWidth: width,
tag: item.ImageTags.Banner
});
@ -525,7 +525,7 @@ import 'programStyles';
} else if (options.preferDisc && item.ImageTags && item.ImageTags.Disc) {
imgUrl = apiClient.getScaledImageUrl(item.Id, {
type: "Disc",
type: 'Disc',
maxWidth: width,
tag: item.ImageTags.Disc
});
@ -533,7 +533,7 @@ import 'programStyles';
} else if (options.preferLogo && item.ImageTags && item.ImageTags.Logo) {
imgUrl = apiClient.getScaledImageUrl(item.Id, {
type: "Logo",
type: 'Logo',
maxWidth: width,
tag: item.ImageTags.Logo
});
@ -541,7 +541,7 @@ import 'programStyles';
} else if (options.preferLogo && item.ParentLogoImageTag && item.ParentLogoItemId) {
imgUrl = apiClient.getScaledImageUrl(item.ParentLogoItemId, {
type: "Logo",
type: 'Logo',
maxWidth: width,
tag: item.ParentLogoImageTag
});
@ -549,7 +549,7 @@ import 'programStyles';
} else if (options.preferThumb && item.SeriesThumbImageTag && options.inheritThumb !== false) {
imgUrl = apiClient.getScaledImageUrl(item.SeriesId, {
type: "Thumb",
type: 'Thumb',
maxWidth: width,
tag: item.SeriesThumbImageTag
});
@ -557,7 +557,7 @@ import 'programStyles';
} else if (options.preferThumb && item.ParentThumbItemId && options.inheritThumb !== false && item.MediaType !== 'Photo') {
imgUrl = apiClient.getScaledImageUrl(item.ParentThumbItemId, {
type: "Thumb",
type: 'Thumb',
maxWidth: width,
tag: item.ParentThumbImageTag
});
@ -565,7 +565,7 @@ import 'programStyles';
} else if (options.preferThumb && item.BackdropImageTags && item.BackdropImageTags.length) {
imgUrl = apiClient.getScaledImageUrl(item.Id, {
type: "Backdrop",
type: 'Backdrop',
maxWidth: width,
tag: item.BackdropImageTags[0]
});
@ -575,7 +575,7 @@ import 'programStyles';
} else if (options.preferThumb && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length && options.inheritThumb !== false && item.Type === 'Episode') {
imgUrl = apiClient.getScaledImageUrl(item.ParentBackdropItemId, {
type: "Backdrop",
type: 'Backdrop',
maxWidth: width,
tag: item.ParentBackdropImageTags[0]
});
@ -585,7 +585,7 @@ import 'programStyles';
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
imgUrl = apiClient.getScaledImageUrl(item.Id, {
type: "Primary",
type: 'Primary',
maxHeight: height,
maxWidth: width,
tag: item.ImageTags.Primary
@ -607,7 +607,7 @@ import 'programStyles';
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
imgUrl = apiClient.getScaledImageUrl(item.PrimaryImageItemId || item.Id || item.ItemId, {
type: "Primary",
type: 'Primary',
maxHeight: height,
maxWidth: width,
tag: item.PrimaryImageTag
@ -626,14 +626,14 @@ import 'programStyles';
} else if (item.ParentPrimaryImageTag) {
imgUrl = apiClient.getScaledImageUrl(item.ParentPrimaryImageItemId, {
type: "Primary",
type: 'Primary',
maxWidth: width,
tag: item.ParentPrimaryImageTag
});
} else if (item.SeriesPrimaryImageTag) {
imgUrl = apiClient.getScaledImageUrl(item.SeriesId, {
type: "Primary",
type: 'Primary',
maxWidth: width,
tag: item.SeriesPrimaryImageTag
});
@ -642,7 +642,7 @@ import 'programStyles';
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
imgUrl = apiClient.getScaledImageUrl(item.AlbumId, {
type: "Primary",
type: 'Primary',
maxHeight: height,
maxWidth: width,
tag: item.AlbumPrimaryImageTag
@ -657,7 +657,7 @@ import 'programStyles';
} else if (item.Type === 'Season' && item.ImageTags && item.ImageTags.Thumb) {
imgUrl = apiClient.getScaledImageUrl(item.Id, {
type: "Thumb",
type: 'Thumb',
maxWidth: width,
tag: item.ImageTags.Thumb
});
@ -665,7 +665,7 @@ import 'programStyles';
} else if (item.BackdropImageTags && item.BackdropImageTags.length) {
imgUrl = apiClient.getScaledImageUrl(item.Id, {
type: "Backdrop",
type: 'Backdrop',
maxWidth: width,
tag: item.BackdropImageTags[0]
});
@ -673,7 +673,7 @@ import 'programStyles';
} else if (item.ImageTags && item.ImageTags.Thumb) {
imgUrl = apiClient.getScaledImageUrl(item.Id, {
type: "Thumb",
type: 'Thumb',
maxWidth: width,
tag: item.ImageTags.Thumb
});
@ -681,7 +681,7 @@ import 'programStyles';
} else if (item.SeriesThumbImageTag && options.inheritThumb !== false) {
imgUrl = apiClient.getScaledImageUrl(item.SeriesId, {
type: "Thumb",
type: 'Thumb',
maxWidth: width,
tag: item.SeriesThumbImageTag
});
@ -689,7 +689,7 @@ import 'programStyles';
} else if (item.ParentThumbItemId && options.inheritThumb !== false) {
imgUrl = apiClient.getScaledImageUrl(item.ParentThumbItemId, {
type: "Thumb",
type: 'Thumb',
maxWidth: width,
tag: item.ParentThumbImageTag
});
@ -697,7 +697,7 @@ import 'programStyles';
} else if (item.ParentBackdropImageTags && item.ParentBackdropImageTags.length && options.inheritThumb !== false) {
imgUrl = apiClient.getScaledImageUrl(item.ParentBackdropItemId, {
type: "Backdrop",
type: 'Backdrop',
maxWidth: width,
tag: item.ParentBackdropImageTags[0]
});
@ -778,7 +778,7 @@ import 'programStyles';
if (text) {
html += "<div class='" + currentCssClass + "'>";
html += text;
html += "</div>";
html += '</div>';
valid++;
if (maxLines && valid >= maxLines) {
@ -835,7 +835,7 @@ import 'programStyles';
airTimeText += ' - ' + datetime.getDisplayTime(date);
}
} catch (e) {
console.error("error parsing date: " + item.StartDate);
console.error('error parsing date: ' + item.StartDate);
}
}
@ -869,11 +869,11 @@ import 'programStyles';
if (isOuterFooter && options.cardLayout && layoutManager.mobile) {
if (options.cardFooterAside !== 'none') {
html += '<button is="paper-icon-button-light" class="itemAction btnCardOptions cardText-secondary" data-action="menu"><i class="material-icons more_horiz"></i></button>';
html += '<button is="paper-icon-button-light" class="itemAction btnCardOptions cardText-secondary" data-action="menu"><span class="material-icons more_horiz"></span></button>';
}
}
const cssClass = options.centerText ? "cardText cardTextCentered" : "cardText";
const cssClass = options.centerText ? 'cardText cardTextCentered' : 'cardText';
const serverId = item.ServerId || options.serverId;
let lines = [];
@ -907,7 +907,7 @@ import 'programStyles';
}
} else {
const parentTitle = item.SeriesName || item.Series || item.Album || item.AlbumArtist || "";
const parentTitle = item.SeriesName || item.Series || item.Album || item.AlbumArtist || '';
if (parentTitle || showTitle) {
lines.push(parentTitle);
@ -946,7 +946,7 @@ import 'programStyles';
item.AlbumArtists[0].IsFolder = true;
lines.push(getTextActionButton(item.AlbumArtists[0], null, serverId));
} else {
lines.push(isUsingLiveTvNaming(item) ? item.Name : (item.SeriesName || item.Series || item.Album || item.AlbumArtist || ""));
lines.push(isUsingLiveTvNaming(item) ? item.Name : (item.SeriesName || item.Series || item.Album || item.AlbumArtist || ''));
}
}
@ -993,7 +993,7 @@ import 'programStyles';
if (options.showYear || options.showSeriesYear) {
if (item.Type === 'Series') {
if (item.Status === "Continuing") {
if (item.Status === 'Continuing') {
lines.push(globalize.translate('SeriesYearToPresent', item.ProductionYear || ''));
@ -1105,7 +1105,7 @@ import 'programStyles';
html = '<div class="' + footerClass + '">' + html;
//cardFooter
html += "</div>";
html += '</div>';
}
}
@ -1191,7 +1191,7 @@ import 'programStyles';
counts.push(childText);
}
} else if (item.Type === 'MusicGenre' || options.context === "MusicArtist") {
} else if (item.Type === 'MusicGenre' || options.context === 'MusicArtist') {
if (item.AlbumCount) {
@ -1304,7 +1304,7 @@ import 'programStyles';
}
if (options.cardClass) {
className += " " + options.cardClass;
className += ' ' + options.cardClass;
}
if (layoutManager.desktop) {
@ -1356,13 +1356,13 @@ import 'programStyles';
if (options.showChannelLogo && item.ChannelPrimaryImageTag) {
logoUrl = apiClient.getScaledImageUrl(item.ChannelId, {
type: "Primary",
type: 'Primary',
height: logoHeight,
tag: item.ChannelPrimaryImageTag
});
} else if (options.showLogo && item.ParentLogoImageTag) {
logoUrl = apiClient.getScaledImageUrl(item.ParentLogoItemId, {
type: "Logo",
type: 'Logo',
height: logoHeight,
tag: item.ParentLogoImageTag
});
@ -1418,15 +1418,15 @@ import 'programStyles';
const btnCssClass = 'cardOverlayButton cardOverlayButton-br itemAction';
if (options.centerPlayButton) {
overlayButtons += '<button is="paper-icon-button-light" class="' + btnCssClass + ' cardOverlayButton-centered" data-action="play"><i class="material-icons cardOverlayButtonIcon play_arrow"></i></button>';
overlayButtons += '<button is="paper-icon-button-light" class="' + btnCssClass + ' cardOverlayButton-centered" data-action="play"><span class="material-icons cardOverlayButtonIcon play_arrow"></span></button>';
}
if (overlayPlayButton && !item.IsPlaceHolder && (item.LocationType !== 'Virtual' || !item.MediaType || item.Type === 'Program') && item.Type !== 'Person') {
overlayButtons += '<button is="paper-icon-button-light" class="' + btnCssClass + '" data-action="play"><i class="material-icons cardOverlayButtonIcon play_arrow"></i></button>';
overlayButtons += '<button is="paper-icon-button-light" class="' + btnCssClass + '" data-action="play"><span class="material-icons cardOverlayButtonIcon play_arrow"></span></button>';
}
if (options.overlayMoreButton) {
overlayButtons += '<button is="paper-icon-button-light" class="' + btnCssClass + '" data-action="menu"><i class="material-icons cardOverlayButtonIcon more_horiz"></i></button>';
overlayButtons += '<button is="paper-icon-button-light" class="' + btnCssClass + '" data-action="menu"><span class="material-icons cardOverlayButtonIcon more_horiz"></span></button>';
}
}
@ -1518,7 +1518,7 @@ import 'programStyles';
let actionAttribute;
if (tagName === 'button') {
className += " itemAction";
className += ' itemAction';
actionAttribute = ' data-action="' + action + '"';
} else {
actionAttribute = '';
@ -1560,7 +1560,7 @@ import 'programStyles';
const btnCssClass = 'cardOverlayButton cardOverlayButton-hover itemAction paper-icon-button-light';
if (playbackManager.canPlay(item)) {
html += '<button is="paper-icon-button-light" class="' + btnCssClass + ' cardOverlayFab-primary" data-action="resume"><i class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover play_arrow"></i></button>';
html += '<button is="paper-icon-button-light" class="' + btnCssClass + ' cardOverlayFab-primary" data-action="resume"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover play_arrow"></span></button>';
}
html += '<div class="cardOverlayButton-br flex">';
@ -1569,7 +1569,7 @@ import 'programStyles';
if (itemHelper.canMarkPlayed(item)) {
require(['emby-playstatebutton']);
html += '<button is="emby-playstatebutton" type="button" data-action="none" class="' + btnCssClass + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-played="' + (userData.Played) + '"><i class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover">check</i></button>';
html += '<button is="emby-playstatebutton" type="button" data-action="none" class="' + btnCssClass + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-played="' + (userData.Played) + '"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover check"></span></button>';
}
if (itemHelper.canRate(item)) {
@ -1577,10 +1577,10 @@ import 'programStyles';
const likes = userData.Likes == null ? '' : userData.Likes;
require(['emby-ratingbutton']);
html += '<button is="emby-ratingbutton" type="button" data-action="none" class="' + btnCssClass + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-likes="' + likes + '" data-isfavorite="' + (userData.IsFavorite) + '"><i class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover">favorite</i></button>';
html += '<button is="emby-ratingbutton" type="button" data-action="none" class="' + btnCssClass + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-likes="' + likes + '" data-isfavorite="' + (userData.IsFavorite) + '"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover favorite"></span></button>';
}
html += '<button is="paper-icon-button-light" class="' + btnCssClass + '" data-action="menu"><i class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover more_horiz"></i></button>';
html += '<button is="paper-icon-button-light" class="' + btnCssClass + '" data-action="menu"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover more_horiz"></span></button>';
html += '</div>';
html += '</div>';
@ -1596,27 +1596,27 @@ import 'programStyles';
*/
export function getDefaultText(item, options) {
if (item.CollectionType) {
return '<i class="cardImageIcon material-icons ' + imageHelper.getLibraryIcon(item.CollectionType) + '"></i>';
return '<span class="cardImageIcon material-icons ' + imageHelper.getLibraryIcon(item.CollectionType) + '"></span>';
}
switch (item.Type) {
case 'MusicAlbum':
return '<i class="cardImageIcon material-icons">album</i>';
return '<span class="cardImageIcon material-icons album"></span>';
case 'MusicArtist':
case 'Person':
return '<i class="cardImageIcon material-icons">person</i>';
return '<span class="cardImageIcon material-icons person"></span>';
case 'Movie':
return '<i class="cardImageIcon material-icons">movie</i>';
return '<span class="cardImageIcon material-icons movie"></span>';
case 'Series':
return '<i class="cardImageIcon material-icons">tv</i>';
return '<span class="cardImageIcon material-icons tv"></span>';
case 'Book':
return '<i class="cardImageIcon material-icons">book</i>';
return '<span class="cardImageIcon material-icons book"></span>';
case 'Folder':
return '<i class="cardImageIcon material-icons">folder</i>';
return '<span class="cardImageIcon material-icons folder"></span>';
}
if (options && options.defaultCardImageIcon) {
return '<i class="cardImageIcon material-icons">' + options.defaultCardImageIcon + '</i>';
return '<span class="cardImageIcon material-icons ' + options.defaultCardImageIcon + '"></span>';
}
const defaultName = isUsingLiveTvNaming(item) ? item.Name : itemHelper.getDisplayName(item);
@ -1718,7 +1718,7 @@ import 'programStyles';
indicatorsElem = ensureIndicators(card, indicatorsElem);
indicatorsElem.appendChild(playedIndicator);
}
playedIndicator.innerHTML = '<i class="material-icons indicatorIcon">check</i>';
playedIndicator.innerHTML = '<span class="material-icons indicatorIcon check"></span>';
} else {
playedIndicator = card.querySelector('.playedIndicator');
@ -1808,7 +1808,7 @@ import 'programStyles';
const icon = cell.querySelector('.timerIndicator');
if (!icon) {
const indicatorsElem = ensureIndicators(cell);
indicatorsElem.insertAdjacentHTML('beforeend', '<i class="material-icons timerIndicator indicatorIcon fiber_manual_record"></i>');
indicatorsElem.insertAdjacentHTML('beforeend', '<span class="material-icons timerIndicator indicatorIcon fiber_manual_record"></span>');
}
cell.setAttribute('data-timerid', newTimerId);
}

View file

@ -70,7 +70,7 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browse
maxWidth: maxWidth * 2,
tag: chapter.ImageTag,
type: "Chapter",
type: 'Chapter',
index: index
});
}
@ -90,7 +90,7 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browse
var cardImageContainer = imgUrl ? ('<div class="' + cardImageContainerClass + ' lazy" data-src="' + imgUrl + '">') : ('<div class="' + cardImageContainerClass + '">');
if (!imgUrl) {
cardImageContainer += '<i class="material-icons cardImageIcon local_movies"></i>';
cardImageContainer += '<span class="material-icons cardImageIcon local_movies"></span>';
}
var nameHtml = '';

View file

@ -1,7 +1,7 @@
define([], function() {
'use strict';
if (window.appMode === "cordova" || window.appMode === "android") {
if (window.appMode === 'cordova' || window.appMode === 'android') {
return {
load: function () {
window.chrome = window.chrome || {};
@ -17,16 +17,16 @@ define([], function() {
}
return new Promise(function (resolve, reject) {
var fileref = document.createElement("script");
fileref.setAttribute("type", "text/javascript");
var fileref = document.createElement('script');
fileref.setAttribute('type', 'text/javascript');
fileref.onload = function () {
ccLoaded = true;
resolve();
};
fileref.setAttribute("src", "https://www.gstatic.com/cv/js/sender/v1/cast_sender.js");
document.querySelector("head").appendChild(fileref);
fileref.setAttribute('src', 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js');
document.querySelector('head').appendChild(fileref);
});
}
};

View file

@ -1,33 +1,33 @@
define(["dom", "dialogHelper", "loading", "connectionManager", "globalize", "actionsheet", "emby-input", "paper-icon-button-light", "emby-button", "listViewStyle", "material-icons", "formDialogStyle"], function (dom, dialogHelper, loading, connectionManager, globalize, actionsheet) {
"use strict";
define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'actionsheet', 'emby-input', 'paper-icon-button-light', 'emby-button', 'listViewStyle', 'material-icons', 'formDialogStyle'], function (dom, dialogHelper, loading, connectionManager, globalize, actionsheet) {
'use strict';
return function (options) {
function mapChannel(button, channelId, providerChannelId) {
loading.show();
var providerId = options.providerId;
connectionManager.getApiClient(options.serverId).ajax({
type: "POST",
url: ApiClient.getUrl("LiveTv/ChannelMappings"),
type: 'POST',
url: ApiClient.getUrl('LiveTv/ChannelMappings'),
data: {
providerId: providerId,
tunerChannelId: channelId,
providerChannelId: providerChannelId
},
dataType: "json"
dataType: 'json'
}).then(function (mapping) {
var listItem = dom.parentWithClass(button, "listItem");
button.setAttribute("data-providerid", mapping.ProviderChannelId);
listItem.querySelector(".secondary").innerHTML = getMappingSecondaryName(mapping, currentMappingOptions.ProviderName);
var listItem = dom.parentWithClass(button, 'listItem');
button.setAttribute('data-providerid', mapping.ProviderChannelId);
listItem.querySelector('.secondary').innerHTML = getMappingSecondaryName(mapping, currentMappingOptions.ProviderName);
loading.hide();
});
}
function onChannelsElementClick(e) {
var btnMap = dom.parentWithClass(e.target, "btnMap");
var btnMap = dom.parentWithClass(e.target, 'btnMap');
if (btnMap) {
var channelId = btnMap.getAttribute("data-id");
var providerChannelId = btnMap.getAttribute("data-providerid");
var channelId = btnMap.getAttribute('data-id');
var providerChannelId = btnMap.getAttribute('data-providerid');
var menuItems = currentMappingOptions.ProviderChannels.map(function (m) {
return {
name: m.Name,
@ -48,56 +48,56 @@ define(["dom", "dialogHelper", "loading", "connectionManager", "globalize", "act
function getChannelMappingOptions(serverId, providerId) {
var apiClient = connectionManager.getApiClient(serverId);
return apiClient.getJSON(apiClient.getUrl("LiveTv/ChannelMappingOptions", {
return apiClient.getJSON(apiClient.getUrl('LiveTv/ChannelMappingOptions', {
providerId: providerId
}));
}
function getMappingSecondaryName(mapping, providerName) {
return (mapping.ProviderChannelName || "") + " - " + providerName;
return (mapping.ProviderChannelName || '') + ' - ' + providerName;
}
function getTunerChannelHtml(channel, providerName) {
var html = "";
var html = '';
html += '<div class="listItem">';
html += '<i class="material-icons listItemIcon">dvr</i>';
html += '<span class="material-icons listItemIcon dvr"></span>';
html += '<div class="listItemBody two-line">';
html += '<h3 class="listItemBodyText">';
html += channel.Name;
html += "</h3>";
html += '</h3>';
html += '<div class="secondary listItemBodyText">';
if (channel.ProviderChannelName) {
html += getMappingSecondaryName(channel, providerName);
}
html += "</div>";
html += "</div>";
html += '<button class="btnMap autoSize" is="paper-icon-button-light" type="button" data-id="' + channel.Id + '" data-providerid="' + channel.ProviderChannelId + '"><i class="material-icons mode_edit"></i></button>';
return html += "</div>";
html += '</div>';
html += '</div>';
html += '<button class="btnMap autoSize" is="paper-icon-button-light" type="button" data-id="' + channel.Id + '" data-providerid="' + channel.ProviderChannelId + '"><span class="material-icons mode_edit"></span></button>';
return html += '</div>';
}
function getEditorHtml() {
var html = "";
var html = '';
html += '<div class="formDialogContent">';
html += '<div class="dialogContentInner dialog-content-centered">';
html += '<form style="margin:auto;">';
html += "<h1>" + globalize.translate("HeaderChannels") + "</h1>";
html += '<h1>' + globalize.translate('HeaderChannels') + '</h1>';
html += '<div class="channels paperList">';
html += "</div>";
html += "</form>";
html += "</div>";
return html += "</div>";
html += '</div>';
html += '</form>';
html += '</div>';
return html += '</div>';
}
function initEditor(dlg, options) {
getChannelMappingOptions(options.serverId, options.providerId).then(function (result) {
currentMappingOptions = result;
var channelsElement = dlg.querySelector(".channels");
var channelsElement = dlg.querySelector('.channels');
channelsElement.innerHTML = result.TunerChannels.map(function (channel) {
return getTunerChannelHtml(channel, result.ProviderName);
}).join("");
channelsElement.addEventListener("click", onChannelsElementClick);
}).join('');
channelsElement.addEventListener('click', onChannelsElementClick);
});
}
@ -108,27 +108,27 @@ define(["dom", "dialogHelper", "loading", "connectionManager", "globalize", "act
var dialogOptions = {
removeOnClose: true
};
dialogOptions.size = "small";
dialogOptions.size = 'small';
var dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add("formDialog");
dlg.classList.add("ui-body-a");
dlg.classList.add("background-theme-a");
var html = "";
var title = globalize.translate("MapChannels");
dlg.classList.add('formDialog');
dlg.classList.add('ui-body-a');
dlg.classList.add('background-theme-a');
var html = '';
var title = globalize.translate('MapChannels');
html += '<div class="formDialogHeader">';
html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><i class="material-icons arrow_back"></i></button>';
html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
html += '<h3 class="formDialogHeaderTitle">';
html += title;
html += "</h3>";
html += "</div>";
html += '</h3>';
html += '</div>';
html += getEditorHtml();
dlg.innerHTML = html;
initEditor(dlg, options);
dlg.querySelector(".btnCancel").addEventListener("click", function () {
dlg.querySelector('.btnCancel').addEventListener('click', function () {
dialogHelper.close(dlg);
});
return new Promise(function (resolve, reject) {
dlg.addEventListener("close", resolve);
dlg.addEventListener('close', resolve);
dialogHelper.open(dlg);
});
};

View file

@ -37,69 +37,69 @@ define(['events'], function (events) {
// 5) It wasn't as smart as it could have been about what should be part of a
// URL and what should be part of human language.
var protocols = "(?:(?:http|https|rtsp|ftp):\\/\\/)";
var protocols = '(?:(?:http|https|rtsp|ftp):\\/\\/)';
var credentials = "(?:(?:[a-z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-f0-9]{2})){1,64}" // username (1-64 normal or url escaped characters)
+ "(?:\\:(?:[a-z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-f0-9]{2})){1,25})?" // followed by optional password (: + 1-25 normal or url escaped characters)
+ "\\@)";
+ '\\@)';
// IPv6 Regex http://forums.intermapper.com/viewtopic.php?t=452
// by Dartware, LLC is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License
// http://intermapper.com/
var ipv6 = "("
+ "(([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))"
+ "|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))"
+ "|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))"
+ "|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
+ "|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
+ "|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
+ "|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
+ "|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
+ ")(%.+)?";
var ipv6 = '('
+ '(([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))'
+ '|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))'
+ '|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))'
+ '|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))'
+ '|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))'
+ '|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))'
+ '|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))'
+ '|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))'
+ ')(%.+)?';
var ipv4 = "(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\."
+ "(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\."
+ "(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\."
+ "(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])";
var ipv4 = '(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.'
+ '(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.'
+ '(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.'
+ '(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])';
// This would have been a lot cleaner if JS RegExp supported conditionals...
var linkRegExpString =
// begin match for protocol / username / password / host
"(?:"
'(?:'
// ============================
// If we have a recognized protocol at the beginning of the URL, we're
// more relaxed about what we accept, because we assume the user wants
// this to be a URL, and we're not accidentally matching human language
+ protocols + "?"
+ protocols + '?'
// optional username:password@
+ credentials + "?"
+ credentials + '?'
// IP address (both v4 and v6)
+ "(?:"
+ '(?:'
// IPv6
+ ipv6
// IPv4
+ "|" + ipv4
+ '|' + ipv4
+ ")"
+ ')'
// end match for protocol / username / password / host
+ ")"
+ ')'
// optional port number
+ "(?:\\:\\d{1,5})?"
+ '(?:\\:\\d{1,5})?'
// plus optional path and query params (no unicode allowed here?)
+ "(?:"
+ "\\/(?:"
+ '(?:'
+ '\\/(?:'
// some characters we'll accept because it's unlikely human language
// would use them after a URL unless they were part of the url
+ "(?:[a-z0-9\\/\\@\\&\\#\\~\\*\\_\\-\\+])"
+ "|(?:\\%[a-f0-9]{2})"
+ '(?:[a-z0-9\\/\\@\\&\\#\\~\\*\\_\\-\\+])'
+ '|(?:\\%[a-f0-9]{2})'
// some characters are much more likely to be used AFTER a url and
// were not intended to be included in the url itself. Mostly end
// of sentence type things. It's also likely that the URL would
@ -108,9 +108,9 @@ define(['events'], function (events) {
// they must be followed by another character that we're reasonably
// sure is part of the url
+ "|(?:[\\;\\?\\:\\.\\!\\'\\(\\)\\,\\=]+(?=(?:[a-z0-9\\/\\@\\&\\#\\~\\*\\_\\-\\+])|(?:\\%[a-f0-9]{2})))"
+ ")*"
+ "|\\b|\$"
+ ")";
+ ')*'
+ '|\\b|\$'
+ ')';
// regex = XRegExp(regex,'gi');
var linkRegExp = RegExp(linkRegExpString, 'gi');
@ -120,7 +120,7 @@ define(['events'], function (events) {
// if url doesn't begin with a known protocol, add http by default
function ensureProtocol(url) {
if (!url.match(protocolRegExp)) {
url = "http://" + url;
url = 'http://' + url;
}
return url;
}
@ -190,7 +190,7 @@ define(['events'], function (events) {
return apiClient.getPublicSystemInfo().then(function (info) {
var localAddress = info.LocalAddress;
if (!localAddress) {
console.debug("No valid local address returned, defaulting to external one");
console.debug('No valid local address returned, defaulting to external one');
localAddress = serverAddress;
}
addToCache(serverAddress, localAddress);

View file

@ -5,7 +5,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
var currentResolve;
var currentReject;
var PlayerName = 'Chromecast';
var PlayerName = 'Google Cast';
function sendConnectionResult(isOk) {
@ -54,7 +54,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
// production version registered with google
// replace this value if you want to test changes on another instance
var applicationID = "F007D354";
var applicationID = 'F007D354';
var messageNamespace = 'urn:x-cast:com.connectsdk';
@ -114,14 +114,14 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
*/
CastPlayer.prototype.onInitSuccess = function () {
this.isInitialized = true;
console.debug("chromecast init success");
console.debug('chromecast init success');
};
/**
* Generic error callback function
*/
CastPlayer.prototype.onError = function () {
console.debug("chromecast error");
console.debug('chromecast error');
};
/**
@ -177,10 +177,10 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
*/
CastPlayer.prototype.receiverListener = function (e) {
if (e === 'available') {
console.debug("chromecast receiver found");
console.debug('chromecast receiver found');
this.hasReceivers = true;
} else {
console.debug("chromecast receiver list empty");
console.debug('chromecast receiver list empty');
this.hasReceivers = false;
}
};
@ -195,8 +195,8 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
this.session = null;
this.deviceState = DEVICE_STATE.IDLE;
this.castPlayerState = PLAYER_STATE.IDLE;
document.removeEventListener("volumeupbutton", onVolumeUpKeyDown, false);
document.removeEventListener("volumedownbutton", onVolumeDownKeyDown, false);
document.removeEventListener('volumeupbutton', onVolumeUpKeyDown, false);
document.removeEventListener('volumedownbutton', onVolumeDownKeyDown, false);
console.debug('sessionUpdateListener: setting currentMediaSession to null');
this.currentMediaSession = null;
@ -211,7 +211,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
* session request in opt_sessionRequest.
*/
CastPlayer.prototype.launchApp = function () {
console.debug("chromecast launching app...");
console.debug('chromecast launching app...');
chrome.cast.requestSession(this.onRequestSessionSuccess.bind(this), this.onLaunchError.bind(this));
};
@ -220,7 +220,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
* @param {Object} e A chrome.cast.Session object
*/
CastPlayer.prototype.onRequestSessionSuccess = function (e) {
console.debug("chromecast session success: " + e.sessionId);
console.debug('chromecast session success: ' + e.sessionId);
this.onSessionConnected(e);
};
@ -232,8 +232,8 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
this.session.addMediaListener(this.sessionMediaListener.bind(this));
this.session.addUpdateListener(this.sessionUpdateListener.bind(this));
document.addEventListener("volumeupbutton", onVolumeUpKeyDown, false);
document.addEventListener("volumedownbutton", onVolumeDownKeyDown, false);
document.addEventListener('volumeupbutton', onVolumeUpKeyDown, false);
document.addEventListener('volumedownbutton', onVolumeDownKeyDown, false);
events.trigger(this, 'connect');
this.sendMessage({
@ -262,7 +262,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
* Callback function for launch error
*/
CastPlayer.prototype.onLaunchError = function () {
console.debug("chromecast launch error");
console.debug('chromecast launch error');
this.deviceState = DEVICE_STATE.ERROR;
sendConnectionResult(false);
};
@ -284,8 +284,8 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
this.deviceState = DEVICE_STATE.IDLE;
this.castPlayerState = PLAYER_STATE.IDLE;
document.removeEventListener("volumeupbutton", onVolumeUpKeyDown, false);
document.removeEventListener("volumedownbutton", onVolumeDownKeyDown, false);
document.removeEventListener('volumeupbutton', onVolumeUpKeyDown, false);
document.removeEventListener('volumedownbutton', onVolumeDownKeyDown, false);
this.currentMediaSession = null;
};
@ -296,7 +296,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
*/
CastPlayer.prototype.loadMedia = function (options, command) {
if (!this.session) {
console.debug("no session");
console.debug('no session');
return Promise.reject();
}
@ -386,7 +386,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
*/
CastPlayer.prototype.onMediaDiscovered = function (how, mediaSession) {
console.debug("chromecast new media session ID:" + mediaSession.mediaSessionId + ' (' + how + ')');
console.debug('chromecast new media session ID:' + mediaSession.mediaSessionId + ' (' + how + ')');
this.currentMediaSession = mediaSession;
if (how === 'loadMedia') {
@ -405,7 +405,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
* @param {!Boolean} e true/false
*/
CastPlayer.prototype.onMediaStatusUpdate = function (e) {
console.debug("chromecast updating media: " + e);
console.debug('chromecast updating media: ' + e);
if (e === false) {
this.castPlayerState = PLAYER_STATE.IDLE;
}
@ -482,7 +482,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
} else {
query.Limit = query.Limit || 100;
query.ExcludeLocationTypes = "Virtual";
query.ExcludeLocationTypes = 'Virtual';
query.EnableTotalRecordCount = false;
return apiClient.getItems(userId, query);
@ -506,13 +506,13 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
instance._castPlayer = new CastPlayer();
// To allow the native android app to override
document.dispatchEvent(new CustomEvent("chromecastloaded", {
document.dispatchEvent(new CustomEvent('chromecastloaded', {
detail: {
player: instance
}
}));
events.on(instance._castPlayer, "connect", function (e) {
events.on(instance._castPlayer, 'connect', function (e) {
if (currentResolve) {
sendConnectionResult(true);
@ -525,22 +525,22 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
instance.lastPlayerData = null;
});
events.on(instance._castPlayer, "playbackstart", function (e, data) {
events.on(instance._castPlayer, 'playbackstart', function (e, data) {
console.debug('cc: playbackstart');
instance._castPlayer.initializeCastPlayer();
var state = instance.getPlayerStateInternal(data);
events.trigger(instance, "playbackstart", [state]);
events.trigger(instance, 'playbackstart', [state]);
});
events.on(instance._castPlayer, "playbackstop", function (e, data) {
events.on(instance._castPlayer, 'playbackstop', function (e, data) {
console.debug('cc: playbackstop');
var state = instance.getPlayerStateInternal(data);
events.trigger(instance, "playbackstop", [state]);
events.trigger(instance, 'playbackstop', [state]);
var state = instance.lastPlayerData.PlayState || {};
var volume = state.VolumeLevel || 0.5;
@ -553,12 +553,12 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
instance.lastPlayerData.PlayState.IsMuted = mute;
});
events.on(instance._castPlayer, "playbackprogress", function (e, data) {
events.on(instance._castPlayer, 'playbackprogress', function (e, data) {
console.debug('cc: positionchange');
var state = instance.getPlayerStateInternal(data);
events.trigger(instance, "timeupdate", [state]);
events.trigger(instance, 'timeupdate', [state]);
});
bindEventForRelay(instance, 'timeupdate');
@ -567,12 +567,12 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
bindEventForRelay(instance, 'volumechange');
bindEventForRelay(instance, 'repeatmodechange');
events.on(instance._castPlayer, "playstatechange", function (e, data) {
events.on(instance._castPlayer, 'playstatechange', function (e, data) {
console.debug('cc: playstatechange');
var state = instance.getPlayerStateInternal(data);
events.trigger(instance, "pause", [state]);
events.trigger(instance, 'pause', [state]);
});
}
@ -630,24 +630,24 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
name: PlayerName,
id: PlayerName,
playerName: PlayerName,
playableMediaTypes: ["Audio", "Video"],
playableMediaTypes: ['Audio', 'Video'],
isLocalPlayer: false,
appName: PlayerName,
deviceName: appName,
supportedCommands: [
"VolumeUp",
"VolumeDown",
"Mute",
"Unmute",
"ToggleMute",
"SetVolume",
"SetAudioStreamIndex",
"SetSubtitleStreamIndex",
"DisplayContent",
"SetRepeatMode",
"EndSession",
"PlayMediaSource",
"PlayTrailers"
'VolumeUp',
'VolumeDown',
'Mute',
'Unmute',
'ToggleMute',
'SetVolume',
'SetAudioStreamIndex',
'SetSubtitleStreamIndex',
'DisplayContent',
'SetRepeatMode',
'EndSession',
'PlayMediaSource',
'PlayTrailers'
]
};
};
@ -667,7 +667,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
console.debug(JSON.stringify(data));
if (triggerStateChange) {
events.trigger(this, "statechange", [data]);
events.trigger(this, 'statechange', [data]);
}
return data;

View file

@ -24,7 +24,7 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
function createCollection(apiClient, dlg) {
var url = apiClient.getUrl("Collections", {
var url = apiClient.getUrl('Collections', {
Name: dlg.querySelector('#txtNewCollectionName').value,
IsLocked: !dlg.querySelector('#chkEnableInternetMetadata').checked,
@ -32,9 +32,9 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
});
apiClient.ajax({
type: "POST",
type: 'POST',
url: url,
dataType: "json"
dataType: 'json'
}).then(function (result) {
@ -56,13 +56,13 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
function addToCollection(apiClient, dlg, id) {
var url = apiClient.getUrl("Collections/" + id + "/Items", {
var url = apiClient.getUrl('Collections/' + id + '/Items', {
Ids: dlg.querySelector('.fldSelectedItemIds').value || ''
});
apiClient.ajax({
type: "POST",
type: 'POST',
url: url
}).then(function () {
@ -93,8 +93,8 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
var options = {
Recursive: true,
IncludeItemTypes: "BoxSet",
SortBy: "SortName",
IncludeItemTypes: 'BoxSet',
SortBy: 'SortName',
EnableTotalRecordCount: false
};
@ -230,13 +230,13 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
var title = items.length ? globalize.translate('HeaderAddToCollection') : globalize.translate('NewCollection');
html += '<div class="formDialogHeader">';
html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><i class="material-icons arrow_back"></i></button>';
html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
html += '<h3 class="formDialogHeaderTitle">';
html += title;
html += '</h3>';
if (appHost.supports('externallinks')) {
html += '<a is="emby-linkbutton" class="button-link btnHelp flex align-items-center" href="https://web.archive.org/web/20181216120305/https://github.com/MediaBrowser/Wiki/wiki/Collections" target="_blank" style="margin-left:auto;margin-right:.5em;padding:.25em;" title="' + globalize.translate('Help') + '"><i class="material-icons">info</i><span style="margin-left:.25em;">' + globalize.translate('Help') + '</span></a>';
html += '<a is="emby-linkbutton" class="button-link btnHelp flex align-items-center" href="https://web.archive.org/web/20181216120305/https://github.com/MediaBrowser/Wiki/wiki/Collections" target="_blank" style="margin-left:auto;margin-right:.5em;padding:.25em;" title="' + globalize.translate('Help') + '"><span class="material-icons info"></span><span style="margin-left:.25em;">' + globalize.translate('Help') + '</span></a>';
}
html += '</div>';

View file

@ -1,4 +1,4 @@
define(["browser", "dialog", "globalize"], function(browser, dialog, globalize) {
define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize) {
'use strict';
function replaceAll(str, find, replace) {

View file

@ -141,7 +141,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
animateDialogOpen(dlg);
if (isHistoryEnabled(dlg)) {
appRouter.pushState({ dialogId: hash }, "Dialog", '#' + hash);
appRouter.pushState({ dialogId: hash }, 'Dialog', '#' + hash);
window.addEventListener('popstate', onHashChange);
} else {

View file

@ -1,4 +1,4 @@
define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-icon-button-light', 'css!./directorybrowser', 'formDialogStyle', 'emby-button'], function(loading, dialogHelper, dom) {
define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-input', 'paper-icon-button-light', 'css!./directorybrowser', 'formDialogStyle', 'emby-button'], function(loading, dialogHelper, dom, globalize) {
'use strict';
function getSystemInfo() {
@ -16,14 +16,14 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
function refreshDirectoryBrowser(page, path, fileOptions, updatePathOnError) {
if (path && typeof path !== 'string') {
throw new Error("invalid path");
throw new Error('invalid path');
}
loading.show();
var promises = [];
if ("Network" === path) {
if ('Network' === path) {
promises.push(ApiClient.getNetworkDevices());
} else {
if (path) {
@ -37,31 +37,31 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
Promise.all(promises).then(
function(responses) {
var folders = responses[0];
var parentPath = responses[1] || "";
var html = "";
var parentPath = responses[1] || '';
var html = '';
page.querySelector(".results").scrollTop = 0;
page.querySelector("#txtDirectoryPickerPath").value = path || "";
page.querySelector('.results').scrollTop = 0;
page.querySelector('#txtDirectoryPickerPath').value = path || '';
if (path) {
html += getItem("lnkPath lnkDirectory", "", parentPath, "...");
html += getItem('lnkPath lnkDirectory', '', parentPath, '...');
}
for (var i = 0, length = folders.length; i < length; i++) {
var folder = folders[i];
var cssClass = "File" === folder.Type ? "lnkPath lnkFile" : "lnkPath lnkDirectory";
var cssClass = 'File' === folder.Type ? 'lnkPath lnkFile' : 'lnkPath lnkDirectory';
html += getItem(cssClass, folder.Type, folder.Path, folder.Name);
}
if (!path) {
html += getItem("lnkPath lnkDirectory", "", "Network", Globalize.translate("ButtonNetwork"));
html += getItem('lnkPath lnkDirectory', '', 'Network', globalize.translate('ButtonNetwork'));
}
page.querySelector(".results").innerHTML = html;
page.querySelector('.results').innerHTML = html;
loading.hide();
}, function() {
if (updatePathOnError) {
page.querySelector("#txtDirectoryPickerPath").value = "";
page.querySelector(".results").innerHTML = "";
page.querySelector('#txtDirectoryPickerPath').value = '';
page.querySelector('.results').innerHTML = '';
loading.hide();
}
}
@ -69,74 +69,74 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
}
function getItem(cssClass, type, path, name) {
var html = "";
var html = '';
html += '<div class="listItem listItem-border ' + cssClass + '" data-type="' + type + '" data-path="' + path + '">';
html += '<div class="listItemBody" style="padding-left:0;padding-top:.5em;padding-bottom:.5em;">';
html += '<div class="listItemBodyText">';
html += name;
html += "</div>";
html += "</div>";
html += '<i class="material-icons arrow_forward" style="font-size:inherit;"></i>';
html += "</div>";
html += '</div>';
html += '</div>';
html += '<span class="material-icons arrow_forward" style="font-size:inherit;"></span>';
html += '</div>';
return html;
}
function getEditorHtml(options, systemInfo) {
var html = "";
var html = '';
html += '<div class="formDialogContent scrollY">';
html += '<div class="dialogContentInner dialog-content-centered" style="padding-top:2em;">';
if (!options.pathReadOnly) {
var instruction = options.instruction ? options.instruction + "<br/><br/>" : "";
var instruction = options.instruction ? options.instruction + '<br/><br/>' : '';
html += '<div class="infoBanner" style="margin-bottom:1.5em;">';
html += instruction;
html += Globalize.translate("MessageDirectoryPickerInstruction", "<b>\\\\server</b>", "<b>\\\\192.168.1.101</b>");
if ("bsd" === systemInfo.OperatingSystem.toLowerCase()) {
html += "<br/>";
html += "<br/>";
html += Globalize.translate("MessageDirectoryPickerBSDInstruction");
html += "<br/>";
} else if ("linux" === systemInfo.OperatingSystem.toLowerCase()) {
html += "<br/>";
html += "<br/>";
html += Globalize.translate("MessageDirectoryPickerLinuxInstruction");
html += "<br/>";
html += globalize.translate('MessageDirectoryPickerInstruction', '<b>\\\\server</b>', '<b>\\\\192.168.1.101</b>');
if ('bsd' === systemInfo.OperatingSystem.toLowerCase()) {
html += '<br/>';
html += '<br/>';
html += globalize.translate('MessageDirectoryPickerBSDInstruction');
html += '<br/>';
} else if ('linux' === systemInfo.OperatingSystem.toLowerCase()) {
html += '<br/>';
html += '<br/>';
html += globalize.translate('MessageDirectoryPickerLinuxInstruction');
html += '<br/>';
}
html += "</div>";
html += '</div>';
}
html += '<form style="margin:auto;">';
html += '<div class="inputContainer" style="display: flex; align-items: center;">';
html += '<div style="flex-grow:1;">';
var labelKey;
if (options.includeFiles !== true) {
labelKey = "LabelFolder";
labelKey = 'LabelFolder';
} else {
labelKey = "LabelPath";
labelKey = 'LabelPath';
}
var readOnlyAttribute = options.pathReadOnly ? " readonly" : "";
html += '<input is="emby-input" id="txtDirectoryPickerPath" type="text" required="required" ' + readOnlyAttribute + ' label="' + Globalize.translate(labelKey) + '"/>';
html += "</div>";
var readOnlyAttribute = options.pathReadOnly ? ' readonly' : '';
html += '<input is="emby-input" id="txtDirectoryPickerPath" type="text" required="required" ' + readOnlyAttribute + ' label="' + globalize.translate(labelKey) + '"/>';
html += '</div>';
if (!readOnlyAttribute) {
html += '<button type="button" is="paper-icon-button-light" class="btnRefreshDirectories emby-input-iconbutton" title="' + Globalize.translate("ButtonRefresh") + '"><i class="material-icons">search</i></button>';
html += '<button type="button" is="paper-icon-button-light" class="btnRefreshDirectories emby-input-iconbutton" title="' + globalize.translate('ButtonRefresh') + '"><span class="material-icons search"></span></button>';
}
html += "</div>";
html += '</div>';
if (!readOnlyAttribute) {
html += '<div class="results paperList" style="max-height: 200px; overflow-y: auto;"></div>';
}
if (options.enableNetworkSharePath) {
html += '<div class="inputContainer" style="margin-top:2em;">';
html += '<input is="emby-input" id="txtNetworkPath" type="text" label="' + Globalize.translate("LabelOptionalNetworkPath") + '"/>';
html += '<input is="emby-input" id="txtNetworkPath" type="text" label="' + globalize.translate('LabelOptionalNetworkPath') + '"/>';
html += '<div class="fieldDescription">';
html += Globalize.translate("LabelOptionalNetworkPathHelp");
html += "</div>";
html += "</div>";
html += globalize.translate('LabelOptionalNetworkPathHelp');
html += '</div>';
html += '</div>';
}
html += '<div class="formDialogFooter">';
html += '<button is="emby-button" type="submit" class="raised button-submit block formDialogFooterItem">' + Globalize.translate("ButtonOk") + "</button>";
html += "</div>";
html += "</form>";
html += "</div>";
html += "</div>";
html += "</div>";
html += '<button is="emby-button" type="submit" class="raised button-submit block formDialogFooterItem">' + globalize.translate('ButtonOk') + '</button>';
html += '</div>';
html += '</form>';
html += '</div>';
html += '</div>';
html += '</div>';
return html;
}
@ -148,15 +148,15 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
}
function alertTextWithOptions(options) {
require(["alert"], function(alert) {
require(['alert'], function(alert) {
alert(options);
});
}
function validatePath(path, validateWriteable, apiClient) {
return apiClient.ajax({
type: "POST",
url: apiClient.getUrl("Environment/ValidatePath"),
type: 'POST',
url: apiClient.getUrl('Environment/ValidatePath'),
data: {
ValidateWriteable: validateWriteable,
Path: path
@ -164,14 +164,14 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
}).catch(function(response) {
if (response) {
if (response.status === 404) {
alertText(Globalize.translate("PathNotFound"));
alertText(globalize.translate('PathNotFound'));
return Promise.reject();
}
if (response.status === 500) {
if (validateWriteable) {
alertText(Globalize.translate("WriteAccessRequired"));
alertText(globalize.translate('WriteAccessRequired'));
} else {
alertText(Globalize.translate("PathNotFound"));
alertText(globalize.translate('PathNotFound'));
}
return Promise.reject();
}
@ -181,37 +181,37 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
}
function initEditor(content, options, fileOptions) {
content.addEventListener("click", function(e) {
var lnkPath = dom.parentWithClass(e.target, "lnkPath");
content.addEventListener('click', function(e) {
var lnkPath = dom.parentWithClass(e.target, 'lnkPath');
if (lnkPath) {
var path = lnkPath.getAttribute("data-path");
if (lnkPath.classList.contains("lnkFile")) {
content.querySelector("#txtDirectoryPickerPath").value = path;
var path = lnkPath.getAttribute('data-path');
if (lnkPath.classList.contains('lnkFile')) {
content.querySelector('#txtDirectoryPickerPath').value = path;
} else {
refreshDirectoryBrowser(content, path, fileOptions, true);
}
}
});
content.addEventListener("click", function(e) {
if (dom.parentWithClass(e.target, "btnRefreshDirectories")) {
var path = content.querySelector("#txtDirectoryPickerPath").value;
content.addEventListener('click', function(e) {
if (dom.parentWithClass(e.target, 'btnRefreshDirectories')) {
var path = content.querySelector('#txtDirectoryPickerPath').value;
refreshDirectoryBrowser(content, path, fileOptions);
}
});
content.addEventListener("change", function(e) {
var txtDirectoryPickerPath = dom.parentWithTag(e.target, "INPUT");
if (txtDirectoryPickerPath && "txtDirectoryPickerPath" === txtDirectoryPickerPath.id) {
content.addEventListener('change', function(e) {
var txtDirectoryPickerPath = dom.parentWithTag(e.target, 'INPUT');
if (txtDirectoryPickerPath && 'txtDirectoryPickerPath' === txtDirectoryPickerPath.id) {
refreshDirectoryBrowser(content, txtDirectoryPickerPath.value, fileOptions);
}
});
content.querySelector("form").addEventListener("submit", function(e) {
content.querySelector('form').addEventListener('submit', function(e) {
if (options.callback) {
var networkSharePath = this.querySelector("#txtNetworkPath");
var networkSharePath = this.querySelector('#txtNetworkPath');
networkSharePath = networkSharePath ? networkSharePath.value : null;
var path = this.querySelector("#txtDirectoryPickerPath").value;
var path = this.querySelector('#txtDirectoryPickerPath').value;
validatePath(path, options.validateWriteable, ApiClient).then(options.callback(path, networkSharePath));
}
e.preventDefault();
@ -224,11 +224,11 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
if (options.path) {
return Promise.resolve(options.path);
} else {
return ApiClient.getJSON(ApiClient.getUrl("Environment/DefaultDirectoryBrowser")).then(
return ApiClient.getJSON(ApiClient.getUrl('Environment/DefaultDirectoryBrowser')).then(
function(result) {
return result.Path || "";
return result.Path || '';
}, function() {
return "";
return '';
}
);
}
@ -253,35 +253,35 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
var systemInfo = responses[0];
var initialPath = responses[1];
var dlg = dialogHelper.createDialog({
size: "medium-tall",
size: 'medium-tall',
removeOnClose: true,
scrollY: false
});
dlg.classList.add("ui-body-a");
dlg.classList.add("background-theme-a");
dlg.classList.add("directoryPicker");
dlg.classList.add("formDialog");
dlg.classList.add('ui-body-a');
dlg.classList.add('background-theme-a');
dlg.classList.add('directoryPicker');
dlg.classList.add('formDialog');
var html = "";
var html = '';
html += '<div class="formDialogHeader">';
html += '<button is="paper-icon-button-light" class="btnCloseDialog autoSize" tabindex="-1"><i class="material-icons arrow_back"></i></button>';
html += '<button is="paper-icon-button-light" class="btnCloseDialog autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
html += '<h3 class="formDialogHeaderTitle">';
html += options.header || Globalize.translate("HeaderSelectPath");
html += "</h3>";
html += "</div>";
html += options.header || globalize.translate('HeaderSelectPath');
html += '</h3>';
html += '</div>';
html += getEditorHtml(options, systemInfo);
dlg.innerHTML = html;
initEditor(dlg, options, fileOptions);
dlg.addEventListener("close", onDialogClosed);
dlg.addEventListener('close', onDialogClosed);
dialogHelper.open(dlg);
dlg.querySelector(".btnCloseDialog").addEventListener("click", function() {
dlg.querySelector('.btnCloseDialog').addEventListener('click', function() {
dialogHelper.close(dlg);
});
currentDialog = dlg;
dlg.querySelector("#txtDirectoryPickerPath").value = initialPath;
var txtNetworkPath = dlg.querySelector("#txtNetworkPath");
dlg.querySelector('#txtDirectoryPickerPath').value = initialPath;
var txtNetworkPath = dlg.querySelector('#txtNetworkPath');
if (txtNetworkPath) {
txtNetworkPath.value = options.networkSharePath || "";
txtNetworkPath.value = options.networkSharePath || '';
}
if (!options.pathReadOnly) {
refreshDirectoryBrowser(dlg, initialPath, fileOptions, true);

View file

@ -1,5 +1,5 @@
define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', 'apphost', 'focusManager', 'datetime', 'globalize', 'loading', 'connectionManager', 'skinManager', 'dom', 'events', 'emby-select', 'emby-checkbox', 'emby-button'], function (require, browser, layoutManager, appSettings, pluginManager, appHost, focusManager, datetime, globalize, loading, connectionManager, skinManager, dom, events) {
"use strict";
'use strict';
function fillThemes(select, isDashboard) {
select.innerHTML = skinManager.getThemes().map(function (t) {

View file

@ -1,41 +1,41 @@
define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoader", "globalize", "layoutManager", "scrollStyles", "emby-itemscontainer"], function (loading, libraryBrowser, cardBuilder, dom, appHost, imageLoader, globalize, layoutManager) {
"use strict";
define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoader', 'globalize', 'layoutManager', 'scrollStyles', 'emby-itemscontainer'], function (loading, libraryBrowser, cardBuilder, dom, appHost, imageLoader, globalize, layoutManager) {
'use strict';
function enableScrollX() {
return !layoutManager.desktop;
}
function getThumbShape() {
return enableScrollX() ? "overflowBackdrop" : "backdrop";
return enableScrollX() ? 'overflowBackdrop' : 'backdrop';
}
function getPosterShape() {
return enableScrollX() ? "overflowPortrait" : "portrait";
return enableScrollX() ? 'overflowPortrait' : 'portrait';
}
function getSquareShape() {
return enableScrollX() ? "overflowSquare" : "square";
return enableScrollX() ? 'overflowSquare' : 'square';
}
function getSections() {
return [{
name: "HeaderFavoriteMovies",
types: "Movie",
id: "favoriteMovies",
name: 'HeaderFavoriteMovies',
types: 'Movie',
id: 'favoriteMovies',
shape: getPosterShape(),
showTitle: false,
overlayPlayButton: true
}, {
name: "HeaderFavoriteShows",
types: "Series",
id: "favoriteShows",
name: 'HeaderFavoriteShows',
types: 'Series',
id: 'favoriteShows',
shape: getPosterShape(),
showTitle: false,
overlayPlayButton: true
}, {
name: "HeaderFavoriteEpisodes",
types: "Episode",
id: "favoriteEpisode",
name: 'HeaderFavoriteEpisodes',
types: 'Episode',
id: 'favoriteEpisode',
shape: getThumbShape(),
preferThumb: false,
showTitle: true,
@ -44,9 +44,9 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
overlayText: false,
centerText: true
}, {
name: "HeaderFavoriteVideos",
types: "Video,MusicVideo",
id: "favoriteVideos",
name: 'HeaderFavoriteVideos',
types: 'Video,MusicVideo',
id: 'favoriteVideos',
shape: getThumbShape(),
preferThumb: true,
showTitle: true,
@ -54,9 +54,9 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
overlayText: false,
centerText: true
}, {
name: "HeaderFavoriteArtists",
types: "MusicArtist",
id: "favoriteArtists",
name: 'HeaderFavoriteArtists',
types: 'MusicArtist',
id: 'favoriteArtists',
shape: getSquareShape(),
preferThumb: false,
showTitle: true,
@ -66,9 +66,9 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
overlayPlayButton: true,
coverImage: true
}, {
name: "HeaderFavoriteAlbums",
types: "MusicAlbum",
id: "favoriteAlbums",
name: 'HeaderFavoriteAlbums',
types: 'MusicAlbum',
id: 'favoriteAlbums',
shape: getSquareShape(),
preferThumb: false,
showTitle: true,
@ -78,9 +78,9 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
overlayPlayButton: true,
coverImage: true
}, {
name: "HeaderFavoriteSongs",
types: "Audio",
id: "favoriteSongs",
name: 'HeaderFavoriteSongs',
types: 'Audio',
id: 'favoriteSongs',
shape: getSquareShape(),
preferThumb: false,
showTitle: true,
@ -88,7 +88,7 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
showParentTitle: true,
centerText: true,
overlayMoreButton: true,
action: "instantmix",
action: 'instantmix',
coverImage: true
}];
}
@ -96,13 +96,13 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
function loadSection(elem, userId, topParentId, section, isSingleSection) {
var screenWidth = dom.getWindowSize().innerWidth;
var options = {
SortBy: "SortName",
SortOrder: "Ascending",
Filters: "IsFavorite",
SortBy: 'SortName',
SortOrder: 'Ascending',
Filters: 'IsFavorite',
Recursive: true,
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
CollapseBoxSetItems: false,
ExcludeLocationTypes: "Virtual",
ExcludeLocationTypes: 'Virtual',
EnableTotalRecordCount: false
};
@ -120,7 +120,7 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
var promise;
if ("MusicArtist" === section.types) {
if ('MusicArtist' === section.types) {
promise = ApiClient.getArtists(userId, options);
} else {
options.IncludeItemTypes = section.types;
@ -128,25 +128,25 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
}
return promise.then(function (result) {
var html = "";
var html = '';
if (result.Items.length) {
if (html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">', !layoutManager.tv && options.Limit && result.Items.length >= options.Limit) {
html += '<a is="emby-linkbutton" href="' + ("list.html?serverId=" + ApiClient.serverId() + "&type=" + section.types + "&IsFavorite=true") + '" class="more button-flat button-flat-mini sectionTitleTextButton">';
html += '<a is="emby-linkbutton" href="' + ('list.html?serverId=' + ApiClient.serverId() + '&type=' + section.types + '&IsFavorite=true') + '" class="more button-flat button-flat-mini sectionTitleTextButton">';
html += '<h2 class="sectionTitle sectionTitle-cards">';
html += globalize.translate(section.name);
html += "</h2>";
html += '<i class="material-icons chevron_right"></i>';
html += "</a>";
html += '</h2>';
html += '<span class="material-icons chevron_right"></span>';
html += '</a>';
} else {
html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate(section.name) + "</h2>";
html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate(section.name) + '</h2>';
}
html += "</div>";
html += '</div>';
if (enableScrollX()) {
var scrollXClass = "scrollX hiddenScrollX";
var scrollXClass = 'scrollX hiddenScrollX';
if (layoutManager.tv) {
scrollXClass += " smoothScrollX";
scrollXClass += ' smoothScrollX';
}
html += '<div is="emby-itemscontainer" class="itemsContainer ' + scrollXClass + ' padded-left padded-right">';
@ -154,7 +154,7 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
html += '<div is="emby-itemscontainer" class="itemsContainer vertical-wrap padded-left padded-right">';
}
var supportsImageAnalysis = appHost.supports("imageanalysis");
var supportsImageAnalysis = appHost.supports('imageanalysis');
var cardLayout = (appHost.preferVisualCards || supportsImageAnalysis) && section.autoCardLayout && section.showTitle;
cardLayout = false;
html += cardBuilder.getCardsHtml(result.Items, {
@ -172,7 +172,7 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
allowBottomPadding: !enableScrollX(),
cardLayout: cardLayout
});
html += "</div>";
html += '</div>';
}
elem.innerHTML = html;
@ -183,7 +183,7 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
function loadSections(page, userId, topParentId, types) {
loading.show();
var sections = getSections();
var sectionid = getParameterByName("sectionid");
var sectionid = getParameterByName('sectionid');
if (sectionid) {
sections = sections.filter(function (s) {
@ -199,10 +199,10 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
var i;
var length;
var elem = page.querySelector(".favoriteSections");
var elem = page.querySelector('.favoriteSections');
if (!elem.innerHTML) {
var html = "";
var html = '';
for (i = 0, length = sections.length; i < length; i++) {
html += '<div class="verticalSection section' + sections[i].id + '"></div>';
@ -215,7 +215,7 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
for (i = 0, length = sections.length; i < length; i++) {
var section = sections[i];
elem = page.querySelector(".section" + section.id);
elem = page.querySelector('.section' + section.id);
promises.push(loadSection(elem, userId, topParentId, section, 1 === sections.length));
}

View file

@ -86,7 +86,7 @@ define([], function () {
var value = params[key];
if (value !== null && value !== undefined && value !== '') {
values.push(encodeURIComponent(key) + "=" + encodeURIComponent(value));
values.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
}
}
return values.join('&');
@ -94,7 +94,7 @@ define([], function () {
function ajax(request) {
if (!request) {
throw new Error("Request cannot be null");
throw new Error('Request cannot be null');
}
request.headers = request.headers || {};

View file

@ -1,10 +1,10 @@
import multiDownload from "multi-download";
import multiDownload from 'multi-download';
export function download(items) {
if (window.NativeShell) {
items.map(function (item) {
window.NativeShell.downloadFile(item.url);
window.NativeShell.downloadFile(item);
});
} else {
multiDownload(items.map(function (item) {

View file

@ -1,52 +1,49 @@
define(["dom", "dialogHelper", "globalize", "connectionManager", "events", "browser", "require", "emby-checkbox", "emby-collapse", "css!./style"], function (dom, dialogHelper, globalize, connectionManager, events, browser, require) {
"use strict";
define(['dom', 'dialogHelper', 'globalize', 'connectionManager', 'events', 'browser', 'require', 'emby-checkbox', 'emby-collapse', 'css!./style'], function (dom, dialogHelper, globalize, connectionManager, events, browser, require) {
'use strict';
function renderOptions(context, selector, cssClass, items, isCheckedFn) {
var elem = context.querySelector(selector);
if (items.length) {
elem.classList.remove("hide");
elem.classList.remove('hide');
} else {
elem.classList.add("hide");
elem.classList.add('hide');
}
var html = "";
var html = '';
html += '<div class="checkboxList">';
html += items.map(function (filter) {
var itemHtml = "";
var checkedHtml = isCheckedFn(filter) ? " checked" : "";
itemHtml += "<label>";
var itemHtml = '';
var checkedHtml = isCheckedFn(filter) ? ' checked' : '';
itemHtml += '<label>';
itemHtml += '<input is="emby-checkbox" type="checkbox"' + checkedHtml + ' data-filter="' + filter + '" class="' + cssClass + '"/>';
itemHtml += "<span>" + filter + "</span>";
itemHtml += "</label>";
itemHtml += '<span>' + filter + '</span>';
itemHtml += '</label>';
return itemHtml;
}).join("");
html += "</div>";
elem.querySelector(".filterOptions").innerHTML = html;
}).join('');
html += '</div>';
elem.querySelector('.filterOptions').innerHTML = html;
}
function renderFilters(context, result, query) {
if (result.Tags) {
result.Tags.length = Math.min(result.Tags.length, 50);
}
renderOptions(context, ".genreFilters", "chkGenreFilter", result.Genres, function (i) {
var delimeter = "|";
return (delimeter + (query.Genres || "") + delimeter).indexOf(delimeter + i + delimeter) != -1;
renderOptions(context, '.genreFilters', 'chkGenreFilter', result.Genres, function (i) {
var delimeter = '|';
return (delimeter + (query.Genres || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
});
renderOptions(context, ".officialRatingFilters", "chkOfficialRatingFilter", result.OfficialRatings, function (i) {
var delimeter = "|";
return (delimeter + (query.OfficialRatings || "") + delimeter).indexOf(delimeter + i + delimeter) != -1;
renderOptions(context, '.officialRatingFilters', 'chkOfficialRatingFilter', result.OfficialRatings, function (i) {
var delimeter = '|';
return (delimeter + (query.OfficialRatings || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
});
renderOptions(context, ".tagFilters", "chkTagFilter", result.Tags, function (i) {
var delimeter = "|";
return (delimeter + (query.Tags || "") + delimeter).indexOf(delimeter + i + delimeter) != -1;
renderOptions(context, '.tagFilters', 'chkTagFilter', result.Tags, function (i) {
var delimeter = '|';
return (delimeter + (query.Tags || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
});
renderOptions(context, ".yearFilters", "chkYearFilter", result.Years, function (i) {
var delimeter = ",";
return (delimeter + (query.Years || "") + delimeter).indexOf(delimeter + i + delimeter) != -1;
renderOptions(context, '.yearFilters', 'chkYearFilter', result.Years, function (i) {
var delimeter = ',';
return (delimeter + (query.Years || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
});
}
function loadDynamicFilters(context, apiClient, userId, itemQuery) {
return apiClient.getJSON(apiClient.getUrl("Items/Filters", {
return apiClient.getJSON(apiClient.getUrl('Items/Filters', {
UserId: userId,
ParentId: itemQuery.ParentId,
IncludeItemTypes: itemQuery.IncludeItemTypes
@ -61,98 +58,98 @@ define(["dom", "dialogHelper", "globalize", "connectionManager", "events", "brow
var length;
var query = options.query;
if (options.mode == "livetvchannels") {
context.querySelector(".chkFavorite").checked = query.IsFavorite == true;
context.querySelector(".chkLikes").checked = query.IsLiked == true;
context.querySelector(".chkDislikes").checked = query.IsDisliked == true;
if (options.mode == 'livetvchannels') {
context.querySelector('.chkFavorite').checked = query.IsFavorite == true;
context.querySelector('.chkLikes').checked = query.IsLiked == true;
context.querySelector('.chkDislikes').checked = query.IsDisliked == true;
} else {
elems = context.querySelectorAll(".chkStandardFilter");
elems = context.querySelectorAll('.chkStandardFilter');
for (i = 0, length = elems.length; i < length; i++) {
var chkStandardFilter = elems[i];
var filters = "," + (query.Filters || "");
var filterName = chkStandardFilter.getAttribute("data-filter");
chkStandardFilter.checked = filters.indexOf("," + filterName) != -1;
var filters = ',' + (query.Filters || '');
var filterName = chkStandardFilter.getAttribute('data-filter');
chkStandardFilter.checked = filters.indexOf(',' + filterName) != -1;
}
}
elems = context.querySelectorAll(".chkVideoTypeFilter");
elems = context.querySelectorAll('.chkVideoTypeFilter');
for (i = 0, length = elems.length; i < length; i++) {
var chkVideoTypeFilter = elems[i];
var filters = "," + (query.VideoTypes || "");
var filterName = chkVideoTypeFilter.getAttribute("data-filter");
chkVideoTypeFilter.checked = filters.indexOf("," + filterName) != -1;
var filters = ',' + (query.VideoTypes || '');
var filterName = chkVideoTypeFilter.getAttribute('data-filter');
chkVideoTypeFilter.checked = filters.indexOf(',' + filterName) != -1;
}
context.querySelector(".chk3DFilter").checked = query.Is3D == true;
context.querySelector(".chkHDFilter").checked = query.IsHD == true;
context.querySelector(".chk4KFilter").checked = query.Is4K == true;
context.querySelector(".chkSDFilter").checked = query.IsHD == true;
context.querySelector("#chkSubtitle").checked = query.HasSubtitles == true;
context.querySelector("#chkTrailer").checked = query.HasTrailer == true;
context.querySelector("#chkThemeSong").checked = query.HasThemeSong == true;
context.querySelector("#chkThemeVideo").checked = query.HasThemeVideo == true;
context.querySelector("#chkSpecialFeature").checked = query.HasSpecialFeature == true;
context.querySelector("#chkSpecialEpisode").checked = query.ParentIndexNumber == 0;
context.querySelector("#chkMissingEpisode").checked = query.IsMissing == true;
context.querySelector("#chkFutureEpisode").checked = query.IsUnaired == true;
context.querySelector('.chk3DFilter').checked = query.Is3D == true;
context.querySelector('.chkHDFilter').checked = query.IsHD == true;
context.querySelector('.chk4KFilter').checked = query.Is4K == true;
context.querySelector('.chkSDFilter').checked = query.IsHD == true;
context.querySelector('#chkSubtitle').checked = query.HasSubtitles == true;
context.querySelector('#chkTrailer').checked = query.HasTrailer == true;
context.querySelector('#chkThemeSong').checked = query.HasThemeSong == true;
context.querySelector('#chkThemeVideo').checked = query.HasThemeVideo == true;
context.querySelector('#chkSpecialFeature').checked = query.HasSpecialFeature == true;
context.querySelector('#chkSpecialEpisode').checked = query.ParentIndexNumber == 0;
context.querySelector('#chkMissingEpisode').checked = query.IsMissing == true;
context.querySelector('#chkFutureEpisode').checked = query.IsUnaired == true;
for (i = 0, length = elems.length; i < length; i++) {
var chkStatus = elems[i];
var filters = "," + (query.SeriesStatus || "");
var filterName = chkStatus.getAttribute("data-filter");
chkStatus.checked = filters.indexOf("," + filterName) != -1;
var filters = ',' + (query.SeriesStatus || '');
var filterName = chkStatus.getAttribute('data-filter');
chkStatus.checked = filters.indexOf(',' + filterName) != -1;
}
}
function triggerChange(instance) {
events.trigger(instance, "filterchange");
events.trigger(instance, 'filterchange');
}
function setVisibility(context, options) {
if (options.mode == "livetvchannels" || options.mode == "albums" || options.mode == "artists" || options.mode == "albumartists" || options.mode == "songs") {
hideByClass(context, "videoStandard");
if (options.mode == 'livetvchannels' || options.mode == 'albums' || options.mode == 'artists' || options.mode == 'albumartists' || options.mode == 'songs') {
hideByClass(context, 'videoStandard');
}
if (enableDynamicFilters(options.mode)) {
context.querySelector(".genreFilters").classList.remove("hide");
context.querySelector(".officialRatingFilters").classList.remove("hide");
context.querySelector(".tagFilters").classList.remove("hide");
context.querySelector(".yearFilters").classList.remove("hide");
context.querySelector('.genreFilters').classList.remove('hide');
context.querySelector('.officialRatingFilters').classList.remove('hide');
context.querySelector('.tagFilters').classList.remove('hide');
context.querySelector('.yearFilters').classList.remove('hide');
}
if (options.mode == "movies" || options.mode == "episodes") {
context.querySelector(".videoTypeFilters").classList.remove("hide");
if (options.mode == 'movies' || options.mode == 'episodes') {
context.querySelector('.videoTypeFilters').classList.remove('hide');
}
if (options.mode == "movies" || options.mode == "series" || options.mode == "episodes") {
context.querySelector(".features").classList.remove("hide");
if (options.mode == 'movies' || options.mode == 'series' || options.mode == 'episodes') {
context.querySelector('.features').classList.remove('hide');
}
if (options.mode == "series") {
context.querySelector(".seriesStatus").classList.remove("hide");
if (options.mode == 'series') {
context.querySelector('.seriesStatus').classList.remove('hide');
}
if (options.mode == "episodes") {
showByClass(context, "episodeFilter");
if (options.mode == 'episodes') {
showByClass(context, 'episodeFilter');
}
}
function showByClass(context, className) {
var elems = context.querySelectorAll("." + className);
var elems = context.querySelectorAll('.' + className);
for (var i = 0, length = elems.length; i < length; i++) {
elems[i].classList.remove("hide");
elems[i].classList.remove('hide');
}
}
function hideByClass(context, className) {
var elems = context.querySelectorAll("." + className);
var elems = context.querySelectorAll('.' + className);
for (var i = 0, length = elems.length; i < length; i++) {
elems[i].classList.add("hide");
elems[i].classList.add('hide');
}
}
function enableDynamicFilters(mode) {
return mode == "movies" || mode == "series" || mode == "albums" || mode == "albumartists" || mode == "artists" || mode == "songs" || mode == "episodes";
return mode == 'movies' || mode == 'series' || mode == 'albums' || mode == 'albumartists' || mode == 'artists' || mode == 'songs' || mode == 'episodes';
}
return function (options) {
@ -165,12 +162,12 @@ define(["dom", "dialogHelper", "globalize", "connectionManager", "events", "brow
function onStandardFilterChange() {
var query = options.query;
var filterName = this.getAttribute("data-filter");
var filters = query.Filters || "";
filters = ("," + filters).replace("," + filterName, "").substring(1);
var filterName = this.getAttribute('data-filter');
var filters = query.Filters || '';
filters = (',' + filters).replace(',' + filterName, '').substring(1);
if (this.checked) {
filters = filters ? filters + "," + filterName : filterName;
filters = filters ? filters + ',' + filterName : filterName;
}
query.StartIndex = 0;
@ -180,12 +177,12 @@ define(["dom", "dialogHelper", "globalize", "connectionManager", "events", "brow
function onVideoTypeFilterChange() {
var query = options.query;
var filterName = this.getAttribute("data-filter");
var filters = query.VideoTypes || "";
filters = ("," + filters).replace("," + filterName, "").substring(1);
var filterName = this.getAttribute('data-filter');
var filters = query.VideoTypes || '';
filters = (',' + filters).replace(',' + filterName, '').substring(1);
if (this.checked) {
filters = filters ? filters + "," + filterName : filterName;
filters = filters ? filters + ',' + filterName : filterName;
}
query.StartIndex = 0;
@ -195,12 +192,12 @@ define(["dom", "dialogHelper", "globalize", "connectionManager", "events", "brow
function onStatusChange() {
var query = options.query;
var filterName = this.getAttribute("data-filter");
var filters = query.SeriesStatus || "";
filters = ("," + filters).replace("," + filterName, "").substring(1);
var filterName = this.getAttribute('data-filter');
var filters = query.SeriesStatus || '';
filters = (',' + filters).replace(',' + filterName, '').substring(1);
if (this.checked) {
filters = filters ? filters + "," + filterName : filterName;
filters = filters ? filters + ',' + filterName : filterName;
}
query.SeriesStatus = filters;
@ -214,86 +211,86 @@ define(["dom", "dialogHelper", "globalize", "connectionManager", "events", "brow
var length;
var query = options.query;
if (options.mode == "livetvchannels") {
elems = context.querySelectorAll(".chkFavorite");
if (options.mode == 'livetvchannels') {
elems = context.querySelectorAll('.chkFavorite');
for (i = 0, length = elems.length; i < length; i++) {
elems[i].addEventListener("change", onFavoriteChange);
elems[i].addEventListener('change', onFavoriteChange);
}
context.querySelector(".chkLikes").addEventListener("change", function () {
context.querySelector('.chkLikes').addEventListener('change', function () {
query.StartIndex = 0;
query.IsLiked = this.checked ? true : null;
triggerChange(self);
});
context.querySelector(".chkDislikes").addEventListener("change", function () {
context.querySelector('.chkDislikes').addEventListener('change', function () {
query.StartIndex = 0;
query.IsDisliked = this.checked ? true : null;
triggerChange(self);
});
} else {
elems = context.querySelectorAll(".chkStandardFilter");
elems = context.querySelectorAll('.chkStandardFilter');
for (i = 0, length = elems.length; i < length; i++) {
elems[i].addEventListener("change", onStandardFilterChange);
elems[i].addEventListener('change', onStandardFilterChange);
}
}
elems = context.querySelectorAll(".chkVideoTypeFilter");
elems = context.querySelectorAll('.chkVideoTypeFilter');
for (i = 0, length = elems.length; i < length; i++) {
elems[i].addEventListener("change", onVideoTypeFilterChange);
elems[i].addEventListener('change', onVideoTypeFilterChange);
}
context.querySelector(".chk3DFilter").addEventListener("change", function () {
context.querySelector('.chk3DFilter').addEventListener('change', function () {
query.StartIndex = 0;
query.Is3D = this.checked ? true : null;
triggerChange(self);
});
context.querySelector(".chk4KFilter").addEventListener("change", function () {
context.querySelector('.chk4KFilter').addEventListener('change', function () {
query.StartIndex = 0;
query.Is4K = this.checked ? true : null;
triggerChange(self);
});
context.querySelector(".chkHDFilter").addEventListener("change", function () {
context.querySelector('.chkHDFilter').addEventListener('change', function () {
query.StartIndex = 0;
query.IsHD = this.checked ? true : null;
triggerChange(self);
});
context.querySelector(".chkSDFilter").addEventListener("change", function () {
context.querySelector('.chkSDFilter').addEventListener('change', function () {
query.StartIndex = 0;
query.IsHD = this.checked ? false : null;
triggerChange(self);
});
elems = context.querySelectorAll(".chkStatus");
elems = context.querySelectorAll('.chkStatus');
for (i = 0, length = elems.length; i < length; i++) {
elems[i].addEventListener("change", onStatusChange);
elems[i].addEventListener('change', onStatusChange);
}
context.querySelector("#chkTrailer").addEventListener("change", function () {
context.querySelector('#chkTrailer').addEventListener('change', function () {
query.StartIndex = 0;
query.HasTrailer = this.checked ? true : null;
triggerChange(self);
});
context.querySelector("#chkThemeSong").addEventListener("change", function () {
context.querySelector('#chkThemeSong').addEventListener('change', function () {
query.StartIndex = 0;
query.HasThemeSong = this.checked ? true : null;
triggerChange(self);
});
context.querySelector("#chkSpecialFeature").addEventListener("change", function () {
context.querySelector('#chkSpecialFeature').addEventListener('change', function () {
query.StartIndex = 0;
query.HasSpecialFeature = this.checked ? true : null;
triggerChange(self);
});
context.querySelector("#chkThemeVideo").addEventListener("change", function () {
context.querySelector('#chkThemeVideo').addEventListener('change', function () {
query.StartIndex = 0;
query.HasThemeVideo = this.checked ? true : null;
triggerChange(self);
});
context.querySelector("#chkMissingEpisode").addEventListener("change", function () {
context.querySelector('#chkMissingEpisode').addEventListener('change', function () {
query.StartIndex = 0;
query.IsMissing = this.checked ? true : false;
triggerChange(self);
});
context.querySelector("#chkSpecialEpisode").addEventListener("change", function () {
context.querySelector('#chkSpecialEpisode').addEventListener('change', function () {
query.StartIndex = 0;
query.ParentIndexNumber = this.checked ? 0 : null;
triggerChange(self);
});
context.querySelector("#chkFutureEpisode").addEventListener("change", function () {
context.querySelector('#chkFutureEpisode').addEventListener('change', function () {
query.StartIndex = 0;
if (this.checked) {
query.IsUnaired = true;
@ -304,18 +301,18 @@ define(["dom", "dialogHelper", "globalize", "connectionManager", "events", "brow
}
triggerChange(self);
});
context.querySelector("#chkSubtitle").addEventListener("change", function () {
context.querySelector('#chkSubtitle').addEventListener('change', function () {
query.StartIndex = 0;
query.HasSubtitles = this.checked ? true : null;
triggerChange(self);
});
context.addEventListener("change", function (e) {
var chkGenreFilter = dom.parentWithClass(e.target, "chkGenreFilter");
context.addEventListener('change', function (e) {
var chkGenreFilter = dom.parentWithClass(e.target, 'chkGenreFilter');
if (chkGenreFilter) {
var filterName = chkGenreFilter.getAttribute("data-filter");
var filters = query.Genres || "";
var delimiter = "|";
filters = (delimiter + filters).replace(delimiter + filterName, "").substring(1);
var filterName = chkGenreFilter.getAttribute('data-filter');
var filters = query.Genres || '';
var delimiter = '|';
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
if (chkGenreFilter.checked) {
filters = filters ? (filters + delimiter + filterName) : filterName;
}
@ -324,12 +321,12 @@ define(["dom", "dialogHelper", "globalize", "connectionManager", "events", "brow
triggerChange(self);
return;
}
var chkTagFilter = dom.parentWithClass(e.target, "chkTagFilter");
var chkTagFilter = dom.parentWithClass(e.target, 'chkTagFilter');
if (chkTagFilter) {
var filterName = chkTagFilter.getAttribute("data-filter");
var filters = query.Tags || "";
var delimiter = "|";
filters = (delimiter + filters).replace(delimiter + filterName, "").substring(1);
var filterName = chkTagFilter.getAttribute('data-filter');
var filters = query.Tags || '';
var delimiter = '|';
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
if (chkTagFilter.checked) {
filters = filters ? (filters + delimiter + filterName) : filterName;
}
@ -338,12 +335,12 @@ define(["dom", "dialogHelper", "globalize", "connectionManager", "events", "brow
triggerChange(self);
return;
}
var chkYearFilter = dom.parentWithClass(e.target, "chkYearFilter");
var chkYearFilter = dom.parentWithClass(e.target, 'chkYearFilter');
if (chkYearFilter) {
var filterName = chkYearFilter.getAttribute("data-filter");
var filters = query.Years || "";
var delimiter = ",";
filters = (delimiter + filters).replace(delimiter + filterName, "").substring(1);
var filterName = chkYearFilter.getAttribute('data-filter');
var filters = query.Years || '';
var delimiter = ',';
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
if (chkYearFilter.checked) {
filters = filters ? (filters + delimiter + filterName) : filterName;
}
@ -352,12 +349,12 @@ define(["dom", "dialogHelper", "globalize", "connectionManager", "events", "brow
triggerChange(self);
return;
}
var chkOfficialRatingFilter = dom.parentWithClass(e.target, "chkOfficialRatingFilter");
var chkOfficialRatingFilter = dom.parentWithClass(e.target, 'chkOfficialRatingFilter');
if (chkOfficialRatingFilter) {
var filterName = chkOfficialRatingFilter.getAttribute("data-filter");
var filters = query.OfficialRatings || "";
var delimiter = "|";
filters = (delimiter + filters).replace(delimiter + filterName, "").substring(1);
var filterName = chkOfficialRatingFilter.getAttribute('data-filter');
var filters = query.OfficialRatings || '';
var delimiter = '|';
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
if (chkOfficialRatingFilter.checked) {
filters = filters ? (filters + delimiter + filterName) : filterName;
}
@ -373,23 +370,23 @@ define(["dom", "dialogHelper", "globalize", "connectionManager", "events", "brow
self.show = function () {
return new Promise(function (resolve, reject) {
require(["text!./filterdialog.template.html"], function (template) {
require(['text!./filterdialog.template.html'], function (template) {
var dlg = dialogHelper.createDialog({
removeOnClose: true,
modal: false
});
dlg.classList.add("ui-body-a");
dlg.classList.add("background-theme-a");
dlg.classList.add("formDialog");
dlg.classList.add("filterDialog");
dlg.classList.add('ui-body-a');
dlg.classList.add('background-theme-a');
dlg.classList.add('formDialog');
dlg.classList.add('filterDialog');
dlg.innerHTML = globalize.translateDocument(template);
setVisibility(dlg, options);
dialogHelper.open(dlg);
dlg.addEventListener("close", resolve);
dlg.addEventListener('close', resolve);
updateFilterControls(dlg, options);
bindEvents(dlg);
if (enableDynamicFilters(options.mode)) {
dlg.classList.add("dynamicFilterDialog");
dlg.classList.add('dynamicFilterDialog');
var apiClient = connectionManager.getApiClient(options.serverId);
loadDynamicFilters(dlg, apiClient, apiClient.getCurrentUserId(), options.query);
}

View file

@ -279,7 +279,7 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
var html = '';
html += '<div class="formDialogHeader">';
html += '<button is="paper-icon-button-light" class="btnCancel hide-mouse-idle-tv" tabindex="-1"><i class="material-icons arrow_back"></i></button>';
html += '<button is="paper-icon-button-light" class="btnCancel hide-mouse-idle-tv" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
html += '<h3 class="formDialogHeaderTitle">${Filters}</h3>';
html += '</div>';

View file

@ -117,7 +117,7 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
return false;
}
if (elem.getAttribute('tabindex') === "-1") {
if (elem.getAttribute('tabindex') === '-1') {
return false;
}

View file

@ -1,103 +0,0 @@
define(['events', 'dom', 'apphost', 'browser'], function (events, dom, appHost, browser) {
'use strict';
function fullscreenManager() {
}
fullscreenManager.prototype.requestFullscreen = function (element) {
element = element || document.documentElement;
if (element.requestFullscreen) {
element.requestFullscreen();
return;
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen();
return;
} else if (element.webkitRequestFullscreen) {
element.webkitRequestFullscreen();
return;
} else if (element.msRequestFullscreen) {
element.msRequestFullscreen();
return;
}
// Hack - This is only available for video elements in ios safari
if (element.tagName !== 'VIDEO') {
element = document.querySelector('video') || element;
}
if (element.webkitEnterFullscreen) {
element.webkitEnterFullscreen();
}
};
fullscreenManager.prototype.exitFullscreen = function () {
if (!this.isFullScreen()) {
return;
}
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.webkitCancelFullscreen) {
document.webkitCancelFullscreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
};
// TODO: use screenfull.js
fullscreenManager.prototype.isFullScreen = function () {
return document.fullscreen ||
document.mozFullScreen ||
document.webkitIsFullScreen ||
document.msFullscreenElement || /* IE/Edge syntax */
document.fullscreenElement || /* Standard syntax */
document.webkitFullscreenElement || /* Chrome, Safari and Opera syntax */
document.mozFullScreenElement; /* Firefox syntax */
};
var manager = new fullscreenManager();
function onFullScreenChange() {
events.trigger(manager, 'fullscreenchange');
}
dom.addEventListener(document, 'fullscreenchange', onFullScreenChange, {
passive: true
});
dom.addEventListener(document, 'webkitfullscreenchange', onFullScreenChange, {
passive: true
});
dom.addEventListener(document, 'mozfullscreenchange', onFullScreenChange, {
passive: true
});
function isTargetValid(target) {
return !dom.parentWithTag(target, ['BUTTON', 'INPUT', 'TEXTAREA']);
}
if (appHost.supports("fullscreenchange") && (browser.edgeUwp || -1 !== navigator.userAgent.toLowerCase().indexOf("electron"))) {
dom.addEventListener(window, 'dblclick', function (e) {
if (isTargetValid(e.target)) {
if (manager.isFullScreen()) {
manager.exitFullscreen();
} else {
manager.requestFullscreen();
}
}
}, {
passive: true
});
}
return manager;
});

View file

@ -1,28 +1,28 @@
define(["dom", "appRouter", "connectionManager"], function (dom, appRouter, connectionManager) {
"use strict";
define(['dom', 'appRouter', 'connectionManager'], function (dom, appRouter, connectionManager) {
'use strict';
function onGroupedCardClick(e, card) {
var itemId = card.getAttribute("data-id");
var serverId = card.getAttribute("data-serverid");
var itemId = card.getAttribute('data-id');
var serverId = card.getAttribute('data-serverid');
var apiClient = connectionManager.getApiClient(serverId);
var userId = apiClient.getCurrentUserId();
var playedIndicator = card.querySelector(".playedIndicator");
var playedIndicator = card.querySelector('.playedIndicator');
var playedIndicatorHtml = playedIndicator ? playedIndicator.innerHTML : null;
var options = {
Limit: parseInt(playedIndicatorHtml || "10"),
Fields: "PrimaryImageAspectRatio,DateCreated",
Limit: parseInt(playedIndicatorHtml || '10'),
Fields: 'PrimaryImageAspectRatio,DateCreated',
ParentId: itemId,
GroupItems: false
};
var actionableParent = dom.parentWithTag(e.target, ["A", "BUTTON", "INPUT"]);
var actionableParent = dom.parentWithTag(e.target, ['A', 'BUTTON', 'INPUT']);
if (!actionableParent || actionableParent.classList.contains("cardContent")) {
apiClient.getJSON(apiClient.getUrl("Users/" + userId + "/Items/Latest", options)).then(function (items) {
if (!actionableParent || actionableParent.classList.contains('cardContent')) {
apiClient.getJSON(apiClient.getUrl('Users/' + userId + '/Items/Latest', options)).then(function (items) {
if (1 === items.length) {
return void appRouter.showItem(items[0]);
}
var url = "itemdetails.html?id=" + itemId + "&serverId=" + serverId;
var url = 'itemdetails.html?id=' + itemId + '&serverId=' + serverId;
Dashboard.navigate(url);
});
e.stopPropagation();
@ -32,7 +32,7 @@ define(["dom", "appRouter", "connectionManager"], function (dom, appRouter, conn
}
function onItemsContainerClick(e) {
var groupedCard = dom.parentWithClass(e.target, "groupedCard");
var groupedCard = dom.parentWithClass(e.target, 'groupedCard');
if (groupedCard) {
onGroupedCardClick(e, groupedCard);

View file

@ -1,5 +1,5 @@
<div class="formDialogHeader">
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><i class="material-icons arrow_back"></i></button>
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>
<h3 class="formDialogHeaderTitle">
${Settings}
</h3>

View file

@ -1,4 +1,4 @@
define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', 'scrollHelper', 'serverNotifications', 'loading', 'datetime', 'focusManager', 'playbackManager', 'userSettings', 'imageLoader', 'events', 'layoutManager', 'itemShortcuts', 'dom', 'css!./guide.css', 'programStyles', 'material-icons', 'scrollStyles', 'emby-button', 'paper-icon-button-light', 'emby-tabs', 'emby-scroller', 'flexStyles', 'registerElement'], function (require, inputManager, browser, globalize, connectionManager, scrollHelper, serverNotifications, loading, datetime, focusManager, playbackManager, userSettings, imageLoader, events, layoutManager, itemShortcuts, dom) {
define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', 'scrollHelper', 'serverNotifications', 'loading', 'datetime', 'focusManager', 'playbackManager', 'userSettings', 'imageLoader', 'events', 'layoutManager', 'itemShortcuts', 'dom', 'css!./guide.css', 'programStyles', 'material-icons', 'scrollStyles', 'emby-programcell', 'emby-button', 'paper-icon-button-light', 'emby-tabs', 'emby-scroller', 'flexStyles', 'registerElement'], function (require, inputManager, browser, globalize, connectionManager, scrollHelper, serverNotifications, loading, datetime, focusManager, playbackManager, userSettings, imageLoader, events, layoutManager, itemShortcuts, dom) {
'use strict';
function showViewSettings(instance) {
@ -227,7 +227,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
channelQuery.Limit = channelLimit;
channelQuery.AddCurrentProgram = false;
channelQuery.EnableUserData = false;
channelQuery.EnableImageTypes = "Primary";
channelQuery.EnableImageTypes = 'Primary';
var categories = self.categoryOptions.categories || [];
var displayMovieContent = !categories.length || categories.indexOf('movies') !== -1;
@ -261,8 +261,8 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
}
if (userSettings.get('livetv-channelorder') === 'DatePlayed') {
channelQuery.SortBy = "DatePlayed";
channelQuery.SortOrder = "Descending";
channelQuery.SortBy = 'DatePlayed';
channelQuery.SortOrder = 'Descending';
} else {
channelQuery.SortBy = null;
channelQuery.SortOrder = null;
@ -329,7 +329,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
ImageTypeLimit: 1,
EnableImages: false,
//EnableImageTypes: layoutManager.tv ? "Primary,Backdrop" : "Primary",
SortBy: "StartDate",
SortBy: 'StartDate',
EnableTotalRecordCount: false,
EnableUserData: false
};
@ -415,7 +415,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
var status;
if (item.Type === 'SeriesTimer') {
return '<i class="material-icons programIcon seriesTimerIcon fiber_smart_record"></i>';
return '<span class="material-icons programIcon seriesTimerIcon fiber_smart_record"></span>';
} else if (item.TimerId || item.SeriesTimerId) {
status = item.Status || 'Cancelled';
@ -429,13 +429,13 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
if (item.SeriesTimerId) {
if (status !== 'Cancelled') {
return '<i class="material-icons programIcon seriesTimerIcon fiber_smart_record"></i>';
return '<span class="material-icons programIcon seriesTimerIcon fiber_smart_record"></span>';
}
return '<i class="material-icons programIcon seriesTimerIcon seriesTimerIcon-inactive fiber_smart_record"></i>';
return '<span class="material-icons programIcon seriesTimerIcon seriesTimerIcon-inactive fiber_smart_record"></span>';
}
return '<i class="material-icons programIcon timerIcon fiber_manual_record"></i>';
return '<span class="material-icons programIcon timerIcon fiber_manual_record"></span>';
}
function getChannelProgramsHtml(context, date, channel, programs, options, listInfo) {
@ -502,7 +502,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
var endPercent = (renderEndMs - renderStartMs) / msPerDay;
endPercent *= 100;
var cssClass = "programCell itemAction";
var cssClass = 'programCell itemAction';
var accentCssClass = null;
var displayInnerContent = true;
@ -525,11 +525,11 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
}
if (displayInnerContent && enableColorCodedBackgrounds && accentCssClass) {
cssClass += " programCell-" + accentCssClass;
cssClass += ' programCell-' + accentCssClass;
}
if (now >= startDateLocalMs && now < endDateLocalMs) {
cssClass += " programCell-active";
cssClass += ' programCell-active';
}
var timerAttributes = '';
@ -545,11 +545,11 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
html += '<button' + isAttribute + ' data-action="' + clickAction + '"' + timerAttributes + ' data-channelid="' + program.ChannelId + '" data-id="' + program.Id + '" data-serverid="' + program.ServerId + '" data-startdate="' + program.StartDate + '" data-enddate="' + program.EndDate + '" data-type="' + program.Type + '" class="' + cssClass + '" style="left:' + startPercent + '%;width:' + endPercent + '%;">';
if (displayInnerContent) {
var guideProgramNameClass = "guideProgramName";
var guideProgramNameClass = 'guideProgramName';
html += '<div class="' + guideProgramNameClass + '">';
html += '<div class="guide-programNameCaret hide"><i class="guideProgramNameCaretIcon material-icons keyboard_arrow_left"></i></div>';
html += '<div class="guide-programNameCaret hide"><span class="guideProgramNameCaretIcon material-icons keyboard_arrow_left"></span></div>';
html += '<div class="guideProgramNameText">' + program.Name;
@ -577,7 +577,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
html += '</div>';
if (program.IsHD && options.showHdIcon) {
//html += '<i class="guideHdIcon material-icons programIcon">hd</i>';
//html += '<span class="guideHdIcon material-icons programIcon hd"></span>';
if (layoutManager.tv) {
html += '<div class="programIcon guide-programTextIcon guide-programTextIcon-tv">HD</div>';
} else {
@ -630,7 +630,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
var url = apiClient.getScaledImageUrl(channel.Id, {
maxHeight: 220,
tag: channel.ImageTags.Primary,
type: "Primary"
type: 'Primary'
});
html += '<div class="guideChannelImage lazy" data-src="' + url + '"></div>';
@ -1105,7 +1105,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
var icon = cell.querySelector('.timerIcon');
if (!icon) {
cell.querySelector('.guideProgramName').insertAdjacentHTML('beforeend', '<i class="timerIcon material-icons programIcon fiber_manual_record"></i>');
cell.querySelector('.guideProgramName').insertAdjacentHTML('beforeend', '<span class="timerIcon material-icons programIcon fiber_manual_record"></span>');
}
if (newTimerId) {
@ -1252,18 +1252,5 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
});
}
var ProgramCellPrototype = Object.create(HTMLButtonElement.prototype);
ProgramCellPrototype.detachedCallback = function () {
this.posLeft = null;
this.posWidth = null;
this.guideProgramName = null;
};
document.registerElement('emby-programcell', {
prototype: ProgramCellPrototype,
extends: 'button'
});
return Guide;
});

View file

@ -10,7 +10,7 @@
<div class="guide-headerTimeslots">
<div class="guide-channelTimeslotHeader">
<button is="paper-icon-button-light" type="button" class="btnGuideViewSettings">
<i class="material-icons btnGuideViewSettingsIcon more_horiz"></i>
<span class="material-icons btnGuideViewSettingsIcon more_horiz"></span>
</button>
</div>
<div class="timeslotHeaders scrollX guideScroller"></div>
@ -30,9 +30,9 @@
<div class="guideOptions hide">
<button is="paper-icon-button-light" type="button" class="btnPreviousPage">
<i class="material-icons arrow_back"></i>
<span class="material-icons arrow_back"></span>
</button>
<button is="paper-icon-button-light" type="button" class="btnNextPage">
<i class="material-icons arrow_forward"></i>
<span class="material-icons arrow_forward"></span>
</button>
</div>

View file

@ -1,11 +0,0 @@
.headroom {
transition: transform 140ms linear;
}
.headroom--pinned {
transform: none;
}
.headroom--unpinned:not(.headroomDisabled) {
transform: translateY(-100%);
}

View file

@ -1,343 +0,0 @@
/*!
* headroom.js v0.7.0 - Give your page some headroom. Hide your header until you need it
* Copyright (c) 2014 Nick Williams - http://wicky.nillia.ms/headroom.js
* License: MIT
*/
define(['dom', 'layoutManager', 'browser', 'css!./headroom'], function (dom, layoutManager, browser) {
'use strict';
/* exported features */
var requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
/**
* Handles debouncing of events via requestAnimationFrame
* @see http://www.html5rocks.com/en/tutorials/speed/animations/
* @param {Function} callback The callback to handle whichever event
*/
function Debouncer(callback) {
this.callback = callback;
this.ticking = false;
}
Debouncer.prototype = {
constructor: Debouncer,
/**
* dispatches the event to the supplied callback
* @private
*/
update: function () {
if (this.callback) {
this.callback();
}
this.ticking = false;
},
/**
* Attach this as the event listeners
*/
handleEvent: function () {
if (!this.ticking) {
requestAnimationFrame(this.rafCallback || (this.rafCallback = this.update.bind(this)));
this.ticking = true;
}
}
};
function onHeadroomClearedExternally() {
this.state = null;
}
/**
* UI enhancement for fixed headers.
* Hides header when scrolling down
* Shows header when scrolling up
* @constructor
* @param {DOMElement} elem the header element
* @param {Object} options options for the widget
*/
function Headroom(elems, options) {
options = Object.assign(Headroom.options, options || {});
this.lastKnownScrollY = 0;
this.elems = elems;
this.scroller = options.scroller;
this.debouncer = onScroll.bind(this);
this.offset = options.offset;
this.initialised = false;
this.initialClass = options.initialClass;
this.unPinnedClass = options.unPinnedClass;
this.pinnedClass = options.pinnedClass;
this.state = 'clear';
this.options = {
offset: 0,
scroller: window,
initialClass: 'headroom',
unPinnedClass: 'headroom--unpinned',
pinnedClass: 'headroom--pinned'
};
this.add = function (elem) {
if (browser.supportsCssAnimation()) {
elem.classList.add(this.initialClass);
elem.addEventListener('clearheadroom', onHeadroomClearedExternally.bind(this));
this.elems.push(elem);
}
};
this.remove = function (elem) {
elem.classList.remove(this.unPinnedClass);
elem.classList.remove(this.initialClass);
elem.classList.remove(this.pinnedClass);
var i = this.elems.indexOf(elem);
if (i !== -1) {
this.elems.splice(i, 1);
}
};
this.pause = function () {
this.paused = true;
};
this.resume = function () {
this.paused = false;
};
/**
* Unattaches events and removes any classes that were added
*/
this.destroy = function () {
this.initialised = false;
for (var i = 0, length = this.elems.length; i < length; i++) {
var classList = this.elems[i].classList;
classList.remove(this.unPinnedClass);
classList.remove(this.initialClass);
classList.remove(this.pinnedClass);
}
var scrollEventName = this.scroller.getScrollEventName ? this.scroller.getScrollEventName() : 'scroll';
dom.removeEventListener(this.scroller, scrollEventName, this.debouncer, {
capture: false,
passive: true
});
};
/**
* Attaches the scroll event
* @private
*/
this.attachEvent = function () {
if (!this.initialised) {
this.lastKnownScrollY = this.getScrollY();
this.initialised = true;
var scrollEventName = this.scroller.getScrollEventName ? this.scroller.getScrollEventName() : 'scroll';
dom.addEventListener(this.scroller, scrollEventName, this.debouncer, {
capture: false,
passive: true
});
this.update();
}
};
/**
* Unpins the header if it's currently pinned
*/
this.clear = function () {
if (this.state === 'clear') {
return;
}
this.state = 'clear';
var unpinnedClass = this.unPinnedClass;
var pinnedClass = this.pinnedClass;
for (var i = 0, length = this.elems.length; i < length; i++) {
var classList = this.elems[i].classList;
classList.remove(unpinnedClass);
//classList.remove(pinnedClass);
}
};
/**
* Unpins the header if it's currently pinned
*/
this.pin = function () {
if (this.state === 'pin') {
return;
}
this.state = 'pin';
var unpinnedClass = this.unPinnedClass;
var pinnedClass = this.pinnedClass;
for (var i = 0, length = this.elems.length; i < length; i++) {
var classList = this.elems[i].classList;
classList.remove(unpinnedClass);
classList.add(pinnedClass);
}
};
/**
* Unpins the header if it's currently pinned
*/
this.unpin = function () {
if (this.state === 'unpin') {
return;
}
this.state = 'unpin';
var unpinnedClass = this.unPinnedClass;
var pinnedClass = this.pinnedClass;
for (var i = 0, length = this.elems.length; i < length; i++) {
var classList = this.elems[i].classList;
classList.add(unpinnedClass);
//classList.remove(pinnedClass);
}
};
/**
* Gets the Y scroll position
* @see https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY
* @return {Number} pixels the page has scrolled along the Y-axis
*/
this.getScrollY = function () {
var scroller = this.scroller;
if (scroller.getScrollPosition) {
return scroller.getScrollPosition();
}
var pageYOffset = scroller.pageYOffset;
if (pageYOffset !== undefined) {
return pageYOffset;
}
var scrollTop = scroller.scrollTop;
if (scrollTop !== undefined) {
return scrollTop;
}
return (document.documentElement || document.body).scrollTop;
};
/**
* determine if it is appropriate to unpin
* @param {int} currentScrollY the current y scroll position
* @return {bool} true if should unpin, false otherwise
*/
this.shouldUnpin = function (currentScrollY) {
var scrollingDown = currentScrollY > this.lastKnownScrollY;
var pastOffset = currentScrollY >= this.offset;
return scrollingDown && pastOffset;
};
/**
* determine if it is appropriate to pin
* @param {int} currentScrollY the current y scroll position
* @return {bool} true if should pin, false otherwise
*/
this.shouldPin = function (currentScrollY) {
var scrollingUp = currentScrollY < this.lastKnownScrollY;
var pastOffset = currentScrollY <= this.offset;
return scrollingUp || pastOffset;
};
/**
* Handles updating the state of the widget
*/
this.update = function () {
if (this.paused) {
return;
}
var currentScrollY = this.getScrollY();
var lastKnownScrollY = this.lastKnownScrollY;
var isTv = layoutManager.tv;
if (currentScrollY <= (isTv ? 120 : 10)) {
this.clear();
} else if (this.shouldUnpin(currentScrollY)) {
this.unpin();
} else if (this.shouldPin(currentScrollY)) {
var toleranceExceeded = Math.abs(currentScrollY - lastKnownScrollY) >= 14;
if (currentScrollY && isTv) {
this.unpin();
} else if (toleranceExceeded) {
this.clear();
}
} else if (isTv) {
//this.clear();
}
this.lastKnownScrollY = currentScrollY;
};
if (browser.supportsCssAnimation()) {
for (var i = 0, length = this.elems.length; i < length; i++) {
this.elems[i].classList.add(this.initialClass);
this.elems[i].addEventListener('clearheadroom', onHeadroomClearedExternally.bind(this));
}
this.attachEvent();
}
}
function onScroll() {
if (this.paused) {
return;
}
requestAnimationFrame(this.rafCallback || (this.rafCallback = this.update.bind(this)));
}
/**
* Default options
* @type {Object}
*/
Headroom.options = {
offset: 0,
scroller: window,
initialClass: 'headroom',
unPinnedClass: 'headroom--unpinned',
pinnedClass: 'headroom--pinned'
};
return Headroom;
});

View file

@ -1,5 +1,5 @@
define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loading', 'connectionManager', 'homeSections', 'dom', 'events', 'listViewStyle', 'emby-select', 'emby-checkbox'], function (require, appHost, layoutManager, focusManager, globalize, loading, connectionManager, homeSections, dom, events) {
"use strict";
'use strict';
var numConfigurableSections = 7;
@ -149,7 +149,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
currentHtml += '<div class="listItem viewItem" data-viewid="' + view.Id + '">';
currentHtml += '<i class="material-icons listItemIcon folder_open"></i>';
currentHtml += '<span class="material-icons listItemIcon folder_open"></span>';
currentHtml += '<div class="listItemBody">';
@ -159,8 +159,8 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
currentHtml += '</div>';
currentHtml += '<button type="button" is="paper-icon-button-light" class="btnViewItemUp btnViewItemMove autoSize" title="' + globalize.translate('Up') + '"><i class="material-icons keyboard_arrow_up"></i></button>';
currentHtml += '<button type="button" is="paper-icon-button-light" class="btnViewItemDown btnViewItemMove autoSize" title="' + globalize.translate('Down') + '"><i class="material-icons keyboard_arrow_down"></i></button>';
currentHtml += '<button type="button" is="paper-icon-button-light" class="btnViewItemUp btnViewItemMove autoSize" title="' + globalize.translate('Up') + '"><span class="material-icons keyboard_arrow_up"></span></button>';
currentHtml += '<button type="button" is="paper-icon-button-light" class="btnViewItemDown btnViewItemMove autoSize" title="' + globalize.translate('Down') + '"><span class="material-icons keyboard_arrow_down"></span></button>';
currentHtml += '</div>';
@ -276,7 +276,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
updateHomeSectionValues(context, userSettings);
var promise1 = apiClient.getUserViews({ IncludeHidden: true }, user.Id);
var promise2 = apiClient.getJSON(apiClient.getUrl("Users/" + user.Id + "/GroupingOptions"));
var promise2 = apiClient.getJSON(apiClient.getUrl('Users/' + user.Id + '/GroupingOptions'));
Promise.all([promise1, promise2]).then(function (responses) {
@ -363,17 +363,17 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
user.Configuration.HidePlayedInLatest = context.querySelector('.chkHidePlayedFromLatest').checked;
user.Configuration.LatestItemsExcludes = getCheckboxItems(".chkIncludeInLatest", context, false).map(function (i) {
user.Configuration.LatestItemsExcludes = getCheckboxItems('.chkIncludeInLatest', context, false).map(function (i) {
return i.getAttribute('data-folderid');
});
user.Configuration.MyMediaExcludes = getCheckboxItems(".chkIncludeInMyMedia", context, false).map(function (i) {
user.Configuration.MyMediaExcludes = getCheckboxItems('.chkIncludeInMyMedia', context, false).map(function (i) {
return i.getAttribute('data-folderid');
});
user.Configuration.GroupedFolders = getCheckboxItems(".chkGroupFolder", context, true).map(function (i) {
user.Configuration.GroupedFolders = getCheckboxItems('.chkGroupFolder', context, true).map(function (i) {
return i.getAttribute('data-folderid');
});

View file

@ -10,6 +10,13 @@
<div class="fieldDescription">${LabelPleaseRestart}</div>
</div>
<div class="verticalSection verticalSection-extrabottompadding">
<label class="checkboxContainer">
<input class="chkHidePlayedFromLatest" type="checkbox" is="emby-checkbox" />
<span>${HideWatchedContentFromLatestMedia}</span>
</label>
</div>
<div class="selectContainer">
<select is="emby-select" id="selectHomeSection1" label="{section1label}">
<option value="smalllibrarytiles">${HeaderMyMedia}</option>
@ -110,13 +117,6 @@
<div class="perLibrarySettings"></div>
<div class="verticalSection verticalSection-extrabottompadding">
<label class="checkboxContainer">
<input class="chkHidePlayedFromLatest" type="checkbox" is="emby-checkbox" />
<span>${HideWatchedContentFromLatestMedia}</span>
</label>
</div>
<div class="verticalSection verticalSection-extrabottompadding">
<h2 class="sectionTitle">${HeaderLibraryFolders}</h2>
<div>

View file

@ -64,21 +64,21 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
} else {
var noLibDescription;
if (user['Policy'] && user['Policy']['IsAdministrator']) {
noLibDescription = Globalize.translate("NoCreatedLibraries", '<a id="button-createLibrary" class="button-link">', '</a>');
noLibDescription = globalize.translate('NoCreatedLibraries', '<br><a id="button-createLibrary" class="button-link">', '</a>');
} else {
noLibDescription = Globalize.translate("AskAdminToCreateLibrary");
noLibDescription = globalize.translate('AskAdminToCreateLibrary');
}
html += '<div class="centerMessage padded-left padded-right">';
html += '<h2>' + Globalize.translate("MessageNothingHere") + '</h2>';
html += '<h2>' + globalize.translate('MessageNothingHere') + '</h2>';
html += '<p>' + noLibDescription + '</p>';
html += '</div>';
elem.innerHTML = html;
var createNowLink = elem.querySelector("#button-createLibrary");
var createNowLink = elem.querySelector('#button-createLibrary');
if (createNowLink) {
createNowLink.addEventListener("click", function () {
Dashboard.navigate("library.html");
createNowLink.addEventListener('click', function () {
Dashboard.navigate('library.html');
});
}
}
@ -172,7 +172,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
}
function getLibraryButtonsHtml(items) {
var html = "";
var html = '';
html += '<div class="verticalSection verticalSection-extrabottompadding">';
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderMyMedia') + '</h2>';
@ -183,7 +183,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
for (var i = 0, length = items.length; i < length; i++) {
var item = items[i];
var icon = imageHelper.getLibraryIcon(item.CollectionType);
html += '<a is="emby-linkbutton" href="' + appRouter.getRouteUrl(item) + '" class="raised homeLibraryButton"><i class="material-icons homeLibraryIcon ' + icon + '"></i><span class="homeLibraryText">' + item.Name + '</span></a>';
html += '<a is="emby-linkbutton" href="' + appRouter.getRouteUrl(item) + '" class="raised homeLibraryButton"><span class="material-icons homeLibraryIcon ' + icon + '"></span><span class="homeLibraryText">' + item.Name + '</span></a>';
}
html += '</div>';
@ -229,9 +229,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
var options = {
Limit: limit,
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
ImageTypeLimit: 1,
EnableImageTypes: "Primary,Backdrop,Thumb",
EnableImageTypes: 'Primary,Backdrop,Thumb',
ParentId: parentId
};
@ -243,9 +243,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
return function (items) {
var cardLayout = false;
var shape;
if (itemType === 'Channel' || viewType === 'movies' || viewType === 'books') {
if (itemType === 'Channel' || viewType === 'movies' || viewType === 'books' || viewType === 'tvshows') {
shape = getPortraitShape();
} else if (viewType === 'music') {
} else if (viewType === 'music' || viewType === 'homevideos') {
shape = getSquareShape();
} else {
shape = getThumbShape();
@ -282,7 +282,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
html += '<h2 class="sectionTitle sectionTitle-cards">';
html += globalize.translate('LatestFromLibrary', parent.Name);
html += '</h2>';
html += '<i class="material-icons chevron_right"></i>';
html += '<span class="material-icons chevron_right"></span>';
html += '</a>';
} else {
html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate('LatestFromLibrary', parent.Name) + '</h2>';
@ -386,9 +386,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
var options = {
Limit: limit,
Recursive: true,
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
ImageTypeLimit: 1,
EnableImageTypes: "Primary,Backdrop,Thumb",
EnableImageTypes: 'Primary,Backdrop,Thumb',
EnableTotalRecordCount: false,
MediaTypes: 'Video'
};
@ -459,9 +459,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
var options = {
Limit: limit,
Recursive: true,
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
ImageTypeLimit: 1,
EnableImageTypes: "Primary,Backdrop,Thumb",
EnableImageTypes: 'Primary,Backdrop,Thumb',
EnableTotalRecordCount: false,
MediaTypes: 'Audio'
};
@ -524,9 +524,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
IsAiring: true,
limit: 24,
ImageTypeLimit: 1,
EnableImageTypes: "Primary,Thumb,Backdrop",
EnableImageTypes: 'Primary,Thumb,Backdrop',
EnableTotalRecordCount: false,
Fields: "ChannelInfo,PrimaryImageAspectRatio"
Fields: 'ChannelInfo,PrimaryImageAspectRatio'
});
};
}
@ -565,9 +565,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
IsAiring: true,
limit: 1,
ImageTypeLimit: 1,
EnableImageTypes: "Primary,Thumb,Backdrop",
EnableImageTypes: 'Primary,Thumb,Backdrop',
EnableTotalRecordCount: false,
Fields: "ChannelInfo,PrimaryImageAspectRatio"
Fields: 'ChannelInfo,PrimaryImageAspectRatio'
}).then(function (result) {
var html = '';
if (result.Items.length) {
@ -630,7 +630,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
html += '<h2 class="sectionTitle sectionTitle-cards">';
html += globalize.translate('HeaderOnNow');
html += '</h2>';
html += '<i class="material-icons chevron_right"></i>';
html += '<span class="material-icons chevron_right"></span>';
html += '</a>';
} else {
@ -667,10 +667,10 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
var apiClient = connectionManager.getApiClient(serverId);
return apiClient.getNextUpEpisodes({
Limit: enableScrollX() ? 24 : 15,
Fields: "PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo",
Fields: 'PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo',
UserId: apiClient.getCurrentUserId(),
ImageTypeLimit: 1,
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
EnableImageTypes: 'Primary,Backdrop,Banner,Thumb',
EnableTotalRecordCount: false
});
};
@ -705,7 +705,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
html += '<h2 class="sectionTitle sectionTitle-cards">';
html += globalize.translate('HeaderNextUp');
html += '</h2>';
html += '<i class="material-icons chevron_right"></i>';
html += '<span class="material-icons chevron_right"></span>';
html += '</a>';
} else {
html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate('HeaderNextUp') + '</h2>';
@ -739,7 +739,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
return apiClient.getLiveTvRecordings({
userId: apiClient.getCurrentUserId(),
Limit: enableScrollX() ? 12 : 5,
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
EnableTotalRecordCount: false,
IsLibraryItem: activeRecordingsOnly ? null : false,
IsInProgress: activeRecordingsOnly ? true : null

View file

@ -2,12 +2,12 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
'use strict';
function getSavedVolume() {
return appSettings.get("volume") || 1;
return appSettings.get('volume') || 1;
}
function saveVolume(value) {
if (value) {
appSettings.set("volume", value);
appSettings.set('volume', value);
}
}
@ -109,7 +109,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
var now = Date.now();
if (window.performance && window.performance.now) {
now = performance.now();
now = performance.now(); // eslint-disable-line compat/compat
}
if (!recoverDecodingErrorDate || (now - recoverDecodingErrorDate) > 3000) {
@ -162,7 +162,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
}
}
function seekOnPlaybackStart(instance, element, ticks) {
function seekOnPlaybackStart(instance, element, ticks, onMediaReady) {
var seconds = (ticks || 0) / 10000000;
@ -175,9 +175,10 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
if (element.duration >= seconds) {
// media is ready, seek immediately
setCurrentTimeIfNeeded(element, seconds);
if (onMediaReady) onMediaReady();
} else {
// update video player position when media is ready to be sought
var events = ["durationchange", "loadeddata", "play", "loadedmetadata"];
var events = ['durationchange', 'loadeddata', 'play', 'loadedmetadata'];
var onMediaChange = function(e) {
if (element.currentTime === 0 && element.duration >= seconds) {
// seek only when video position is exactly zero,
@ -189,6 +190,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
events.map(function(name) {
element.removeEventListener(name, onMediaChange);
});
if (onMediaReady) onMediaReady();
}
};
events.map(function (name) {
@ -371,13 +373,13 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
onErrorInternal(instance, 'network');
}
} else {
console.debug("fatal network error encountered, try to recover");
console.debug('fatal network error encountered, try to recover');
hls.startLoad();
}
break;
case Hls.ErrorTypes.MEDIA_ERROR:
console.debug("fatal media error encountered, try to recover");
console.debug('fatal media error encountered, try to recover');
var currentReject = reject;
reject = null;
handleHlsJsMediaError(instance, currentReject);
@ -407,7 +409,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
elem.src = '';
elem.innerHTML = '';
elem.removeAttribute("src");
elem.removeAttribute('src');
destroyHlsPlayer(instance);
destroyFlvPlayer(instance);

View file

@ -1,5 +1,5 @@
define(['events', 'browser', 'require', 'apphost', 'appSettings', 'htmlMediaHelper'], function (events, browser, require, appHost, appSettings, htmlMediaHelper) {
"use strict";
'use strict';
function getDefaultProfile() {
return new Promise(function (resolve, reject) {

View file

@ -1,5 +1,5 @@
define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackManager', 'appRouter', 'appSettings', 'connectionManager', 'htmlMediaHelper', 'itemHelper', 'fullscreenManager', 'globalize'], function (browser, require, events, appHost, loading, dom, playbackManager, appRouter, appSettings, connectionManager, htmlMediaHelper, itemHelper, fullscreenManager, globalize) {
"use strict";
define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackManager', 'appRouter', 'appSettings', 'connectionManager', 'htmlMediaHelper', 'itemHelper', 'screenfull', 'globalize'], function (browser, require, events, appHost, loading, dom, playbackManager, appRouter, appSettings, connectionManager, htmlMediaHelper, itemHelper, screenfull, globalize) {
'use strict';
/* globals cast */
var mediaManager;
@ -212,7 +212,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
function incrementFetchQueue() {
if (self._fetchQueue <= 0) {
self.isFetching = true;
events.trigger(self, "beginFetch");
events.trigger(self, 'beginFetch');
}
self._fetchQueue++;
@ -223,7 +223,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
if (self._fetchQueue <= 0) {
self.isFetching = false;
events.trigger(self, "endFetch");
events.trigger(self, 'endFetch');
}
}
@ -466,7 +466,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
console.debug('content type: ' + contentType);
host.onError = function (errorCode) {
console.error("fatal Error - " + errorCode);
console.error('fatal Error - ' + errorCode);
};
mediaElement.autoplay = false;
@ -600,8 +600,9 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
var offsetValue = parseFloat(offset);
// if .ass currently rendering
if (currentAssRenderer) {
if (currentSubtitlesOctopus) {
updateCurrentTrackOffset(offsetValue);
currentSubtitlesOctopus.timeOffset = (self._currentPlayOptions.transcodingOffsetTicks || 0) / 10000000 + offsetValue;
} else {
var trackElement = getTextTrack();
// if .vtt currently rendering
@ -610,7 +611,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
} else if (currentTrackEvents) {
setTrackEventsSubtitleOffset(currentTrackEvents, offsetValue);
} else {
console.debug("No available track, cannot apply offset: ", offsetValue);
console.debug('No available track, cannot apply offset: ', offsetValue);
}
}
};
@ -794,7 +795,9 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
dlg.parentNode.removeChild(dlg);
}
fullscreenManager.exitFullscreen();
if (screenfull.isEnabled) {
screenfull.exit();
}
};
function onEnded() {
@ -856,7 +859,13 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
loading.hide();
htmlMediaHelper.seekOnPlaybackStart(self, e.target, self._currentPlayOptions.playerStartPositionTicks);
htmlMediaHelper.seekOnPlaybackStart(self, e.target, self._currentPlayOptions.playerStartPositionTicks, function () {
if (currentSubtitlesOctopus) {
currentSubtitlesOctopus.timeOffset = (self._currentPlayOptions.transcodingOffsetTicks || 0) / 10000000 + currentTrackOffset;
currentSubtitlesOctopus.resize();
currentSubtitlesOctopus.resetRenderAheadCache(false);
}
});
if (self._currentPlayOptions.fullscreen) {
@ -1056,11 +1065,12 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
fonts: attachments.map(function (i) {
return apiClient.getUrl(i.DeliveryUrl);
}),
workerUrl: appRouter.baseUrl() + "/libraries/subtitles-octopus-worker.js",
legacyWorkerUrl: appRouter.baseUrl() + "/libraries/subtitles-octopus-worker-legacy.js",
workerUrl: appRouter.baseUrl() + '/libraries/subtitles-octopus-worker.js',
legacyWorkerUrl: appRouter.baseUrl() + '/libraries/subtitles-octopus-worker-legacy.js',
onError: function() {
htmlMediaHelper.onErrorInternal(self, 'mediadecodeerror');
},
timeOffset: (self._currentPlayOptions.transcodingOffsetTicks || 0) / 10000000,
// new octopus options; override all, even defaults
renderMode: 'blend',
@ -1220,11 +1230,6 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
function updateSubtitleText(timeMs) {
// handle offset for ass tracks
if (currentTrackOffset) {
timeMs += (currentTrackOffset * 1000);
}
var clock = currentClock;
if (clock) {
try {
@ -1412,12 +1417,12 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
var list = [];
var video = document.createElement('video');
if (video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === "function" || document.pictureInPictureEnabled) {
if (video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === 'function' || document.pictureInPictureEnabled) {
list.push('PictureInPicture');
} else if (browser.ipad) {
// Unfortunately this creates a false positive on devices where its' not actually supported
if (navigator.userAgent.toLowerCase().indexOf('os 9') === -1) {
if (video.webkitSupportsPresentationMode && video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === "function") {
if (video.webkitSupportsPresentationMode && video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === 'function') {
list.push('PictureInPicture');
}
}
@ -1432,7 +1437,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
}
list.push('SetBrightness');
list.push("SetAspectRatio");
list.push('SetAspectRatio');
return list;
}
@ -1517,8 +1522,8 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
Windows.UI.ViewManagement.ApplicationView.getForCurrentView().tryEnterViewModeAsync(Windows.UI.ViewManagement.ApplicationViewMode.default);
}
} else {
if (video && video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === "function") {
video.webkitSetPresentationMode(isEnabled ? "picture-in-picture" : "inline");
if (video && video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === 'function') {
video.webkitSetPresentationMode(isEnabled ? 'picture-in-picture' : 'inline');
}
}
};
@ -1532,7 +1537,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
} else {
var video = this._mediaElement;
if (video) {
return video.webkitPresentationMode === "picture-in-picture";
return video.webkitPresentationMode === 'picture-in-picture';
}
}
@ -1555,11 +1560,11 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
if (video) {
if (isEnabled) {
video.requestAirPlay().catch(function(err) {
console.error("Error requesting AirPlay", err);
console.error('Error requesting AirPlay', err);
});
} else {
document.exitAirPLay().catch(function(err) {
console.error("Error exiting AirPlay", err);
console.error('Error exiting AirPlay', err);
});
}
}
@ -1691,29 +1696,29 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
HtmlVideoPlayer.prototype.setAspectRatio = function (val) {
var mediaElement = this._mediaElement;
if (mediaElement) {
if ("auto" === val) {
mediaElement.style.removeProperty("object-fit");
if ('auto' === val) {
mediaElement.style.removeProperty('object-fit');
} else {
mediaElement.style["object-fit"] = val;
mediaElement.style['object-fit'] = val;
}
}
this._currentAspectRatio = val;
};
HtmlVideoPlayer.prototype.getAspectRatio = function () {
return this._currentAspectRatio || "auto";
return this._currentAspectRatio || 'auto';
};
HtmlVideoPlayer.prototype.getSupportedAspectRatios = function () {
return [{
name: "Auto",
id: "auto"
name: 'Auto',
id: 'auto'
}, {
name: "Cover",
id: "cover"
name: 'Cover',
id: 'cover'
}, {
name: "Fill",
id: "fill"
name: 'Fill',
id: 'fill'
}];
};
@ -1762,7 +1767,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
if (protocol) {
mediaCategory.stats.push({
label: globalize.translate("LabelProtocol"),
label: globalize.translate('LabelProtocol'),
value: protocol
});
}
@ -1772,12 +1777,12 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
if (this._hlsPlayer || this._shakaPlayer) {
mediaCategory.stats.push({
label: globalize.translate("LabelStreamType"),
label: globalize.translate('LabelStreamType'),
value: 'HLS'
});
} else {
mediaCategory.stats.push({
label: globalize.translate("LabelStreamType"),
label: globalize.translate('LabelStreamType'),
value: 'Video'
});
}
@ -1795,7 +1800,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
// Don't show player dimensions on smart TVs because the app UI could be lower resolution than the video and this causes users to think there is a problem
if (width && height && !browser.tv) {
videoCategory.stats.push({
label: globalize.translate("LabelPlayerDimensions"),
label: globalize.translate('LabelPlayerDimensions'),
value: width + 'x' + height
});
}
@ -1805,7 +1810,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
if (width && height) {
videoCategory.stats.push({
label: globalize.translate("LabelVideoResolution"),
label: globalize.translate('LabelVideoResolution'),
value: width + 'x' + height
});
}
@ -1815,13 +1820,13 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa
var droppedVideoFrames = playbackQuality.droppedVideoFrames || 0;
videoCategory.stats.push({
label: globalize.translate("LabelDroppedFrames"),
label: globalize.translate('LabelDroppedFrames'),
value: droppedVideoFrames
});
var corruptedVideoFrames = playbackQuality.corruptedVideoFrames || 0;
videoCategory.stats.push({
label: globalize.translate("LabelCorruptedFrames"),
label: globalize.translate('LabelCorruptedFrames'),
value: corruptedVideoFrames
});
}

View file

@ -109,15 +109,15 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
html += '<span style="margin-right: 10px;">';
var startAtDisplay = totalRecordCount ? startIndex + 1 : 0;
html += globalize.translate("ListPaging", startAtDisplay, recordsEnd, totalRecordCount);
html += globalize.translate('ListPaging', startAtDisplay, recordsEnd, totalRecordCount);
html += '</span>';
if (showControls) {
html += '<div data-role="controlgroup" data-type="horizontal" style="display:inline-block;">';
html += '<button is="paper-icon-button-light" title="' + globalize.translate('Previous') + '" class="btnPreviousPage autoSize" ' + (startIndex ? '' : 'disabled') + '><i class="material-icons arrow_back"></i></button>';
html += '<button is="paper-icon-button-light" title="' + globalize.translate('Next') + '" class="btnNextPage autoSize" ' + (startIndex + limit >= totalRecordCount ? 'disabled' : '') + '><i class="material-icons arrow_forward"></i></button>';
html += '<button is="paper-icon-button-light" title="' + globalize.translate('Previous') + '" class="btnPreviousPage autoSize" ' + (startIndex ? '' : 'disabled') + '><span class="material-icons arrow_back"></span></button>';
html += '<button is="paper-icon-button-light" title="' + globalize.translate('Next') + '" class="btnNextPage autoSize" ' + (startIndex + limit >= totalRecordCount ? 'disabled' : '') + '><span class="material-icons arrow_forward"></span></button>';
html += '</div>';
}
@ -144,7 +144,7 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
}
function getDisplayUrl(url, apiClient) {
return apiClient.getUrl("Images/Remote", { imageUrl: url });
return apiClient.getUrl('Images/Remote', { imageUrl: url });
}
function getRemoteImageHtml(image, imageType, apiClient) {
@ -155,21 +155,21 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
var html = '';
var cssClass = "card scalableCard imageEditorCard";
var cssClass = 'card scalableCard imageEditorCard';
var cardBoxCssClass = 'cardBox visualCardBox';
var shape = 'backdrop';
if (imageType === "Backdrop" || imageType === "Art" || imageType === "Thumb" || imageType === "Logo") {
if (imageType === 'Backdrop' || imageType === 'Art' || imageType === 'Thumb' || imageType === 'Logo') {
shape = 'backdrop';
} else if (imageType === "Banner") {
} else if (imageType === 'Banner') {
shape = 'banner';
} else if (imageType === "Disc") {
} else if (imageType === 'Disc') {
shape = 'square';
} else {
if (currentItemType === "Episode") {
if (currentItemType === 'Episode') {
shape = 'backdrop';
} else if (currentItemType === "MusicAlbum" || currentItemType === "MusicArtist") {
} else if (currentItemType === 'MusicAlbum' || currentItemType === 'MusicArtist') {
shape = 'square';
} else {
shape = 'portrait';
@ -241,18 +241,18 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
html += '<div class="cardText cardText-secondary cardTextCentered">';
if (image.RatingType === "Likes") {
html += image.CommunityRating + (image.CommunityRating === 1 ? " like" : " likes");
if (image.RatingType === 'Likes') {
html += image.CommunityRating + (image.CommunityRating === 1 ? ' like' : ' likes');
} else {
if (image.CommunityRating) {
html += image.CommunityRating.toFixed(1);
if (image.VoteCount) {
html += ' • ' + image.VoteCount + (image.VoteCount === 1 ? " vote" : " votes");
html += ' • ' + image.VoteCount + (image.VoteCount === 1 ? ' vote' : ' votes');
}
} else {
html += "Unrated";
html += 'Unrated';
}
}
@ -262,7 +262,7 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
if (enableFooterButtons) {
html += '<div class="cardText cardTextCentered">';
html += '<button is="paper-icon-button-light" class="btnDownloadRemoteImage autoSize" raised" title="' + globalize.translate('Download') + '"><i class="material-icons cloud_download"></i></button>';
html += '<button is="paper-icon-button-light" class="btnDownloadRemoteImage autoSize" raised" title="' + globalize.translate('Download') + '"><span class="material-icons cloud_download"></span></button>';
html += '</div>';
}

View file

@ -1,5 +1,5 @@
<div class="formDialogHeader">
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><i class="material-icons arrow_back"></i></button>
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>
<h3 class="formDialogHeaderTitle">
${Search}
</h3>

View file

@ -99,10 +99,10 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
var html = '';
var cssClass = "card scalableCard imageEditorCard";
var cssClass = 'card scalableCard imageEditorCard';
var cardBoxCssClass = 'cardBox visualCardBox';
cssClass += " backdropCard backdropCard-scalable";
cssClass += ' backdropCard backdropCard-scalable';
if (tagName === 'button') {
cssClass += ' btnImageCard';
@ -152,26 +152,26 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
if (enableFooterButtons) {
html += '<div class="cardText cardTextCentered">';
if (image.ImageType === "Backdrop" || image.ImageType === "Screenshot") {
if (image.ImageType === 'Backdrop' || image.ImageType === 'Screenshot') {
if (index > 0) {
html += '<button type="button" is="paper-icon-button-light" class="btnMoveImage autoSize" data-imagetype="' + image.ImageType + '" data-index="' + image.ImageIndex + '" data-newindex="' + (image.ImageIndex - 1) + '" title="' + globalize.translate('MoveLeft') + '"><i class="material-icons chevron_left"></i></button>';
html += '<button type="button" is="paper-icon-button-light" class="btnMoveImage autoSize" data-imagetype="' + image.ImageType + '" data-index="' + image.ImageIndex + '" data-newindex="' + (image.ImageIndex - 1) + '" title="' + globalize.translate('MoveLeft') + '"><span class="material-icons chevron_left"></span></button>';
} else {
html += '<button type="button" is="paper-icon-button-light" class="autoSize" disabled title="' + globalize.translate('MoveLeft') + '"><i class="material-icons chevron_left"></i></button>';
html += '<button type="button" is="paper-icon-button-light" class="autoSize" disabled title="' + globalize.translate('MoveLeft') + '"><span class="material-icons chevron_left"></span></button>';
}
if (index < numImages - 1) {
html += '<button type="button" is="paper-icon-button-light" class="btnMoveImage autoSize" data-imagetype="' + image.ImageType + '" data-index="' + image.ImageIndex + '" data-newindex="' + (image.ImageIndex + 1) + '" title="' + globalize.translate('MoveRight') + '"><i class="material-icons chevron_right"></i></button>';
html += '<button type="button" is="paper-icon-button-light" class="btnMoveImage autoSize" data-imagetype="' + image.ImageType + '" data-index="' + image.ImageIndex + '" data-newindex="' + (image.ImageIndex + 1) + '" title="' + globalize.translate('MoveRight') + '"><span class="material-icons chevron_right"></span></button>';
} else {
html += '<button type="button" is="paper-icon-button-light" class="autoSize" disabled title="' + globalize.translate('MoveRight') + '"><i class="material-icons chevron_right"></i></button>';
html += '<button type="button" is="paper-icon-button-light" class="autoSize" disabled title="' + globalize.translate('MoveRight') + '"><span class="material-icons chevron_right"></span></button>';
}
} else {
if (imageProviders.length) {
html += '<button type="button" is="paper-icon-button-light" data-imagetype="' + image.ImageType + '" class="btnSearchImages autoSize" title="' + globalize.translate('Search') + '"><i class="material-icons">search</i></button>';
html += '<button type="button" is="paper-icon-button-light" data-imagetype="' + image.ImageType + '" class="btnSearchImages autoSize" title="' + globalize.translate('Search') + '"><span class="material-icons search"></span></button>';
}
}
html += '<button type="button" is="paper-icon-button-light" data-imagetype="' + image.ImageType + '" data-index="' + (image.ImageIndex != null ? image.ImageIndex : "null") + '" class="btnDeleteImage autoSize" title="' + globalize.translate('Delete') + '"><i class="material-icons">delete</i></button>';
html += '<button type="button" is="paper-icon-button-light" data-imagetype="' + image.ImageType + '" data-index="' + (image.ImageIndex != null ? image.ImageIndex : 'null') + '" class="btnDeleteImage autoSize" title="' + globalize.translate('Delete') + '"><span class="material-icons delete"></span></button>';
html += '</div>';
}
@ -251,7 +251,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
function renderStandardImages(page, apiClient, item, imageInfos, imageProviders) {
var images = imageInfos.filter(function (i) {
return i.ImageType !== "Screenshot" && i.ImageType !== "Backdrop" && i.ImageType !== "Chapter";
return i.ImageType !== 'Screenshot' && i.ImageType !== 'Backdrop' && i.ImageType !== 'Chapter';
});
renderImages(page, item, apiClient, images, imageProviders, page.querySelector('#images'));
@ -260,7 +260,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
function renderBackdrops(page, apiClient, item, imageInfos, imageProviders) {
var images = imageInfos.filter(function (i) {
return i.ImageType === "Backdrop";
return i.ImageType === 'Backdrop';
}).sort(function (a, b) {
return a.ImageIndex - b.ImageIndex;
@ -277,7 +277,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
function renderScreenshots(page, apiClient, item, imageInfos, imageProviders) {
var images = imageInfos.filter(function (i) {
return i.ImageType === "Screenshot";
return i.ImageType === 'Screenshot';
}).sort(function (a, b) {
return a.ImageIndex - b.ImageIndex;
@ -425,7 +425,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
addListeners(context, 'btnDeleteImage', 'click', function () {
var type = this.getAttribute('data-imagetype');
var index = this.getAttribute('data-index');
index = index === "null" ? null : parseInt(index);
index = index === 'null' ? null : parseInt(index);
var apiClient = connectionManager.getApiClient(currentItem.ServerId);
deleteImage(context, currentItem.Id, type, index, apiClient, true);
});

View file

@ -1,5 +1,5 @@
<div class="formDialogHeader">
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><i class="material-icons arrow_back"></i></button>
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>
<h3 class="formDialogHeaderTitle">
${HeaderEditImages}
</h3>
@ -12,10 +12,10 @@
<div class="imageEditor-buttons first-imageEditor-buttons">
<h2 style="margin:0;">${Images}</h2>
<button type="button" is="emby-button" class="btnBrowseAllImages fab mini autoSize" style="margin-left: 1em;">
<i class="material-icons">search</i>
<span class="material-icons search"></span>
</button>
<button type="button" is="emby-button" class="btnOpenUploadMenu fab mini hide" style="margin-left: .5em;">
<i class="material-icons">add</i>
<span class="material-icons add"></span>
</button>
</div>
<div id="images" class="itemsContainer vertical-wrap">
@ -27,10 +27,10 @@
<div class="imageEditor-buttons">
<h2 style="margin:0;">${Backdrops}</h2>
<button type="button" is="emby-button" class="btnBrowseAllImages fab mini autoSize" style="margin-left: 1em;" data-imagetype="Backdrop">
<i class="material-icons">search</i>
<span class="material-icons search"></span>
</button>
<button type="button" is="emby-button" class="btnOpenUploadMenu fab mini hide" style="margin-left: .5em;" data-imagetype="Backdrop">
<i class="material-icons">add</i>
<span class="material-icons add"></span>
</button>
</div>
<div id="backdrops" class="itemsContainer vertical-wrap">
@ -42,10 +42,10 @@
<div class="imageEditor-buttons">
<h2 style="margin: 0;">${Screenshots}</h2>
<button type="button" is="emby-button" class="btnBrowseAllImages fab mini autoSize" style="margin-left: 1em;" data-imagetype="Screenshot">
<i class="material-icons">search</i>
<span class="material-icons search"></span>
</button>
<button type="button" is="emby-button" class="btnOpenUploadMenu fab mini hide" style="margin-left: .5em;" data-imagetype="Screenshot">
<i class="material-icons">add</i>
<span class="material-icons add"></span>
</button>
</div>
<div id="screenshots" class="itemsContainer vertical-wrap">

View file

@ -1,11 +1,11 @@
define(["globalize", "dom", "dialogHelper", "emby-checkbox", "emby-select", "emby-input"], function (globalize, dom, dialogHelper) {
"use strict";
define(['globalize', 'dom', 'dialogHelper', 'emby-checkbox', 'emby-select', 'emby-input'], function (globalize, dom, dialogHelper) {
'use strict';
function getDefaultImageConfig(itemType, type) {
return {
Type: type,
MinWidth: 0,
Limit: "Primary" === type ? 1 : 0
Limit: 'Primary' === type ? 1 : 0
};
}
@ -21,27 +21,27 @@ define(["globalize", "dom", "dialogHelper", "emby-checkbox", "emby-select", "emb
function setVisibilityOfBackdrops(elem, visible) {
if (visible) {
elem.classList.remove("hide");
elem.querySelector("input").setAttribute("required", "required");
elem.classList.remove('hide');
elem.querySelector('input').setAttribute('required', 'required');
} else {
elem.classList.add("hide");
elem.querySelector("input").setAttribute("required", "");
elem.querySelector("input").removeAttribute("required");
elem.classList.add('hide');
elem.querySelector('input').setAttribute('required', '');
elem.querySelector('input').removeAttribute('required');
}
}
function loadValues(context, itemType, options, availableOptions) {
var supportedImageTypes = availableOptions.SupportedImageTypes || [];
setVisibilityOfBackdrops(context.querySelector(".backdropFields"), -1 != supportedImageTypes.indexOf("Backdrop"));
setVisibilityOfBackdrops(context.querySelector(".screenshotFields"), -1 != supportedImageTypes.indexOf("Screenshot"));
Array.prototype.forEach.call(context.querySelectorAll(".imageType"), function (i) {
var imageType = i.getAttribute("data-imagetype");
var container = dom.parentWithTag(i, "LABEL");
setVisibilityOfBackdrops(context.querySelector('.backdropFields'), -1 != supportedImageTypes.indexOf('Backdrop'));
setVisibilityOfBackdrops(context.querySelector('.screenshotFields'), -1 != supportedImageTypes.indexOf('Screenshot'));
Array.prototype.forEach.call(context.querySelectorAll('.imageType'), function (i) {
var imageType = i.getAttribute('data-imagetype');
var container = dom.parentWithTag(i, 'LABEL');
if (-1 == supportedImageTypes.indexOf(imageType)) {
container.classList.add("hide");
container.classList.add('hide');
} else {
container.classList.remove("hide");
container.classList.remove('hide');
}
if (getImageConfig(options, availableOptions, imageType, itemType).Limit) {
@ -50,31 +50,31 @@ define(["globalize", "dom", "dialogHelper", "emby-checkbox", "emby-select", "emb
i.checked = false;
}
});
var backdropConfig = getImageConfig(options, availableOptions, "Backdrop", itemType);
context.querySelector("#txtMaxBackdrops").value = backdropConfig.Limit;
context.querySelector("#txtMinBackdropDownloadWidth").value = backdropConfig.MinWidth;
var screenshotConfig = getImageConfig(options, availableOptions, "Screenshot", itemType);
context.querySelector("#txtMaxScreenshots").value = screenshotConfig.Limit;
context.querySelector("#txtMinScreenshotDownloadWidth").value = screenshotConfig.MinWidth;
var backdropConfig = getImageConfig(options, availableOptions, 'Backdrop', itemType);
context.querySelector('#txtMaxBackdrops').value = backdropConfig.Limit;
context.querySelector('#txtMinBackdropDownloadWidth').value = backdropConfig.MinWidth;
var screenshotConfig = getImageConfig(options, availableOptions, 'Screenshot', itemType);
context.querySelector('#txtMaxScreenshots').value = screenshotConfig.Limit;
context.querySelector('#txtMinScreenshotDownloadWidth').value = screenshotConfig.MinWidth;
}
function saveValues(context, options) {
options.ImageOptions = Array.prototype.map.call(context.querySelectorAll(".imageType:not(.hide)"), function (c) {
options.ImageOptions = Array.prototype.map.call(context.querySelectorAll('.imageType:not(.hide)'), function (c) {
return {
Type: c.getAttribute("data-imagetype"),
Type: c.getAttribute('data-imagetype'),
Limit: c.checked ? 1 : 0,
MinWidth: 0
};
});
options.ImageOptions.push({
Type: "Backdrop",
Limit: context.querySelector("#txtMaxBackdrops").value,
MinWidth: context.querySelector("#txtMinBackdropDownloadWidth").value
Type: 'Backdrop',
Limit: context.querySelector('#txtMaxBackdrops').value,
MinWidth: context.querySelector('#txtMinBackdropDownloadWidth').value
});
options.ImageOptions.push({
Type: "Screenshot",
Limit: context.querySelector("#txtMaxScreenshots").value,
MinWidth: context.querySelector("#txtMinScreenshotDownloadWidth").value
Type: 'Screenshot',
Limit: context.querySelector('#txtMaxScreenshots').value,
MinWidth: context.querySelector('#txtMinScreenshotDownloadWidth').value
});
}
@ -82,23 +82,23 @@ define(["globalize", "dom", "dialogHelper", "emby-checkbox", "emby-select", "emb
this.show = function (itemType, options, availableOptions) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open("GET", "components/imageoptionseditor/imageoptionseditor.template.html", true);
xhr.open('GET', 'components/imageoptionseditor/imageoptionseditor.template.html', true);
xhr.onload = function (e) {
var template = this.response;
var dlg = dialogHelper.createDialog({
size: "medium-tall",
size: 'medium-tall',
removeOnClose: true,
scrollY: false
});
dlg.classList.add("formDialog");
dlg.classList.add('formDialog');
dlg.innerHTML = globalize.translateDocument(template);
dlg.addEventListener("close", function () {
dlg.addEventListener('close', function () {
saveValues(dlg, options);
});
loadValues(dlg, itemType, options, availableOptions);
dialogHelper.open(dlg).then(resolve, resolve);
dlg.querySelector(".btnCancel").addEventListener("click", function () {
dlg.querySelector('.btnCancel').addEventListener('click', function () {
dialogHelper.close(dlg);
});
};

View file

@ -1,5 +1,5 @@
<div class="formDialogHeader">
<button type="button" is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><i class="material-icons arrow_back"></i></button>
<button type="button" is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>
<h3 class="formDialogHeaderTitle">
${HeaderImageOptions}
</h3>

View file

@ -7,7 +7,7 @@ define(['dom'], function (dom) {
return Promise.reject('elem cannot be null');
}
if (elem.tagName !== "IMG") {
if (elem.tagName !== 'IMG') {
elem.style.backgroundImage = "url('" + url + "')";
return Promise.resolve();
@ -27,7 +27,7 @@ define(['dom'], function (dom) {
dom.addEventListener(elem, 'load', resolve, {
once: true
});
elem.setAttribute("src", url);
elem.setAttribute('src', url);
});
}

View file

@ -1,50 +1,82 @@
define(['lazyLoader', 'imageFetcher', 'layoutManager', 'browser', 'appSettings', 'userSettings', 'require', 'css!./style'], function (lazyLoader, imageFetcher, layoutManager, browser, appSettings, userSettings, require) {
'use strict';
var self = {};
function fillImage(elem, source, enableEffects) {
if (!elem) {
throw new Error('elem cannot be null');
}
if (!source) {
source = elem.getAttribute('data-src');
}
import * as lazyLoader from 'lazyLoader';
import * as userSettings from 'userSettings';
import 'css!./style';
/* eslint-disable indent */
export function lazyImage(elem, source = elem.getAttribute('data-src')) {
if (!source) {
return;
}
fillImageElement(elem, source, enableEffects);
fillImageElement(elem, source);
}
function fillImageElement(elem, source, enableEffects) {
imageFetcher.loadImage(elem, source).then(function () {
export function fillImage(entry) {
if (!entry) {
throw new Error('entry cannot be null');
}
if (enableEffects !== false) {
fadeIn(elem);
}
elem.removeAttribute("data-src");
});
}
function fadeIn(elem) {
if (userSettings.enableFastFadein()) {
elem.classList.add('lazy-image-fadein-fast');
var source = undefined;
if (entry.target) {
source = entry.target.getAttribute('data-src');
} else {
elem.classList.add('lazy-image-fadein');
source = entry;
}
if (entry.intersectionRatio > 0) {
if (source) fillImageElement(entry.target, source);
} else if (!source) {
emptyImageElement(entry.target);
}
}
function lazyChildren(elem) {
function fillImageElement(elem, url) {
if (url === undefined) {
throw new Error('url cannot be undefined');
}
let preloaderImg = new Image();
preloaderImg.src = url;
preloaderImg.addEventListener('load', () => {
if (elem.tagName !== 'IMG') {
elem.style.backgroundImage = "url('" + url + "')";
} else {
elem.setAttribute('src', url);
}
if (userSettings.enableFastFadein()) {
elem.classList.add('lazy-image-fadein-fast');
} else {
elem.classList.add('lazy-image-fadein');
}
elem.removeAttribute('data-src');
});
}
function emptyImageElement(elem) {
var url;
if (elem.tagName !== 'IMG') {
url = elem.style.backgroundImage.slice(4, -1).replace(/"/g, '');
elem.style.backgroundImage = 'none';
} else {
url = elem.getAttribute('src');
elem.setAttribute('src', '');
}
elem.setAttribute('data-src', url);
elem.classList.remove('lazy-image-fadein-fast');
elem.classList.remove('lazy-image-fadein');
}
export function lazyChildren(elem) {
lazyLoader.lazyChildren(elem, fillImage);
}
function getPrimaryImageAspectRatio(items) {
export function getPrimaryImageAspectRatio(items) {
var values = [];
@ -104,7 +136,7 @@ define(['lazyLoader', 'imageFetcher', 'layoutManager', 'browser', 'appSettings',
return result;
}
function fillImages(elems) {
export function fillImages(elems) {
for (var i = 0, length = elems.length; i < length; i++) {
var elem = elems[0];
@ -112,10 +144,11 @@ define(['lazyLoader', 'imageFetcher', 'layoutManager', 'browser', 'appSettings',
}
}
self.fillImages = fillImages;
self.lazyImage = fillImage;
self.lazyChildren = lazyChildren;
self.getPrimaryImageAspectRatio = getPrimaryImageAspectRatio;
return self;
});
/* eslint-enable indent */
export default {
fillImages: fillImages,
fillImage: fillImage,
lazyImage: lazyImage,
lazyChildren: lazyChildren,
getPrimaryImageAspectRatio: getPrimaryImageAspectRatio
};

View file

@ -1,44 +1,13 @@
.lazy-image-fadein {
.cardImageContainer.lazy {
opacity: 0;
animation: lazy-image-fadein 330ms ease-in normal both;
-webkit-animation-duration: 0.8s;
-moz-animation-duration: 0.8s;
-o-animation-duration: 0.8s;
animation-duration: 0.8s;
-webkit-animation-name: popInAnimation;
-moz-animation-name: popInAnimation;
-o-animation-name: popInAnimation;
animation-name: popInAnimation;
-webkit-animation-fill-mode: forwards;
-moz-animation-fill-mode: forwards;
-o-animation-fill-mode: forwards;
animation-fill-mode: forwards;
-webkit-animation-timing-function: cubic-bezier(0, 0, 0.5, 1);
-moz-animation-timing-function: cubic-bezier(0, 0, 0.5, 1);
-o-animation-timing-function: cubic-bezier(0, 0, 0.5, 1);
animation-timing-function: cubic-bezier(0, 0, 0.5, 1);
}
.lazy-image-fadein-fast {
animation: lazy-image-fadein 160ms ease-in normal both;
.cardImageContainer.lazy.lazy-image-fadein {
opacity: 1;
transition: opacity 0.7s;
}
@keyframes lazy-image-fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes popInAnimation {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
.cardImageContainer.lazy.lazy-image-fadein-fast {
opacity: 1;
transition: opacity 0.2s;
}

View file

@ -74,7 +74,7 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
return false;
}
if (!file.type.startsWith("image/")) {
if (!file.type.startsWith('image/')) {
require(['toast'], function (toast) {
toast(globalize.translate('MessageImageFileTypeAllowed'));
});
@ -87,9 +87,9 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
var dlg = dom.parentWithClass(this, 'dialog');
var imageType = dlg.querySelector('#selectImageType').value;
if (imageType === "None") {
require(["toast"], function(toast) {
toast(globalize.translate("MessageImageTypeNotSelected"));
if (imageType === 'None') {
require(['toast'], function(toast) {
toast(globalize.translate('MessageImageTypeNotSelected'));
});
e.preventDefault();
return false;
@ -112,11 +112,11 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
page.querySelector('form').addEventListener('submit', onSubmit);
page.querySelector('#uploadImage').addEventListener("change", function () {
page.querySelector('#uploadImage').addEventListener('change', function () {
setFiles(page, this.files);
});
page.querySelector('.btnBrowse').addEventListener("click", function () {
page.querySelector('.btnBrowse').addEventListener('click', function () {
page.querySelector('#uploadImage').click();
});
}

View file

@ -1,5 +1,5 @@
<div class="formDialogHeader">
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><i class="material-icons arrow_back"></i></button>
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>
<h3 class="formDialogHeaderTitle">
${HeaderUploadImage}
</h3>
@ -14,7 +14,7 @@
<h2 style="margin:0;">${HeaderAddUpdateImage}</h2>
<button is="emby-button" type="button" class="raised raised-mini btnBrowse" style="margin-left:1.5em;">
<i class="material-icons">folder</i>
<span class="material-icons folder"></span>
<span>${Browse}</span>
</button>
</div>

View file

@ -1,4 +1,4 @@
define(['datetime', 'itemHelper', 'css!./indicators.css', 'material-icons'], function (datetime, itemHelper) {
define(['datetime', 'itemHelper', 'emby-progressbar', 'css!./indicators.css', 'material-icons'], function (datetime, itemHelper) {
'use strict';
function enableProgressIndicator(item) {
@ -44,7 +44,7 @@ define(['datetime', 'itemHelper', 'css!./indicators.css', 'material-icons'], fun
function getProgressBarHtml(item, options) {
var pct;
if (enableProgressIndicator(item) && item.Type !== "Recording") {
if (enableProgressIndicator(item) && item.Type !== 'Recording') {
var userData = options ? (options.userData || item.UserData) : item.UserData;
if (userData) {
pct = userData.PlayedPercentage;
@ -90,7 +90,7 @@ define(['datetime', 'itemHelper', 'css!./indicators.css', 'material-icons'], fun
}
if (userData.PlayedPercentage && userData.PlayedPercentage >= 100 || (userData.Played)) {
return '<div class="playedIndicator indicator"><i class="material-icons indicatorIcon">check</i></div>';
return '<div class="playedIndicator indicator"><span class="material-icons indicatorIcon check"></span></div>';
}
}
@ -118,7 +118,7 @@ define(['datetime', 'itemHelper', 'css!./indicators.css', 'material-icons'], fun
var status;
if (item.Type === 'SeriesTimer') {
return '<i class="material-icons timerIndicator indicatorIcon fiber_smart_record"></i>';
return '<span class="material-icons timerIndicator indicatorIcon fiber_smart_record"></span>';
} else if (item.TimerId || item.SeriesTimerId) {
status = item.Status || 'Cancelled';
} else if (item.Type === 'Timer') {
@ -129,20 +129,20 @@ define(['datetime', 'itemHelper', 'css!./indicators.css', 'material-icons'], fun
if (item.SeriesTimerId) {
if (status !== 'Cancelled') {
return '<i class="material-icons timerIndicator indicatorIcon fiber_smart_record"></i>';
return '<span class="material-icons timerIndicator indicatorIcon fiber_smart_record"></span>';
}
return '<i class="material-icons timerIndicator timerIndicator-inactive indicatorIcon fiber_smart_record"></i>';
return '<span class="material-icons timerIndicator timerIndicator-inactive indicatorIcon fiber_smart_record"></span>';
}
return '<i class="material-icons timerIndicator indicatorIcon fiber_manual_record"></i>';
return '<span class="material-icons timerIndicator indicatorIcon fiber_manual_record"></span>';
}
function getSyncIndicator(item) {
if (item.SyncPercent === 100) {
return '<div class="syncIndicator indicator fullSyncIndicator"><i class="material-icons indicatorIcon file_download"></i></div>';
return '<div class="syncIndicator indicator fullSyncIndicator"><span class="material-icons indicatorIcon file_download"></span></div>';
} else if (item.SyncPercent != null) {
return '<div class="syncIndicator indicator emptySyncIndicator"><i class="material-icons indicatorIcon file_download"></i></div>';
return '<div class="syncIndicator indicator emptySyncIndicator"><span class="material-icons indicatorIcon file_download"></span></div>';
}
return '';
@ -150,16 +150,16 @@ define(['datetime', 'itemHelper', 'css!./indicators.css', 'material-icons'], fun
function getTypeIndicator(item) {
if (item.Type === 'Video') {
return '<div class="indicator videoIndicator"><i class="material-icons indicatorIcon">videocam</i></div>';
return '<div class="indicator videoIndicator"><span class="material-icons indicatorIcon videocam"></span></div>';
}
if (item.Type === 'Folder') {
return '<div class="indicator videoIndicator"><i class="material-icons indicatorIcon">folder</i></div>';
return '<div class="indicator videoIndicator"><span class="material-icons indicatorIcon folder"></span></div>';
}
if (item.Type === 'PhotoAlbum') {
return '<div class="indicator videoIndicator"><i class="material-icons indicatorIcon photo_album"></i></div>';
return '<div class="indicator videoIndicator"><span class="material-icons indicatorIcon photo_album"></span></div>';
}
if (item.Type === 'Photo') {
return '<div class="indicator videoIndicator"><i class="material-icons indicatorIcon">photo</i></div>';
return '<div class="indicator videoIndicator"><span class="material-icons indicatorIcon photo"></span></div>';
}
return '';
@ -183,45 +183,6 @@ define(['datetime', 'itemHelper', 'css!./indicators.css', 'material-icons'], fun
return '';
}
var ProgressBarPrototype = Object.create(HTMLDivElement.prototype);
function onAutoTimeProgress() {
var start = parseInt(this.getAttribute('data-starttime'));
var end = parseInt(this.getAttribute('data-endtime'));
var now = new Date().getTime();
var total = end - start;
var pct = 100 * ((now - start) / total);
pct = Math.min(100, pct);
pct = Math.max(0, pct);
var itemProgressBarForeground = this.querySelector('.itemProgressBarForeground');
itemProgressBarForeground.style.width = pct + '%';
}
ProgressBarPrototype.attachedCallback = function () {
if (this.timeInterval) {
clearInterval(this.timeInterval);
}
if (this.getAttribute('data-automode') === 'time') {
this.timeInterval = setInterval(onAutoTimeProgress.bind(this), 60000);
}
};
ProgressBarPrototype.detachedCallback = function () {
if (this.timeInterval) {
clearInterval(this.timeInterval);
this.timeInterval = null;
}
};
document.registerElement('emby-progressbar', {
prototype: ProgressBarPrototype,
extends: 'div'
});
return {
getProgressHtml: getProgressHtml,
getProgressBarHtml: getProgressBarHtml,

View file

@ -1,145 +1,145 @@
define(["dialogHelper", "require", "layoutManager", "globalize", "userSettings", "connectionManager", "loading", "focusManager", "dom", "apphost", "emby-select", "listViewStyle", "paper-icon-button-light", "css!./../formdialog", "material-icons", "emby-button", "flexStyles"], function (dialogHelper, require, layoutManager, globalize, userSettings, connectionManager, loading, focusManager, dom, appHost) {
"use strict";
define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings', 'connectionManager', 'loading', 'focusManager', 'dom', 'apphost', 'emby-select', 'listViewStyle', 'paper-icon-button-light', 'css!./../formdialog', 'material-icons', 'emby-button', 'flexStyles'], function (dialogHelper, require, layoutManager, globalize, userSettings, connectionManager, loading, focusManager, dom, appHost) {
'use strict';
function setMediaInfo(user, page, item) {
var html = item.MediaSources.map(function (version) {
return getMediaSourceHtml(user, item, version);
}).join('<div style="border-top:1px solid #444;margin: 1em 0;"></div>');
if (item.MediaSources.length > 1) {
html = "<br/>" + html;
html = '<br/>' + html;
}
var mediaInfoContent = page.querySelector("#mediaInfoContent");
var mediaInfoContent = page.querySelector('#mediaInfoContent');
mediaInfoContent.innerHTML = html;
}
function getMediaSourceHtml(user, item, version) {
var html = "";
var html = '';
if (version.Name) {
html += '<div><h2 class="mediaInfoStreamType">' + version.Name + "</h2></div>";
html += '<div><h2 class="mediaInfoStreamType">' + version.Name + '</h2></div>';
}
if (version.Container) {
html += createAttribute(globalize.translate("MediaInfoContainer"), version.Container) + "<br/>";
html += createAttribute(globalize.translate('MediaInfoContainer'), version.Container) + '<br/>';
}
if (version.Formats && version.Formats.length) {
html += createAttribute(globalize.translate("MediaInfoFormat"), version.Formats.join(",")) + "<br/>";
html += createAttribute(globalize.translate('MediaInfoFormat'), version.Formats.join(',')) + '<br/>';
}
if (version.Path && user && user.Policy.IsAdministrator) {
html += createAttribute(globalize.translate("MediaInfoPath"), version.Path) + "<br/>";
html += createAttribute(globalize.translate('MediaInfoPath'), version.Path) + '<br/>';
}
if (version.Size) {
var size = (version.Size / (1024 * 1024)).toFixed(0) + " MB";
html += createAttribute(globalize.translate("MediaInfoSize"), size) + "<br/>";
var size = (version.Size / (1024 * 1024)).toFixed(0) + ' MB';
html += createAttribute(globalize.translate('MediaInfoSize'), size) + '<br/>';
}
for (var i = 0, length = version.MediaStreams.length; i < length; i++) {
var stream = version.MediaStreams[i];
if (stream.Type === "Data") {
if (stream.Type === 'Data') {
continue;
}
html += '<div class="mediaInfoStream">';
var displayType = globalize.translate("MediaInfoStreamType" + stream.Type);
html += '<h2 class="mediaInfoStreamType">' + displayType + "</h2>";
var displayType = globalize.translate('MediaInfoStreamType' + stream.Type);
html += '<h2 class="mediaInfoStreamType">' + displayType + '</h2>';
var attributes = [];
if (stream.DisplayTitle) {
attributes.push(createAttribute("Title", stream.DisplayTitle));
attributes.push(createAttribute('Title', stream.DisplayTitle));
}
if (stream.Language && stream.Type !== "Video") {
attributes.push(createAttribute(globalize.translate("MediaInfoLanguage"), stream.Language));
if (stream.Language && stream.Type !== 'Video') {
attributes.push(createAttribute(globalize.translate('MediaInfoLanguage'), stream.Language));
}
if (stream.Codec) {
attributes.push(createAttribute(globalize.translate("MediaInfoCodec"), stream.Codec.toUpperCase()));
attributes.push(createAttribute(globalize.translate('MediaInfoCodec'), stream.Codec.toUpperCase()));
}
if (stream.CodecTag) {
attributes.push(createAttribute(globalize.translate("MediaInfoCodecTag"), stream.CodecTag));
attributes.push(createAttribute(globalize.translate('MediaInfoCodecTag'), stream.CodecTag));
}
if (stream.IsAVC != null) {
attributes.push(createAttribute("AVC", (stream.IsAVC ? "Yes" : "No")));
attributes.push(createAttribute('AVC', (stream.IsAVC ? 'Yes' : 'No')));
}
if (stream.Profile) {
attributes.push(createAttribute(globalize.translate("MediaInfoProfile"), stream.Profile));
attributes.push(createAttribute(globalize.translate('MediaInfoProfile'), stream.Profile));
}
if (stream.Level) {
attributes.push(createAttribute(globalize.translate("MediaInfoLevel"), stream.Level));
attributes.push(createAttribute(globalize.translate('MediaInfoLevel'), stream.Level));
}
if (stream.Width || stream.Height) {
attributes.push(createAttribute(globalize.translate("MediaInfoResolution"), stream.Width + "x" + stream.Height));
attributes.push(createAttribute(globalize.translate('MediaInfoResolution'), stream.Width + 'x' + stream.Height));
}
if (stream.AspectRatio && stream.Codec !== "mjpeg") {
attributes.push(createAttribute(globalize.translate("MediaInfoAspectRatio"), stream.AspectRatio));
if (stream.AspectRatio && stream.Codec !== 'mjpeg') {
attributes.push(createAttribute(globalize.translate('MediaInfoAspectRatio'), stream.AspectRatio));
}
if (stream.Type === "Video") {
if (stream.Type === 'Video') {
if (stream.IsAnamorphic != null) {
attributes.push(createAttribute(globalize.translate("MediaInfoAnamorphic"), (stream.IsAnamorphic ? "Yes" : "No")));
attributes.push(createAttribute(globalize.translate('MediaInfoAnamorphic'), (stream.IsAnamorphic ? 'Yes' : 'No')));
}
attributes.push(createAttribute(globalize.translate("MediaInfoInterlaced"), (stream.IsInterlaced ? "Yes" : "No")));
attributes.push(createAttribute(globalize.translate('MediaInfoInterlaced'), (stream.IsInterlaced ? 'Yes' : 'No')));
}
if (stream.AverageFrameRate || stream.RealFrameRate) {
attributes.push(createAttribute(globalize.translate("MediaInfoFramerate"), (stream.AverageFrameRate || stream.RealFrameRate)));
attributes.push(createAttribute(globalize.translate('MediaInfoFramerate'), (stream.AverageFrameRate || stream.RealFrameRate)));
}
if (stream.ChannelLayout) {
attributes.push(createAttribute(globalize.translate("MediaInfoLayout"), stream.ChannelLayout));
attributes.push(createAttribute(globalize.translate('MediaInfoLayout'), stream.ChannelLayout));
}
if (stream.Channels) {
attributes.push(createAttribute(globalize.translate("MediaInfoChannels"), stream.Channels + " ch"));
attributes.push(createAttribute(globalize.translate('MediaInfoChannels'), stream.Channels + ' ch'));
}
if (stream.BitRate && stream.Codec !== "mjpeg") {
attributes.push(createAttribute(globalize.translate("MediaInfoBitrate"), (parseInt(stream.BitRate / 1000)) + " kbps"));
if (stream.BitRate && stream.Codec !== 'mjpeg') {
attributes.push(createAttribute(globalize.translate('MediaInfoBitrate'), (parseInt(stream.BitRate / 1000)) + ' kbps'));
}
if (stream.SampleRate) {
attributes.push(createAttribute(globalize.translate("MediaInfoSampleRate"), stream.SampleRate + " Hz"));
attributes.push(createAttribute(globalize.translate('MediaInfoSampleRate'), stream.SampleRate + ' Hz'));
}
if (stream.BitDepth) {
attributes.push(createAttribute(globalize.translate("MediaInfoBitDepth"), stream.BitDepth + " bit"));
attributes.push(createAttribute(globalize.translate('MediaInfoBitDepth'), stream.BitDepth + ' bit'));
}
if (stream.PixelFormat) {
attributes.push(createAttribute(globalize.translate("MediaInfoPixelFormat"), stream.PixelFormat));
attributes.push(createAttribute(globalize.translate('MediaInfoPixelFormat'), stream.PixelFormat));
}
if (stream.RefFrames) {
attributes.push(createAttribute(globalize.translate("MediaInfoRefFrames"), stream.RefFrames));
attributes.push(createAttribute(globalize.translate('MediaInfoRefFrames'), stream.RefFrames));
}
if (stream.NalLengthSize) {
attributes.push(createAttribute("NAL", stream.NalLengthSize));
attributes.push(createAttribute('NAL', stream.NalLengthSize));
}
if (stream.Type !== "Video") {
attributes.push(createAttribute(globalize.translate("MediaInfoDefault"), (stream.IsDefault ? "Yes" : "No")));
if (stream.Type !== 'Video') {
attributes.push(createAttribute(globalize.translate('MediaInfoDefault'), (stream.IsDefault ? 'Yes' : 'No')));
}
if (stream.Type === "Subtitle") {
attributes.push(createAttribute(globalize.translate("MediaInfoForced"), (stream.IsForced ? "Yes" : "No")));
attributes.push(createAttribute(globalize.translate("MediaInfoExternal"), (stream.IsExternal ? "Yes" : "No")));
if (stream.Type === 'Subtitle') {
attributes.push(createAttribute(globalize.translate('MediaInfoForced'), (stream.IsForced ? 'Yes' : 'No')));
attributes.push(createAttribute(globalize.translate('MediaInfoExternal'), (stream.IsExternal ? 'Yes' : 'No')));
}
if (stream.Type === "Video" && version.Timestamp) {
attributes.push(createAttribute(globalize.translate("MediaInfoTimestamp"), version.Timestamp));
if (stream.Type === 'Video' && version.Timestamp) {
attributes.push(createAttribute(globalize.translate('MediaInfoTimestamp'), version.Timestamp));
}
html += attributes.join("<br/>");
html += "</div>";
html += attributes.join('<br/>');
html += '</div>';
}
return html;
}
function createAttribute(label, value) {
return '<span class="mediaInfoLabel">' + label + '</span><span class="mediaInfoAttribute">' + value + "</span>";
return '<span class="mediaInfoLabel">' + label + '</span><span class="mediaInfoAttribute">' + value + '</span>';
}
function showMediaInfoMore(itemId, serverId, template) {
var apiClient = connectionManager.getApiClient(serverId);
return apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) {
var dialogOptions = {
size: "small",
size: 'small',
removeOnClose: true,
scrollY: false
};
if (layoutManager.tv) {
dialogOptions.size = "fullscreen";
dialogOptions.size = 'fullscreen';
}
var dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add("formDialog");
var html = "";
html += globalize.translateDocument(template, "core");
dlg.classList.add('formDialog');
var html = '';
html += globalize.translateDocument(template, 'core');
dlg.innerHTML = html;
if (layoutManager.tv) {
dlg.querySelector(".formDialogContent");
dlg.querySelector('.formDialogContent');
}
dialogHelper.open(dlg);
dlg.querySelector(".btnCancel").addEventListener("click", function (e) {
dlg.querySelector('.btnCancel').addEventListener('click', function (e) {
dialogHelper.close(dlg);
});
apiClient.getCurrentUser().then(function (user) {
@ -152,7 +152,7 @@ define(["dialogHelper", "require", "layoutManager", "globalize", "userSettings",
function showMediaInfo(itemId, serverId) {
loading.show();
return new Promise(function (resolve, reject) {
require(["text!./itemMediaInfo.template.html"], function (template) {
require(['text!./itemMediaInfo.template.html'], function (template) {
showMediaInfoMore(itemId, serverId, template).then(resolve, reject);
});
});

View file

@ -1,6 +1,6 @@
<div class="formDialogHeader">
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1">
<i class="material-icons arrow_back"></i>
<span class="material-icons arrow_back"></span>
</button>
<h3 class="formDialogHeaderTitle">${HeaderMediaInfo}</h3>
</div>

View file

@ -1,5 +1,5 @@
define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter", "playbackManager", "loading", "appSettings", "browser", "actionsheet"], function (appHost, globalize, connectionManager, itemHelper, appRouter, playbackManager, loading, appSettings, browser, actionsheet) {
"use strict";
define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', 'playbackManager', 'loading', 'appSettings', 'browser', 'actionsheet'], function (appHost, globalize, connectionManager, itemHelper, appRouter, playbackManager, loading, appSettings, browser, actionsheet) {
'use strict';
function getCommands(options) {
var item = options.item;
@ -10,20 +10,20 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
var commands = [];
if (canPlay && item.MediaType !== "Photo") {
if (canPlay && item.MediaType !== 'Photo') {
if (options.play !== false) {
commands.push({
name: globalize.translate("Play"),
id: "resume",
icon: "&#xE037;"
name: globalize.translate('Play'),
id: 'resume',
icon: 'play_arrow'
});
}
if (options.playAllFromHere && item.Type !== "Program" && item.Type !== "TvChannel") {
if (options.playAllFromHere && item.Type !== 'Program' && item.Type !== 'TvChannel') {
commands.push({
name: globalize.translate("PlayAllFromHere"),
id: "playallfromhere",
icon: "&#xE037;"
name: globalize.translate('PlayAllFromHere'),
id: 'playallfromhere',
icon: 'play_arrow'
});
}
}
@ -31,17 +31,17 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
if (playbackManager.canQueue(item)) {
if (options.queue !== false) {
commands.push({
name: globalize.translate("AddToPlayQueue"),
id: "queue",
icon: "playlist_add"
name: globalize.translate('AddToPlayQueue'),
id: 'queue',
icon: 'playlist_add'
});
}
if (options.queue !== false) {
commands.push({
name: globalize.translate("PlayNext"),
id: "queuenext",
icon: "playlist_add"
name: globalize.translate('PlayNext'),
id: 'queuenext',
icon: 'playlist_add'
});
}
@ -53,24 +53,24 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
//}
}
if (item.IsFolder || item.Type === "MusicArtist" || item.Type === "MusicGenre") {
if (item.CollectionType !== "livetv") {
if (item.IsFolder || item.Type === 'MusicArtist' || item.Type === 'MusicGenre') {
if (item.CollectionType !== 'livetv') {
if (options.shuffle !== false) {
commands.push({
name: globalize.translate("Shuffle"),
id: "shuffle",
icon: "shuffle"
name: globalize.translate('Shuffle'),
id: 'shuffle',
icon: 'shuffle'
});
}
}
}
if (item.MediaType === "Audio" || item.Type === "MusicAlbum" || item.Type === "MusicArtist" || item.Type === "MusicGenre") {
if (item.MediaType === 'Audio' || item.Type === 'MusicAlbum' || item.Type === 'MusicArtist' || item.Type === 'MusicGenre') {
if (options.instantMix !== false && !itemHelper.isLocalItem(item)) {
commands.push({
name: globalize.translate("InstantMix"),
id: "instantmix",
icon: "explore"
name: globalize.translate('InstantMix'),
id: 'instantmix',
icon: 'explore'
});
}
}
@ -84,74 +84,74 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
if (!restrictOptions) {
if (itemHelper.supportsAddingToCollection(item)) {
commands.push({
name: globalize.translate("AddToCollection"),
id: "addtocollection",
icon: "playlist_add"
name: globalize.translate('AddToCollection'),
id: 'addtocollection',
icon: 'playlist_add'
});
}
if (itemHelper.supportsAddingToPlaylist(item)) {
if (itemHelper.supportsAddingToPlaylist(item) && options.playlist !== false) {
commands.push({
name: globalize.translate("AddToPlaylist"),
id: "addtoplaylist",
icon: "playlist_add"
name: globalize.translate('AddToPlaylist'),
id: 'addtoplaylist',
icon: 'playlist_add'
});
}
}
if ((item.Type === "Timer") && user.Policy.EnableLiveTvManagement && options.cancelTimer !== false) {
if ((item.Type === 'Timer') && user.Policy.EnableLiveTvManagement && options.cancelTimer !== false) {
commands.push({
name: globalize.translate("CancelRecording"),
id: "canceltimer",
icon: "cancel"
name: globalize.translate('CancelRecording'),
id: 'canceltimer',
icon: 'cancel'
});
}
if ((item.Type === "Recording" && item.Status === "InProgress") && user.Policy.EnableLiveTvManagement && options.cancelTimer !== false) {
if ((item.Type === 'Recording' && item.Status === 'InProgress') && user.Policy.EnableLiveTvManagement && options.cancelTimer !== false) {
commands.push({
name: globalize.translate("CancelRecording"),
id: "canceltimer",
icon: "cancel"
name: globalize.translate('CancelRecording'),
id: 'canceltimer',
icon: 'cancel'
});
}
if ((item.Type === "SeriesTimer") && user.Policy.EnableLiveTvManagement && options.cancelTimer !== false) {
if ((item.Type === 'SeriesTimer') && user.Policy.EnableLiveTvManagement && options.cancelTimer !== false) {
commands.push({
name: globalize.translate("CancelSeries"),
id: "cancelseriestimer",
icon: "cancel"
name: globalize.translate('CancelSeries'),
id: 'cancelseriestimer',
icon: 'cancel'
});
}
if (item.CanDelete && options.deleteItem !== false) {
if (item.Type === "Playlist" || item.Type === "BoxSet") {
if (item.Type === 'Playlist' || item.Type === 'BoxSet') {
commands.push({
name: globalize.translate("Delete"),
id: "delete",
icon: "delete"
name: globalize.translate('Delete'),
id: 'delete',
icon: 'delete'
});
} else {
commands.push({
name: globalize.translate("DeleteMedia"),
id: "delete",
icon: "delete"
name: globalize.translate('DeleteMedia'),
id: 'delete',
icon: 'delete'
});
}
}
// Books are promoted to major download Button and therefor excluded in the context menu
if ((item.CanDownload && appHost.supports("filedownload")) && item.Type !== "Book") {
if ((item.CanDownload && appHost.supports('filedownload')) && item.Type !== 'Book') {
commands.push({
name: globalize.translate("Download"),
id: "download",
icon: "file_download"
name: globalize.translate('Download'),
id: 'download',
icon: 'file_download'
});
commands.push({
name: globalize.translate("CopyStreamURL"),
id: "copy-stream",
icon: "content_copy"
name: globalize.translate('CopyStreamURL'),
id: 'copy-stream',
icon: 'content_copy'
});
}
@ -163,12 +163,12 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
var canEdit = itemHelper.canEdit(user, item);
if (canEdit) {
if (options.edit !== false && item.Type !== "SeriesTimer") {
var text = (item.Type === "Timer" || item.Type === "SeriesTimer") ? globalize.translate("Edit") : globalize.translate("EditMetadata");
if (options.edit !== false && item.Type !== 'SeriesTimer') {
var text = (item.Type === 'Timer' || item.Type === 'SeriesTimer') ? globalize.translate('Edit') : globalize.translate('EditMetadata');
commands.push({
name: text,
id: "edit",
icon: "edit"
id: 'edit',
icon: 'edit'
});
}
}
@ -176,20 +176,20 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
if (itemHelper.canEditImages(user, item)) {
if (options.editImages !== false) {
commands.push({
name: globalize.translate("EditImages"),
id: "editimages",
icon: "image"
name: globalize.translate('EditImages'),
id: 'editimages',
icon: 'image'
});
}
}
if (canEdit) {
if (item.MediaType === "Video" && item.Type !== "TvChannel" && item.Type !== "Program" && item.LocationType !== "Virtual" && !(item.Type === "Recording" && item.Status !== "Completed")) {
if (item.MediaType === 'Video' && item.Type !== 'TvChannel' && item.Type !== 'Program' && item.LocationType !== 'Virtual' && !(item.Type === 'Recording' && item.Status !== 'Completed')) {
if (options.editSubtitles !== false) {
commands.push({
name: globalize.translate("EditSubtitles"),
id: "editsubtitles",
icon: "closed_caption"
name: globalize.translate('EditSubtitles'),
id: 'editsubtitles',
icon: 'closed_caption'
});
}
}
@ -198,9 +198,9 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
if (options.identify !== false) {
if (itemHelper.canIdentify(user, item)) {
commands.push({
name: globalize.translate("Identify"),
id: "identify",
icon: "edit"
name: globalize.translate('Identify'),
id: 'identify',
icon: 'edit'
});
}
}
@ -208,54 +208,54 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
if (item.MediaSources) {
if (options.moremediainfo !== false) {
commands.push({
name: globalize.translate("MoreMediaInfo"),
id: "moremediainfo",
icon: "info"
name: globalize.translate('MoreMediaInfo'),
id: 'moremediainfo',
icon: 'info'
});
}
}
if (item.Type === "Program" && options.record !== false) {
if (item.Type === 'Program' && options.record !== false) {
if (item.TimerId) {
commands.push({
name: Globalize.translate("ManageRecording"),
id: "record",
icon: "fiber_manual_record"
name: globalize.translate('ManageRecording'),
id: 'record',
icon: 'fiber_manual_record'
});
}
}
if (item.Type === "Program" && options.record !== false) {
if (item.Type === 'Program' && options.record !== false) {
if (!item.TimerId) {
commands.push({
name: Globalize.translate("Record"),
id: "record",
icon: "fiber_manual_record"
name: globalize.translate('Record'),
id: 'record',
icon: 'fiber_manual_record'
});
}
}
if (itemHelper.canRefreshMetadata(item, user)) {
commands.push({
name: globalize.translate("RefreshMetadata"),
id: "refresh",
icon: "refresh"
name: globalize.translate('RefreshMetadata'),
id: 'refresh',
icon: 'refresh'
});
}
if (item.PlaylistItemId && options.playlistId) {
commands.push({
name: globalize.translate("RemoveFromPlaylist"),
id: "removefromplaylist",
icon: "remove"
name: globalize.translate('RemoveFromPlaylist'),
id: 'removefromplaylist',
icon: 'remove'
});
}
if (options.collectionId) {
commands.push({
name: globalize.translate("RemoveFromCollection"),
id: "removefromcollection",
icon: "remove"
name: globalize.translate('RemoveFromCollection'),
id: 'removefromcollection',
icon: 'remove'
});
}
@ -263,9 +263,9 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
if (options.share === true) {
if (itemHelper.canShare(item, user)) {
commands.push({
name: globalize.translate("Share"),
id: "share",
icon: "share"
name: globalize.translate('Share'),
id: 'share',
icon: 'share'
});
}
}
@ -274,26 +274,26 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
if (options.sync !== false) {
if (itemHelper.canSync(user, item)) {
commands.push({
name: globalize.translate("Sync"),
id: "sync",
icon: "sync"
name: globalize.translate('Sync'),
id: 'sync',
icon: 'sync'
});
}
}
if (options.openAlbum !== false && item.AlbumId && item.MediaType !== "Photo") {
if (options.openAlbum !== false && item.AlbumId && item.MediaType !== 'Photo') {
commands.push({
name: Globalize.translate("ViewAlbum"),
id: "album",
icon: "album"
name: globalize.translate('ViewAlbum'),
id: 'album',
icon: 'album'
});
}
if (options.openArtist !== false && item.ArtistItems && item.ArtistItems.length) {
commands.push({
name: Globalize.translate("ViewArtist"),
id: "artist",
icon: "person"
name: globalize.translate('ViewArtist'),
id: 'artist',
icon: 'person'
});
}
@ -317,48 +317,50 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
return new Promise(function (resolve, reject) {
switch (id) {
case "addtocollection":
require(["collectionEditor"], function (collectionEditor) {
case 'addtocollection':
require(['collectionEditor'], function (collectionEditor) {
new collectionEditor().show({
items: [itemId],
serverId: serverId
}).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
});
break;
case "addtoplaylist":
require(["playlistEditor"], function (playlistEditor) {
case 'addtoplaylist':
require(['playlistEditor'], function (playlistEditor) {
new playlistEditor().show({
items: [itemId],
serverId: serverId
}).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
});
break;
case "download":
require(["fileDownloader"], function (fileDownloader) {
case 'download':
require(['fileDownloader'], function (fileDownloader) {
var downloadHref = apiClient.getItemDownloadUrl(itemId);
fileDownloader.download([{
url: downloadHref,
itemId: itemId,
serverId: serverId
serverId: serverId,
title: item.Name,
filename: item.Path.replace(/^.*[\\\/]/, '')
}]);
getResolveFunction(getResolveFunction(resolve, id), id)();
});
break;
case "copy-stream":
case 'copy-stream':
var downloadHref = apiClient.getItemDownloadUrl(itemId);
var textAreaCopy = function () {
var textArea = document.createElement("textarea");
var textArea = document.createElement('textarea');
textArea.value = downloadHref;
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
if (document.execCommand("copy")) {
require(["toast"], function (toast) {
toast(globalize.translate("CopyStreamURLSuccess"));
if (document.execCommand('copy')) {
require(['toast'], function (toast) {
toast(globalize.translate('CopyStreamURLSuccess'));
});
} else {
prompt(globalize.translate("CopyStreamURL"), downloadHref);
prompt(globalize.translate('CopyStreamURL'), downloadHref);
}
document.body.removeChild(textArea);
};
@ -369,8 +371,8 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
} else {
/* eslint-disable-next-line compat/compat */
navigator.clipboard.writeText(downloadHref).then(function () {
require(["toast"], function (toast) {
toast(globalize.translate("CopyStreamURLSuccess"));
require(['toast'], function (toast) {
toast(globalize.translate('CopyStreamURLSuccess'));
});
}).catch(function () {
textAreaCopy();
@ -378,118 +380,118 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
}
getResolveFunction(resolve, id)();
break;
case "editsubtitles":
require(["subtitleEditor"], function (subtitleEditor) {
case 'editsubtitles':
require(['subtitleEditor'], function (subtitleEditor) {
subtitleEditor.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
});
break;
case "edit":
case 'edit':
editItem(apiClient, item).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
break;
case "editimages":
require(["imageEditor"], function (imageEditor) {
case 'editimages':
require(['imageEditor'], function (imageEditor) {
imageEditor.show({
itemId: itemId,
serverId: serverId
}).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
});
break;
case "identify":
require(["itemIdentifier"], function (itemIdentifier) {
case 'identify':
require(['itemIdentifier'], function (itemIdentifier) {
itemIdentifier.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
});
break;
case "moremediainfo":
require(["itemMediaInfo"], function (itemMediaInfo) {
case 'moremediainfo':
require(['itemMediaInfo'], function (itemMediaInfo) {
itemMediaInfo.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
});
break;
case "refresh":
case 'refresh':
refresh(apiClient, item);
getResolveFunction(resolve, id)();
break;
case "open":
case 'open':
appRouter.showItem(item);
getResolveFunction(resolve, id)();
break;
case "play":
case 'play':
play(item, false);
getResolveFunction(resolve, id)();
break;
case "resume":
case 'resume':
play(item, true);
getResolveFunction(resolve, id)();
break;
case "queue":
case 'queue':
play(item, false, true);
getResolveFunction(resolve, id)();
break;
case "queuenext":
case 'queuenext':
play(item, false, true, true);
getResolveFunction(resolve, id)();
break;
case "record":
require(["recordingCreator"], function (recordingCreator) {
case 'record':
require(['recordingCreator'], function (recordingCreator) {
recordingCreator.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
});
break;
case "shuffle":
case 'shuffle':
playbackManager.shuffle(item);
getResolveFunction(resolve, id)();
break;
case "instantmix":
case 'instantmix':
playbackManager.instantMix(item);
getResolveFunction(resolve, id)();
break;
case "delete":
case 'delete':
deleteItem(apiClient, item).then(getResolveFunction(resolve, id, true, true), getResolveFunction(resolve, id));
break;
case "share":
case 'share':
navigator.share({
title: item.Name,
text: item.Overview,
url: "https://github.com/jellyfin/jellyfin"
url: 'https://github.com/jellyfin/jellyfin'
});
break;
case "album":
case 'album':
appRouter.showItem(item.AlbumId, item.ServerId);
getResolveFunction(resolve, id)();
break;
case "artist":
case 'artist':
appRouter.showItem(item.ArtistItems[0].Id, item.ServerId);
getResolveFunction(resolve, id)();
break;
case "playallfromhere":
case 'playallfromhere':
getResolveFunction(resolve, id)();
break;
case "queueallfromhere":
case 'queueallfromhere':
getResolveFunction(resolve, id)();
break;
case "removefromplaylist":
case 'removefromplaylist':
apiClient.ajax({
url: apiClient.getUrl("Playlists/" + options.playlistId + "/Items", {
EntryIds: [item.PlaylistItemId].join(",")
url: apiClient.getUrl('Playlists/' + options.playlistId + '/Items', {
EntryIds: [item.PlaylistItemId].join(',')
}),
type: "DELETE"
type: 'DELETE'
}).then(function () {
getResolveFunction(resolve, id, true)();
});
break;
case "removefromcollection":
case 'removefromcollection':
apiClient.ajax({
type: "DELETE",
url: apiClient.getUrl("Collections/" + options.collectionId + "/Items", {
type: 'DELETE',
url: apiClient.getUrl('Collections/' + options.collectionId + '/Items', {
Ids: [item.Id].join(",")
Ids: [item.Id].join(',')
})
}).then(function () {
getResolveFunction(resolve, id, true)();
});
break;
case "canceltimer":
case 'canceltimer':
deleteTimer(apiClient, item, resolve, id);
break;
case "cancelseriestimer":
case 'cancelseriestimer':
deleteSeriesTimer(apiClient, item, resolve, id);
break;
default:
@ -500,7 +502,7 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
}
function deleteTimer(apiClient, item, resolve, command) {
require(["recordingHelper"], function (recordingHelper) {
require(['recordingHelper'], function (recordingHelper) {
var timerId = item.TimerId || item.Id;
recordingHelper.cancelTimerWithConfirmation(timerId, item.ServerId).then(function () {
getResolveFunction(resolve, command, true)();
@ -509,7 +511,7 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
}
function deleteSeriesTimer(apiClient, item, resolve, command) {
require(["recordingHelper"], function (recordingHelper) {
require(['recordingHelper'], function (recordingHelper) {
recordingHelper.cancelSeriesTimerWithConfirmation(item.Id, item.ServerId).then(function () {
getResolveFunction(resolve, command, true)();
});
@ -517,14 +519,14 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
}
function play(item, resume, queue, queueNext) {
var method = queue ? (queueNext ? "queueNext" : "queue") : "play";
var method = queue ? (queueNext ? 'queueNext' : 'queue') : 'play';
var startPosition = 0;
if (resume && item.UserData && item.UserData.PlaybackPositionTicks) {
startPosition = item.UserData.PlaybackPositionTicks;
}
if (item.Type === "Program") {
if (item.Type === 'Program') {
playbackManager[method]({
ids: [item.ChannelId],
startPositionTicks: startPosition,
@ -542,16 +544,16 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
return new Promise(function (resolve, reject) {
var serverId = apiClient.serverInfo().Id;
if (item.Type === "Timer") {
require(["recordingEditor"], function (recordingEditor) {
if (item.Type === 'Timer') {
require(['recordingEditor'], function (recordingEditor) {
recordingEditor.show(item.Id, serverId).then(resolve, reject);
});
} else if (item.Type === "SeriesTimer") {
require(["seriesRecordingEditor"], function (recordingEditor) {
} else if (item.Type === 'SeriesTimer') {
require(['seriesRecordingEditor'], function (recordingEditor) {
recordingEditor.show(item.Id, serverId).then(resolve, reject);
});
} else {
require(["metadataEditor"], function (metadataEditor) {
require(['metadataEditor'], function (metadataEditor) {
metadataEditor.show(item.Id, serverId).then(resolve, reject);
});
}
@ -560,7 +562,7 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
function deleteItem(apiClient, item) {
return new Promise(function (resolve, reject) {
require(["deleteHelper"], function (deleteHelper) {
require(['deleteHelper'], function (deleteHelper) {
deleteHelper.deleteItem({
item: item,
navigate: false
@ -572,11 +574,11 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
}
function refresh(apiClient, item) {
require(["refreshDialog"], function (refreshDialog) {
require(['refreshDialog'], function (refreshDialog) {
new refreshDialog({
itemIds: [item.Id],
serverId: apiClient.serverInfo().Id,
mode: item.Type === "CollectionFolder" ? "scan" : null
mode: item.Type === 'CollectionFolder' ? 'scan' : null
}).show();
});
}
@ -590,7 +592,7 @@ define(["apphost", "globalize", "connectionManager", "itemHelper", "appRouter",
return actionsheet.show({
items: commands,
positionTo: options.positionTo,
resolveOnClick: ["share"]
resolveOnClick: ['share']
}).then(function (id) {
return executeCommand(options.item, id, options);
});

View file

@ -4,7 +4,7 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
function getDisplayName(item, options) {
if (!item) {
throw new Error("null item passed into getDisplayName");
throw new Error('null item passed into getDisplayName');
}
options = options || {};
@ -15,31 +15,31 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
var name = ((item.Type === 'Program' || item.Type === 'Recording') && (item.IsSeries || item.EpisodeTitle) ? item.EpisodeTitle : item.Name) || '';
if (item.Type === "TvChannel") {
if (item.Type === 'TvChannel') {
if (item.ChannelNumber) {
return item.ChannelNumber + ' ' + name;
}
return name;
}
if (item.Type === "Episode" && item.ParentIndexNumber === 0) {
if (item.Type === 'Episode' && item.ParentIndexNumber === 0) {
name = globalize.translate('ValueSpecialEpisodeName', name);
} else if ((item.Type === "Episode" || item.Type === 'Program') && item.IndexNumber != null && item.ParentIndexNumber != null && options.includeIndexNumber !== false) {
} else if ((item.Type === 'Episode' || item.Type === 'Program') && item.IndexNumber != null && item.ParentIndexNumber != null && options.includeIndexNumber !== false) {
var displayIndexNumber = item.IndexNumber;
var number = displayIndexNumber;
var nameSeparator = " - ";
var nameSeparator = ' - ';
if (options.includeParentInfo !== false) {
number = "S" + item.ParentIndexNumber + ":E" + number;
number = 'S' + item.ParentIndexNumber + ':E' + number;
} else {
nameSeparator = ". ";
nameSeparator = '. ';
}
if (item.IndexNumberEnd) {
displayIndexNumber = item.IndexNumberEnd;
number += "-" + displayIndexNumber;
number += '-' + displayIndexNumber;
}
if (number) {
@ -94,14 +94,14 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
return false;
}
return item.MediaType || item.IsFolder || item.Type === "Genre" || item.Type === "MusicGenre" || item.Type === "MusicArtist";
return item.MediaType || item.IsFolder || item.Type === 'Genre' || item.Type === 'MusicGenre' || item.Type === 'MusicArtist';
}
function canEdit(user, item) {
var itemType = item.Type;
if (itemType === "UserRootFolder" || itemType === "UserView") {
if (itemType === 'UserRootFolder' || itemType === 'UserView') {
return false;
}
@ -149,15 +149,15 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
var itemType = item.Type;
if (itemType === "Movie" ||
itemType === "Trailer" ||
itemType === "Series" ||
itemType === "BoxSet" ||
itemType === "Person" ||
itemType === "Book" ||
itemType === "MusicAlbum" ||
itemType === "MusicArtist" ||
itemType === "MusicVideo") {
if (itemType === 'Movie' ||
itemType === 'Trailer' ||
itemType === 'Series' ||
itemType === 'BoxSet' ||
itemType === 'Person' ||
itemType === 'Book' ||
itemType === 'MusicAlbum' ||
itemType === 'MusicArtist' ||
itemType === 'MusicVideo') {
if (user.Policy.IsAdministrator) {
@ -259,11 +259,11 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
}
}
if (item.Type === "Series" ||
item.Type === "Season" ||
item.Type === "BoxSet" ||
item.MediaType === "Book" ||
item.MediaType === "Recording") {
if (item.Type === 'Series' ||
item.Type === 'Season' ||
item.Type === 'BoxSet' ||
item.MediaType === 'Book' ||
item.MediaType === 'Recording') {
return true;
}

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