mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Merge remote-tracking branch 'upstream/master' into hwaccel
This commit is contained in:
commit
be6c4a2ba4
506 changed files with 27834 additions and 23514 deletions
|
@ -12,7 +12,7 @@ pr:
|
||||||
- '*'
|
- '*'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
- job: Build
|
- job: Build
|
||||||
displayName: 'Build'
|
displayName: 'Build'
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
|
@ -21,8 +21,6 @@ jobs:
|
||||||
BuildConfiguration: development
|
BuildConfiguration: development
|
||||||
Production:
|
Production:
|
||||||
BuildConfiguration: production
|
BuildConfiguration: production
|
||||||
Standalone:
|
|
||||||
BuildConfiguration: standalone
|
|
||||||
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'ubuntu-latest'
|
vmImage: 'ubuntu-latest'
|
||||||
|
@ -49,26 +47,29 @@ jobs:
|
||||||
condition: eq(variables['BuildConfiguration'], 'development')
|
condition: eq(variables['BuildConfiguration'], 'development')
|
||||||
|
|
||||||
- script: 'yarn build:production'
|
- script: 'yarn build:production'
|
||||||
displayName: 'Build Bundle'
|
displayName: 'Build Production'
|
||||||
condition: eq(variables['BuildConfiguration'], 'production')
|
condition: eq(variables['BuildConfiguration'], 'production')
|
||||||
|
|
||||||
- script: 'yarn build:standalone'
|
|
||||||
displayName: 'Build Standalone'
|
|
||||||
condition: eq(variables['BuildConfiguration'], 'standalone')
|
|
||||||
|
|
||||||
- script: 'test -d dist'
|
- script: 'test -d dist'
|
||||||
displayName: 'Check Build'
|
displayName: 'Check Build'
|
||||||
|
|
||||||
- script: 'mv dist jellyfin-web'
|
- script: 'mv dist jellyfin-web'
|
||||||
displayName: 'Rename Directory'
|
displayName: 'Rename Directory'
|
||||||
|
|
||||||
|
- task: ArchiveFiles@2
|
||||||
|
displayName: 'Archive Directory'
|
||||||
|
inputs:
|
||||||
|
rootFolderOrFile: 'jellyfin-web'
|
||||||
|
includeRootFolder: true
|
||||||
|
archiveFile: 'jellyfin-web-$(BuildConfiguration)'
|
||||||
|
|
||||||
- task: PublishPipelineArtifact@1
|
- task: PublishPipelineArtifact@1
|
||||||
displayName: 'Publish Release'
|
displayName: 'Publish Release'
|
||||||
inputs:
|
inputs:
|
||||||
targetPath: '$(Build.SourcesDirectory)/jellyfin-web'
|
targetPath: '$(Build.SourcesDirectory)/jellyfin-web-$(BuildConfiguration).zip'
|
||||||
artifactName: 'jellyfin-web-$(BuildConfiguration)'
|
artifactName: 'jellyfin-web-$(BuildConfiguration)'
|
||||||
|
|
||||||
- job: Lint
|
- job: Lint
|
||||||
displayName: 'Lint'
|
displayName: 'Lint'
|
||||||
|
|
||||||
pool:
|
pool:
|
||||||
|
|
1
.copr/Makefile
Symbolic link
1
.copr/Makefile
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../fedora/Makefile
|
5
.dependabot/config.yml
Normal file
5
.dependabot/config.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
version: 1
|
||||||
|
update_configs:
|
||||||
|
- package_manager: "javascript"
|
||||||
|
directory: "/"
|
||||||
|
update_schedule: "weekly"
|
|
@ -7,3 +7,6 @@ charset = utf-8
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
|
|
||||||
|
[json]
|
||||||
|
indent_size = 2
|
||||||
|
|
|
@ -1 +1,5 @@
|
||||||
libraries/
|
node_modules
|
||||||
|
dist
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
src/libraries
|
||||||
|
|
196
.eslintrc.js
Normal file
196
.eslintrc.js
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
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'],
|
||||||
|
'space-infix-ops': 'error'
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: [
|
||||||
|
'./src/**/*.js'
|
||||||
|
],
|
||||||
|
parser: 'babel-eslint',
|
||||||
|
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.entries',
|
||||||
|
'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'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,87 +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
|
|
||||||
|
|
||||||
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"]
|
|
36
.gitattributes
vendored
36
.gitattributes
vendored
|
@ -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
4
.github/CODEOWNERS
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
.ci @dkanada @EraYaN
|
||||||
|
.github @jellyfin/core
|
||||||
|
build.sh @joshuaboniface
|
||||||
|
deployment @joshuaboniface
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -3,8 +3,12 @@ config.json
|
||||||
|
|
||||||
# npm
|
# npm
|
||||||
dist
|
dist
|
||||||
|
web
|
||||||
node_modules
|
node_modules
|
||||||
|
|
||||||
# ide
|
# ide
|
||||||
.idea
|
.idea
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
|
#log
|
||||||
|
yarn-error.log
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
- [Ryan Hartzell](https://github.com/ryan-hartzell)
|
- [Ryan Hartzell](https://github.com/ryan-hartzell)
|
||||||
- [Thibault Nocchi](https://github.com/ThibaultNocchi)
|
- [Thibault Nocchi](https://github.com/ThibaultNocchi)
|
||||||
- [MrTimscampi](https://github.com/MrTimscampi)
|
- [MrTimscampi](https://github.com/MrTimscampi)
|
||||||
|
- [Sarab Singh](https://github.com/sarab97)
|
||||||
|
- [Andrei Oanca](https://github.com/OancaAndrei)
|
||||||
|
|
||||||
# Emby Contributors
|
# Emby Contributors
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ Jellyfin Web is the frontend used for most of the clients available for end user
|
||||||
|
|
||||||
### Dependencies
|
### Dependencies
|
||||||
|
|
||||||
- Yarn
|
- [Yarn 1.22.4](https://classic.yarnpkg.com/en/docs/install)
|
||||||
- Gulp-cli
|
- Gulp-cli
|
||||||
|
|
||||||
### Getting Started
|
### Getting Started
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"presets": ["@babel/preset-env"]
|
|
||||||
}
|
|
110
build.sh
Executable file
110
build.sh
Executable 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
9
build.yaml
Normal 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
96
bump_version
Executable 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
5
debian/changelog
vendored
Normal 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
1
debian/compat
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
8
|
16
debian/control
vendored
Normal file
16
debian/control
vendored
Normal 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
28
debian/copyright
vendored
Normal 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
6
debian/gbp.conf
vendored
Normal 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
1
debian/install
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
web usr/share/jellyfin/
|
1
debian/po/POTFILES.in
vendored
Normal file
1
debian/po/POTFILES.in
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
[type: gettext/rfc822deb] templates
|
57
debian/po/templates.pot
vendored
Normal file
57
debian/po/templates.pot
vendored
Normal 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
20
debian/rules
vendored
Executable 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
1
debian/source/format
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
1.0
|
7
debian/source/options
vendored
Normal file
7
debian/source/options
vendored
Normal 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'
|
27
deployment/Dockerfile.centos.all
Normal file
27
deployment/Dockerfile.centos.all
Normal 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"]
|
25
deployment/Dockerfile.debian.all
Normal file
25
deployment/Dockerfile.debian.all
Normal 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"]
|
21
deployment/Dockerfile.fedora.all
Normal file
21
deployment/Dockerfile.fedora.all
Normal 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"]
|
25
deployment/Dockerfile.portable
Normal file
25
deployment/Dockerfile.portable
Normal 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
27
deployment/build.centos.all
Executable 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
25
deployment/build.debian.all
Executable 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
27
deployment/build.fedora.all
Executable 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
28
deployment/build.portable
Executable 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
21
fedora/Makefile
Normal 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
43
fedora/jellyfin-web.spec
Normal 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
|
36
gulpfile.js
36
gulpfile.js
|
@ -1,5 +1,3 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const { src, dest, series, parallel, watch } = require('gulp');
|
const { src, dest, series, parallel, watch } = require('gulp');
|
||||||
const browserSync = require('browser-sync').create();
|
const browserSync = require('browser-sync').create();
|
||||||
const del = require('del');
|
const del = require('del');
|
||||||
|
@ -10,15 +8,14 @@ const htmlmin = require('gulp-htmlmin');
|
||||||
const imagemin = require('gulp-imagemin');
|
const imagemin = require('gulp-imagemin');
|
||||||
const sourcemaps = require('gulp-sourcemaps');
|
const sourcemaps = require('gulp-sourcemaps');
|
||||||
const mode = require('gulp-mode')({
|
const mode = require('gulp-mode')({
|
||||||
modes: ["development", "production"],
|
modes: ['development', 'production'],
|
||||||
default: "development",
|
default: 'development',
|
||||||
verbose: false
|
verbose: false
|
||||||
});
|
});
|
||||||
const stream = require('webpack-stream');
|
const stream = require('webpack-stream');
|
||||||
const inject = require('gulp-inject');
|
const inject = require('gulp-inject');
|
||||||
const postcss = require('gulp-postcss');
|
const postcss = require('gulp-postcss');
|
||||||
const sass = require('gulp-sass');
|
const sass = require('gulp-sass');
|
||||||
const gulpif = require('gulp-if');
|
|
||||||
const lazypipe = require('lazypipe');
|
const lazypipe = require('lazypipe');
|
||||||
|
|
||||||
sass.compiler = require('node-sass');
|
sass.compiler = require('node-sass');
|
||||||
|
@ -47,7 +44,7 @@ const options = {
|
||||||
query: ['src/**/*.png', 'src/**/*.jpg', 'src/**/*.gif', 'src/**/*.svg']
|
query: ['src/**/*.png', 'src/**/*.jpg', 'src/**/*.gif', 'src/**/*.svg']
|
||||||
},
|
},
|
||||||
copy: {
|
copy: {
|
||||||
query: ['src/**/*.json', 'src/**/*.ico']
|
query: ['src/**/*.json', 'src/**/*.ico', 'src/**/*.mp3']
|
||||||
},
|
},
|
||||||
injectBundle: {
|
injectBundle: {
|
||||||
query: 'src/index.html'
|
query: 'src/index.html'
|
||||||
|
@ -57,12 +54,12 @@ const options = {
|
||||||
function serve() {
|
function serve() {
|
||||||
browserSync.init({
|
browserSync.init({
|
||||||
server: {
|
server: {
|
||||||
baseDir: "./dist"
|
baseDir: './dist'
|
||||||
},
|
},
|
||||||
port: 8080
|
port: 8080
|
||||||
});
|
});
|
||||||
|
|
||||||
let events = ['add', 'change'];
|
const events = ['add', 'change'];
|
||||||
|
|
||||||
watch(options.javascript.query).on('all', function (event, path) {
|
watch(options.javascript.query).on('all', function (event, path) {
|
||||||
if (events.includes(event)) {
|
if (events.includes(event)) {
|
||||||
|
@ -70,7 +67,7 @@ function serve() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(options.apploader.query, apploader(true));
|
watch(options.apploader.query, apploader());
|
||||||
|
|
||||||
watch('src/bundle.js', webpack);
|
watch('src/bundle.js', webpack);
|
||||||
|
|
||||||
|
@ -105,7 +102,7 @@ function clean() {
|
||||||
return del(['dist/']);
|
return del(['dist/']);
|
||||||
}
|
}
|
||||||
|
|
||||||
let pipelineJavascript = lazypipe()
|
const pipelineJavascript = lazypipe()
|
||||||
.pipe(function () {
|
.pipe(function () {
|
||||||
return mode.development(sourcemaps.init({ loadMaps: true }));
|
return mode.development(sourcemaps.init({ loadMaps: true }));
|
||||||
})
|
})
|
||||||
|
@ -133,18 +130,12 @@ function javascript(query) {
|
||||||
.pipe(browserSync.stream());
|
.pipe(browserSync.stream());
|
||||||
}
|
}
|
||||||
|
|
||||||
function apploader(standalone) {
|
function apploader() {
|
||||||
function task() {
|
|
||||||
return src(options.apploader.query, { base: './src/' })
|
return src(options.apploader.query, { base: './src/' })
|
||||||
.pipe(gulpif(standalone, concat('scripts/apploader.js')))
|
.pipe(concat('scripts/apploader.js'))
|
||||||
.pipe(pipelineJavascript())
|
.pipe(pipelineJavascript())
|
||||||
.pipe(dest('dist/'))
|
.pipe(dest('dist/'))
|
||||||
.pipe(browserSync.stream());
|
.pipe(browserSync.stream());
|
||||||
};
|
|
||||||
|
|
||||||
task.displayName = 'apploader';
|
|
||||||
|
|
||||||
return task;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function webpack() {
|
function webpack() {
|
||||||
|
@ -192,10 +183,5 @@ function injectBundle() {
|
||||||
.pipe(browserSync.stream());
|
.pipe(browserSync.stream());
|
||||||
}
|
}
|
||||||
|
|
||||||
function build(standalone) {
|
exports.default = series(clean, parallel(javascript, apploader, webpack, css, html, images, copy), injectBundle);
|
||||||
return series(clean, parallel(javascript, apploader(standalone), webpack, css, html, images, copy), injectBundle);
|
exports.serve = series(exports.default, serve);
|
||||||
}
|
|
||||||
|
|
||||||
exports.default = build(false);
|
|
||||||
exports.standalone = build(true);
|
|
||||||
exports.serve = series(exports.standalone, serve);
|
|
||||||
|
|
101
package.json
101
package.json
|
@ -5,26 +5,29 @@
|
||||||
"repository": "https://github.com/jellyfin/jellyfin-web",
|
"repository": "https://github.com/jellyfin/jellyfin-web",
|
||||||
"license": "GPL-2.0-or-later",
|
"license": "GPL-2.0-or-later",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.8.6",
|
"@babel/core": "^7.10.2",
|
||||||
"@babel/plugin-transform-modules-amd": "^7.8.3",
|
"@babel/plugin-proposal-class-properties": "^7.10.1",
|
||||||
|
"@babel/plugin-proposal-private-methods": "^7.10.1",
|
||||||
|
"@babel/plugin-transform-modules-amd": "^7.9.6",
|
||||||
"@babel/polyfill": "^7.8.7",
|
"@babel/polyfill": "^7.8.7",
|
||||||
"@babel/preset-env": "^7.8.6",
|
"@babel/preset-env": "^7.10.2",
|
||||||
"autoprefixer": "^9.7.4",
|
"autoprefixer": "^9.8.0",
|
||||||
|
"babel-eslint": "^11.0.0-beta.2",
|
||||||
"babel-loader": "^8.0.6",
|
"babel-loader": "^8.0.6",
|
||||||
"browser-sync": "^2.26.7",
|
"browser-sync": "^2.26.7",
|
||||||
"clean-webpack-plugin": "^3.0.0",
|
|
||||||
"copy-webpack-plugin": "^5.1.1",
|
"copy-webpack-plugin": "^5.1.1",
|
||||||
"css-loader": "^3.4.2",
|
"css-loader": "^3.4.2",
|
||||||
"cssnano": "^4.1.10",
|
"cssnano": "^4.1.10",
|
||||||
"del": "^5.1.0",
|
"del": "^5.1.0",
|
||||||
"eslint": "^6.8.0",
|
"eslint": "^6.8.0",
|
||||||
"eslint-plugin-eslint-comments": "^3.1.2",
|
"eslint-plugin-compat": "^3.5.1",
|
||||||
|
"eslint-plugin-eslint-comments": "^3.2.0",
|
||||||
"eslint-plugin-import": "^2.20.2",
|
"eslint-plugin-import": "^2.20.2",
|
||||||
"eslint-plugin-promise": "^4.2.1",
|
"eslint-plugin-promise": "^4.2.1",
|
||||||
"file-loader": "^6.0.0",
|
"file-loader": "^6.0.0",
|
||||||
"gulp": "^4.0.2",
|
"gulp": "^4.0.2",
|
||||||
"gulp-babel": "^8.0.0",
|
"gulp-babel": "^8.0.0",
|
||||||
"gulp-cli": "^2.2.0",
|
"gulp-cli": "^2.2.1",
|
||||||
"gulp-concat": "^2.6.1",
|
"gulp-concat": "^2.6.1",
|
||||||
"gulp-htmlmin": "^5.0.1",
|
"gulp-htmlmin": "^5.0.1",
|
||||||
"gulp-if": "^3.0.0",
|
"gulp-if": "^3.0.0",
|
||||||
|
@ -35,44 +38,48 @@
|
||||||
"gulp-sass": "^4.0.2",
|
"gulp-sass": "^4.0.2",
|
||||||
"gulp-sourcemaps": "^2.6.5",
|
"gulp-sourcemaps": "^2.6.5",
|
||||||
"gulp-terser": "^1.2.0",
|
"gulp-terser": "^1.2.0",
|
||||||
"html-webpack-plugin": "^4.0.2",
|
"html-webpack-plugin": "^4.3.0",
|
||||||
"lazypipe": "^1.0.2",
|
"lazypipe": "^1.0.2",
|
||||||
"node-sass": "^4.13.1",
|
"node-sass": "^4.13.1",
|
||||||
"postcss-loader": "^3.0.0",
|
"postcss-loader": "^3.0.0",
|
||||||
"postcss-preset-env": "^6.7.0",
|
"postcss-preset-env": "^6.7.0",
|
||||||
"style-loader": "^1.1.3",
|
"style-loader": "^1.1.3",
|
||||||
"stylelint": "^13.1.0",
|
"stylelint": "^13.5.0",
|
||||||
"stylelint-config-rational-order": "^0.1.2",
|
"stylelint-config-rational-order": "^0.1.2",
|
||||||
"stylelint-no-browser-hacks": "^1.2.1",
|
"stylelint-no-browser-hacks": "^1.2.1",
|
||||||
"stylelint-order": "^4.0.0",
|
"stylelint-order": "^4.0.0",
|
||||||
"webpack": "^4.41.5",
|
"webpack": "^4.41.5",
|
||||||
"webpack-cli": "^3.3.10",
|
|
||||||
"webpack-concat-plugin": "^3.0.0",
|
|
||||||
"webpack-dev-server": "^3.10.3",
|
|
||||||
"webpack-merge": "^4.2.2",
|
"webpack-merge": "^4.2.2",
|
||||||
"webpack-stream": "^5.2.1"
|
"webpack-stream": "^5.2.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"alameda": "^1.4.0",
|
"alameda": "^1.4.0",
|
||||||
|
"blurhash": "^1.1.3",
|
||||||
"classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz",
|
"classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz",
|
||||||
"core-js": "^3.6.4",
|
"core-js": "^3.6.5",
|
||||||
"date-fns": "^2.11.1",
|
"date-fns": "^2.14.0",
|
||||||
"document-register-element": "^1.14.3",
|
"document-register-element": "^1.14.3",
|
||||||
|
"epubjs": "^0.3.85",
|
||||||
|
"fast-text-encoding": "^1.0.1",
|
||||||
"flv.js": "^1.5.0",
|
"flv.js": "^1.5.0",
|
||||||
|
"headroom.js": "^0.11.0",
|
||||||
"hls.js": "^0.13.1",
|
"hls.js": "^0.13.1",
|
||||||
"howler": "^2.1.3",
|
"howler": "^2.2.0",
|
||||||
|
"intersection-observer": "^0.10.0",
|
||||||
|
"jellyfin-apiclient": "^1.2.0",
|
||||||
"jellyfin-noto": "https://github.com/jellyfin/jellyfin-noto",
|
"jellyfin-noto": "https://github.com/jellyfin/jellyfin-noto",
|
||||||
"jquery": "^3.4.1",
|
"jquery": "^3.5.1",
|
||||||
"jstree": "^3.3.7",
|
"jstree": "^3.3.7",
|
||||||
"libass-wasm": "https://github.com/jellyfin/JavascriptSubtitlesOctopus#4.0.0-jf",
|
"libass-wasm": "https://github.com/jellyfin/JavascriptSubtitlesOctopus#4.0.0-jf-smarttv",
|
||||||
"material-design-icons-iconfont": "^5.0.1",
|
"material-design-icons-iconfont": "^5.0.1",
|
||||||
"native-promise-only": "^0.8.0-a",
|
"native-promise-only": "^0.8.0-a",
|
||||||
"page": "^1.11.5",
|
"page": "^1.11.6",
|
||||||
"query-string": "^6.11.1",
|
"query-string": "^6.11.1",
|
||||||
"resize-observer-polyfill": "^1.5.1",
|
"resize-observer-polyfill": "^1.5.1",
|
||||||
"shaka-player": "^2.5.10",
|
"screenfull": "^5.0.2",
|
||||||
|
"shaka-player": "^2.5.12",
|
||||||
"sortablejs": "^1.10.2",
|
"sortablejs": "^1.10.2",
|
||||||
"swiper": "^5.3.1",
|
"swiper": "^5.4.1",
|
||||||
"webcomponents.js": "^0.7.24",
|
"webcomponents.js": "^0.7.24",
|
||||||
"whatwg-fetch": "^3.0.0"
|
"whatwg-fetch": "^3.0.0"
|
||||||
},
|
},
|
||||||
|
@ -83,22 +90,53 @@
|
||||||
"overrides": [
|
"overrides": [
|
||||||
{
|
{
|
||||||
"test": [
|
"test": [
|
||||||
|
"src/components/accessSchedule/accessSchedule.js",
|
||||||
|
"src/components/actionSheet/actionSheet.js",
|
||||||
"src/components/autoFocuser.js",
|
"src/components/autoFocuser.js",
|
||||||
"src/components/cardbuilder/cardBuilder.js",
|
"src/components/cardbuilder/cardBuilder.js",
|
||||||
"src/components/dom.js",
|
"src/components/cardbuilder/chaptercardbuilder.js",
|
||||||
"src/components/filedownloader.js",
|
"src/components/cardbuilder/peoplecardbuilder.js",
|
||||||
"src/components/filesystem.js",
|
"src/components/images/imageLoader.js",
|
||||||
"src/components/input/keyboardnavigation.js",
|
"src/components/indicators/indicators.js",
|
||||||
"src/components/scrollManager.js",
|
"src/components/lazyLoader/lazyLoaderIntersectionObserver.js",
|
||||||
|
"src/components/playback/brightnessosd.js",
|
||||||
|
"src/components/playback/mediasession.js",
|
||||||
|
"src/components/playback/nowplayinghelper.js",
|
||||||
|
"src/components/playback/playbackorientation.js",
|
||||||
|
"src/components/playback/playerSelectionMenu.js",
|
||||||
|
"src/components/playback/playersettingsmenu.js",
|
||||||
|
"src/components/playback/playmethodhelper.js",
|
||||||
|
"src/components/playback/remotecontrolautoplay.js",
|
||||||
|
"src/components/playback/volumeosd.js",
|
||||||
|
"src/components/playmenu.js",
|
||||||
"src/components/sanatizefilename.js",
|
"src/components/sanatizefilename.js",
|
||||||
"src/scripts/settings/webSettings.js",
|
"src/components/scrollManager.js",
|
||||||
|
"src/components/syncplay/groupSelectionMenu.js",
|
||||||
|
"src/components/syncplay/playbackPermissionManager.js",
|
||||||
|
"src/components/syncplay/syncPlayManager.js",
|
||||||
|
"src/components/syncplay/timeSyncManager.js",
|
||||||
|
"src/plugins/bookPlayer/plugin.js",
|
||||||
|
"src/plugins/bookPlayer/tableOfContent.js",
|
||||||
|
"src/plugins/photoPlayer/plugin.js",
|
||||||
|
"src/scripts/deleteHelper.js",
|
||||||
|
"src/scripts/dfnshelper.js",
|
||||||
|
"src/scripts/dom.js",
|
||||||
|
"src/scripts/fileDownloader.js",
|
||||||
|
"src/scripts/filesystem.js",
|
||||||
|
"src/scripts/imagehelper.js",
|
||||||
|
"src/scripts/inputManager.js",
|
||||||
|
"src/plugins/backdropScreensaver/plugin.js",
|
||||||
|
"src/components/filterdialog/filterdialog.js",
|
||||||
|
"src/components/fetchhelper.js",
|
||||||
|
"src/scripts/keyboardNavigation.js",
|
||||||
"src/scripts/settings/appSettings.js",
|
"src/scripts/settings/appSettings.js",
|
||||||
"src/scripts/settings/userSettings.js",
|
"src/scripts/settings/userSettings.js",
|
||||||
"src/scripts/imagehelper.js",
|
"src/scripts/settings/webSettings.js"
|
||||||
"src/scripts/dfnshelper.js"
|
|
||||||
],
|
],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"@babel/plugin-transform-modules-amd"
|
"@babel/plugin-transform-modules-amd",
|
||||||
|
"@babel/plugin-proposal-class-properties",
|
||||||
|
"@babel/plugin-proposal-private-methods"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -119,12 +157,11 @@
|
||||||
"Firefox ESR"
|
"Firefox ESR"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "gulp serve",
|
"serve": "gulp serve --development",
|
||||||
"prepare": "gulp --production",
|
"prepare": "gulp --production",
|
||||||
"build:development": "gulp --development",
|
"build:development": "gulp --development",
|
||||||
"build:production": "gulp --production",
|
"build:production": "gulp --production",
|
||||||
"build:standalone": "gulp standalone --development",
|
"lint": "eslint \".\"",
|
||||||
"lint": "eslint \"src\"",
|
|
||||||
"stylelint": "stylelint \"src/**/*.css\""
|
"stylelint": "stylelint \"src/**/*.css\""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
|
const packageConfig = require('./package.json');
|
||||||
const postcssPresetEnv = require('postcss-preset-env');
|
const postcssPresetEnv = require('postcss-preset-env');
|
||||||
|
const autoprefixer = require('autoprefixer');
|
||||||
const cssnano = require('cssnano');
|
const cssnano = require('cssnano');
|
||||||
|
|
||||||
const config = () => ({
|
const config = () => ({
|
||||||
plugins: [
|
plugins: [
|
||||||
postcssPresetEnv(),
|
// Explicitly specify browserslist to override ones from node_modules
|
||||||
|
// For example, Swiper has it in its package.json
|
||||||
|
postcssPresetEnv({browsers: packageConfig.browserslist}),
|
||||||
|
autoprefixer({overrideBrowserslist: packageConfig.browserslist}),
|
||||||
cssnano()
|
cssnano()
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = config
|
module.exports = config;
|
||||||
|
|
|
@ -15,6 +15,8 @@ print(langlst)
|
||||||
input('press enter to continue')
|
input('press enter to continue')
|
||||||
|
|
||||||
keysus = []
|
keysus = []
|
||||||
|
missing = []
|
||||||
|
|
||||||
with open(langdir + '/' + 'en-us.json') as en:
|
with open(langdir + '/' + 'en-us.json') as en:
|
||||||
langus = json.load(en)
|
langus = json.load(en)
|
||||||
for key in langus:
|
for key in langus:
|
||||||
|
@ -32,10 +34,19 @@ for lang in langlst:
|
||||||
for key in langjson:
|
for key in langjson:
|
||||||
if key in keysus:
|
if key in keysus:
|
||||||
langjnew[key] = langjson[key]
|
langjnew[key] = langjson[key]
|
||||||
|
elif key not in missing:
|
||||||
|
missing.append(key)
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
f.write(json.dumps(langjnew, indent=inde, sort_keys=False, ensure_ascii=False))
|
f.write(json.dumps(langjnew, indent=inde, sort_keys=False, ensure_ascii=False))
|
||||||
f.write('\n')
|
f.write('\n')
|
||||||
f.truncate()
|
f.truncate()
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
print(missing)
|
||||||
|
print('LENGTH: ' + str(len(missing)))
|
||||||
|
with open('missing.txt', 'w') as out:
|
||||||
|
for item in missing:
|
||||||
|
out.write(item + '\n')
|
||||||
|
out.close()
|
||||||
|
|
||||||
print('DONE')
|
print('DONE')
|
||||||
|
|
|
@ -34,7 +34,7 @@ for lang in langlst:
|
||||||
|
|
||||||
print(dep)
|
print(dep)
|
||||||
print('LENGTH: ' + str(len(dep)))
|
print('LENGTH: ' + str(len(dep)))
|
||||||
with open('scout.txt', 'w') as out:
|
with open('unused.txt', 'w') as out:
|
||||||
for item in dep:
|
for item in dep:
|
||||||
out.write(item + '\n')
|
out.write(item + '\n')
|
||||||
out.close()
|
out.close()
|
||||||
|
|
|
@ -5,12 +5,11 @@
|
||||||
<div class="verticalSection">
|
<div class="verticalSection">
|
||||||
<div class="sectionTitleContainer flex align-items-center">
|
<div class="sectionTitleContainer flex align-items-center">
|
||||||
<h1 class="sectionTitle pluginName"></h1>
|
<h1 class="sectionTitle pluginName"></h1>
|
||||||
<a is="emby-linkbutton" class="raised button-alt headerHelpButton" target="_blank" href="https://docs.jellyfin.org/general/server/plugins/index.html">${Help}</a>
|
<a is="emby-linkbutton" rel="noopener noreferrer" class="raised button-alt headerHelpButton" target="_blank" href="https://docs.jellyfin.org/general/server/plugins/index.html">${Help}</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p id="tagline" style="font-style: italic;"></p>
|
<p id="overview" style="font-style: italic;"></p>
|
||||||
<p id="pPreviewImage"></p>
|
<p id="description"></p>
|
||||||
<p id="overview"></p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="verticalSection">
|
<div class="verticalSection">
|
||||||
|
@ -28,7 +27,6 @@
|
||||||
</button>
|
</button>
|
||||||
<div class="fieldDescription">${ServerRestartNeededAfterPluginInstall}</div>
|
<div class="fieldDescription">${ServerRestartNeededAfterPluginInstall}</div>
|
||||||
</div>
|
</div>
|
||||||
<p id="nonServerMsg"></p>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -37,9 +35,6 @@
|
||||||
<div is="emby-collapse" title="${HeaderDeveloperInfo}">
|
<div is="emby-collapse" title="${HeaderDeveloperInfo}">
|
||||||
<div class="collapseContent">
|
<div class="collapseContent">
|
||||||
<p id="developer"></p>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<form class="addServerForm" style="margin: 0 auto;">
|
<form class="addServerForm" style="margin: 0 auto;">
|
||||||
<h1>${HeaderConnectToServer}</h1>
|
<h1>${HeaderConnectToServer}</h1>
|
||||||
<div class="inputContainer">
|
<div class="inputContainer">
|
||||||
<input is="emby-input" type="text" id="txtServerHost" required="required" label="${LabelServerHost}" autocomplete="off" spellcheck="false" autocapitalize="none" autocorrect="off" />
|
<input is="emby-input" type="url" id="txtServerHost" required="required" label="${LabelServerHost}"/>
|
||||||
<div class="fieldDescription">${LabelServerHostHelp}</div>
|
<div class="fieldDescription">${LabelServerHostHelp}</div>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
|
|
|
@ -4,18 +4,19 @@
|
||||||
<div class="detailSectionHeader">
|
<div class="detailSectionHeader">
|
||||||
<h2 style="margin:.6em 0;vertical-align:middle;display:inline-block;">${HeaderApiKeys}</h2>
|
<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}">
|
<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" aria-hidden="true"></span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<p>${HeaderApiKeysHelp}</p>
|
<p>${HeaderApiKeysHelp}</p>
|
||||||
<br />
|
<br />
|
||||||
<table class="tblApiKeys detailTable">
|
<table class="tblApiKeys detailTable">
|
||||||
|
<caption class="clipForScreenReader">${ApiKeysCaption}</caption>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="detailTableHeaderCell"></th>
|
<th scope="col" class="detailTableHeaderCell"></th>
|
||||||
<th class="detailTableHeaderCell">${HeaderApiKey}</th>
|
<th scope="col" class="detailTableHeaderCell">${HeaderApiKey}</th>
|
||||||
<th class="detailTableHeaderCell">${HeaderApp}</th>
|
<th scope="col" class="detailTableHeaderCell">${HeaderApp}</th>
|
||||||
<th class="detailTableHeaderCell">${HeaderDateIssued}</th>
|
<th scope="col" class="detailTableHeaderCell">${HeaderDateIssued}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="resultBody"></tbody>
|
<tbody class="resultBody"></tbody>
|
||||||
|
|
BIN
src/assets/audio/silence.mp3
Normal file
BIN
src/assets/audio/silence.mp3
Normal file
Binary file not shown.
|
@ -21,7 +21,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.libraryPage {
|
.libraryPage {
|
||||||
padding-top: 7em;
|
padding-top: 7em !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-mobile .libraryPage {
|
||||||
|
padding-top: 4em !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.itemDetailPage {
|
.itemDetailPage {
|
||||||
|
@ -128,10 +132,6 @@
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout-mobile .pageTitleWithDefaultLogo {
|
|
||||||
background-image: url(../img/icon-transparent.png);
|
|
||||||
}
|
|
||||||
|
|
||||||
.headerLeft,
|
.headerLeft,
|
||||||
.skinHeader {
|
.skinHeader {
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
|
@ -242,10 +242,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.mainDrawer-scrollContainer {
|
.mainDrawer-scrollContainer {
|
||||||
margin-bottom: 10vh;
|
padding-bottom: 10vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (min-width: 40em) {
|
@media all and (min-width: 40em) {
|
||||||
|
.dashboardDocument .adminDrawerLogo,
|
||||||
.dashboardDocument .mainDrawerButton {
|
.dashboardDocument .mainDrawerButton {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
@ -313,7 +314,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboardDocument .mainDrawer-scrollContainer {
|
.dashboardDocument .mainDrawer-scrollContainer {
|
||||||
margin-top: 4.6em !important;
|
margin-top: 4.65em !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,6 +517,13 @@
|
||||||
|
|
||||||
.itemName {
|
.itemName {
|
||||||
margin: 0.5em 0;
|
margin: 0.5em 0;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nameContainer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.itemMiscInfo {
|
.itemMiscInfo {
|
||||||
|
@ -533,7 +541,6 @@
|
||||||
.layout-mobile .itemName,
|
.layout-mobile .itemName,
|
||||||
.layout-mobile .itemMiscInfo,
|
.layout-mobile .itemMiscInfo,
|
||||||
.layout-mobile .mainDetailButtons {
|
.layout-mobile .mainDetailButtons {
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -575,7 +582,6 @@
|
||||||
|
|
||||||
.infoText {
|
.infoText {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
@ -606,12 +612,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.detailLogo {
|
.detailLogo {
|
||||||
width: 67.25vw;
|
width: 30vw;
|
||||||
height: 14.5vh;
|
height: 25vh;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 15vh;
|
top: 10vh;
|
||||||
right: 0;
|
right: 20vw;
|
||||||
-webkit-background-size: contain;
|
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -619,26 +624,8 @@
|
||||||
display: none;
|
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) {
|
@media all and (max-width: 68.75em) {
|
||||||
.detailLogo {
|
.detailLogo {
|
||||||
width: 14.91em;
|
|
||||||
height: 3.5em;
|
|
||||||
right: 5%;
|
|
||||||
bottom: 5%;
|
|
||||||
top: auto;
|
|
||||||
background-position: center right;
|
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -657,12 +644,7 @@ div.itemDetailGalleryLink.defaultCardBackground {
|
||||||
height: 23vw; /* Dirty hack to get it to look somewhat square. Less than ideal. */
|
height: 23vw; /* Dirty hack to get it to look somewhat square. Less than ideal. */
|
||||||
}
|
}
|
||||||
|
|
||||||
.btnSyncComplete i {
|
.itemDetailGalleryLink.defaultCardBackground > .material-icons {
|
||||||
-webkit-border-radius: 100em;
|
|
||||||
border-radius: 100em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.itemDetailGalleryLink.defaultCardBackground > i {
|
|
||||||
font-size: 15vw;
|
font-size: 15vw;
|
||||||
margin-top: 50%;
|
margin-top: 50%;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
|
@ -694,10 +676,6 @@ div.itemDetailGalleryLink.defaultCardBackground {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btnSyncComplete {
|
|
||||||
background: #673ab7 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.emby-button.detailFloatingButton {
|
.emby-button.detailFloatingButton {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: rgba(0, 0, 0, 0.5) !important;
|
background-color: rgba(0, 0, 0, 0.5) !important;
|
||||||
|
@ -709,7 +687,7 @@ div.itemDetailGalleryLink.defaultCardBackground {
|
||||||
color: rgba(255, 255, 255, 0.76);
|
color: rgba(255, 255, 255, 0.76);
|
||||||
}
|
}
|
||||||
|
|
||||||
.emby-button.detailFloatingButton i {
|
.emby-button.detailFloatingButton .material-icons {
|
||||||
font-size: 3.5em;
|
font-size: 3.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1166,3 +1144,21 @@ div:not(.sectionTitleContainer-cards) > .sectionTitle-cards {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
font-size: 1.4em;
|
font-size: 1.4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.overview-controls {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-clamp-text {
|
||||||
|
overflow: hidden;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 12;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 40em) {
|
||||||
|
.detail-clamp-text {
|
||||||
|
-webkit-line-clamp: 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,17 @@ html {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.clipForScreenReader {
|
||||||
|
clip: rect(1px, 1px, 1px, 1px);
|
||||||
|
clip-path: inset(50%);
|
||||||
|
height: 1px;
|
||||||
|
width: 1px;
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
.material-icons {
|
.material-icons {
|
||||||
/* Fix font ligatures on older WebOS versions */
|
/* Fix font ligatures on older WebOS versions */
|
||||||
-webkit-font-feature-settings: "liga";
|
-webkit-font-feature-settings: "liga";
|
||||||
|
@ -96,3 +107,24 @@ div[data-role=page] {
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
width: 85%;
|
width: 85%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.headroom {
|
||||||
|
will-change: transform;
|
||||||
|
transition: transform 200ms linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headroom--pinned {
|
||||||
|
transform: translateY(0%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.headroom--unpinned {
|
||||||
|
transform: translateY(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.force-scroll {
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide-scroll {
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.osdHeader .headerButton:not(.headerBackButton):not(.headerCastButton) {
|
.osdHeader .headerButton:not(.headerBackButton):not(.headerCastButton):not(.headerSyncButton) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
154
src/bundle.js
154
src/bundle.js
|
@ -5,127 +5,185 @@
|
||||||
var _define = window.define;
|
var _define = window.define;
|
||||||
|
|
||||||
// document-register-element
|
// document-register-element
|
||||||
var docRegister = require("document-register-element");
|
var docRegister = require('document-register-element');
|
||||||
_define("document-register-element", function() {
|
_define('document-register-element', function() {
|
||||||
return docRegister;
|
return docRegister;
|
||||||
});
|
});
|
||||||
|
|
||||||
// fetch
|
// fetch
|
||||||
var fetch = require("whatwg-fetch");
|
var fetch = require('whatwg-fetch');
|
||||||
_define("fetch", function() {
|
_define('fetch', function() {
|
||||||
return fetch;
|
return fetch;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Blurhash
|
||||||
|
var blurhash = require('blurhash');
|
||||||
|
_define('blurhash', function() {
|
||||||
|
return blurhash;
|
||||||
|
});
|
||||||
|
|
||||||
// query-string
|
// query-string
|
||||||
var query = require("query-string");
|
var query = require('query-string');
|
||||||
_define("queryString", function() {
|
_define('queryString', function() {
|
||||||
return query;
|
return query;
|
||||||
});
|
});
|
||||||
|
|
||||||
// flvjs
|
// flvjs
|
||||||
var flvjs = require("flv.js/dist/flv").default;
|
var flvjs = require('flv.js/dist/flv').default;
|
||||||
_define("flvjs", function() {
|
_define('flvjs', function() {
|
||||||
return flvjs;
|
return flvjs;
|
||||||
});
|
});
|
||||||
|
|
||||||
// jstree
|
// jstree
|
||||||
var jstree = require("jstree");
|
var jstree = require('jstree');
|
||||||
require("jstree/dist/themes/default/style.css");
|
require('jstree/dist/themes/default/style.css');
|
||||||
_define("jstree", function() {
|
_define('jstree', function() {
|
||||||
return jstree;
|
return jstree;
|
||||||
});
|
});
|
||||||
|
|
||||||
// jquery
|
// jquery
|
||||||
var jquery = require("jquery");
|
var jquery = require('jquery');
|
||||||
_define("jQuery", function() {
|
_define('jQuery', function() {
|
||||||
return jquery;
|
return jquery;
|
||||||
});
|
});
|
||||||
|
|
||||||
// hlsjs
|
// hlsjs
|
||||||
var hlsjs = require("hls.js");
|
var hlsjs = require('hls.js');
|
||||||
_define("hlsjs", function() {
|
_define('hlsjs', function() {
|
||||||
return hlsjs;
|
return hlsjs;
|
||||||
});
|
});
|
||||||
|
|
||||||
// howler
|
// howler
|
||||||
var howler = require("howler");
|
var howler = require('howler');
|
||||||
_define("howler", function() {
|
_define('howler', function() {
|
||||||
return howler;
|
return howler;
|
||||||
});
|
});
|
||||||
|
|
||||||
// resize-observer-polyfill
|
// resize-observer-polyfill
|
||||||
var resize = require("resize-observer-polyfill").default;
|
var resize = require('resize-observer-polyfill').default;
|
||||||
_define("resize-observer-polyfill", function() {
|
_define('resize-observer-polyfill', function() {
|
||||||
return resize;
|
return resize;
|
||||||
});
|
});
|
||||||
|
|
||||||
// shaka
|
// shaka
|
||||||
var shaka = require("shaka-player");
|
var shaka = require('shaka-player');
|
||||||
_define("shaka", function() {
|
_define('shaka', function() {
|
||||||
return shaka;
|
return shaka;
|
||||||
});
|
});
|
||||||
|
|
||||||
// swiper
|
// swiper
|
||||||
var swiper = require("swiper/js/swiper");
|
var swiper = require('swiper/js/swiper');
|
||||||
require("swiper/css/swiper.min.css");
|
require('swiper/css/swiper.min.css');
|
||||||
_define("swiper", function() {
|
_define('swiper', function() {
|
||||||
return swiper;
|
return swiper;
|
||||||
});
|
});
|
||||||
|
|
||||||
// sortable
|
// sortable
|
||||||
var sortable = require("sortablejs").default;
|
var sortable = require('sortablejs').default;
|
||||||
_define("sortable", function() {
|
_define('sortable', function() {
|
||||||
return sortable;
|
return sortable;
|
||||||
});
|
});
|
||||||
|
|
||||||
// webcomponents
|
// webcomponents
|
||||||
var webcomponents = require("webcomponents.js/webcomponents-lite");
|
var webcomponents = require('webcomponents.js/webcomponents-lite');
|
||||||
_define("webcomponents", function() {
|
_define('webcomponents', function() {
|
||||||
return webcomponents;
|
return webcomponents;
|
||||||
});
|
});
|
||||||
|
|
||||||
// libass-wasm
|
// libass-wasm
|
||||||
var libass_wasm = require("libass-wasm");
|
var libassWasm = require('libass-wasm');
|
||||||
_define("JavascriptSubtitlesOctopus", function() {
|
_define('JavascriptSubtitlesOctopus', function() {
|
||||||
return libass_wasm;
|
return libassWasm;
|
||||||
});
|
});
|
||||||
|
|
||||||
// material-icons
|
// material-icons
|
||||||
var material_icons = require("material-design-icons-iconfont/dist/material-design-icons.css");
|
var materialIcons = require('material-design-icons-iconfont/dist/material-design-icons.css');
|
||||||
_define("material-icons", function() {
|
_define('material-icons', function() {
|
||||||
return material_icons;
|
return materialIcons;
|
||||||
});
|
});
|
||||||
|
|
||||||
// noto font
|
// noto font
|
||||||
var noto = require("jellyfin-noto");
|
var noto = require('jellyfin-noto');
|
||||||
_define("jellyfin-noto", function () {
|
_define('jellyfin-noto', function () {
|
||||||
return noto;
|
return noto;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var epubjs = require('epubjs');
|
||||||
|
_define('epubjs', function () {
|
||||||
|
return epubjs;
|
||||||
|
});
|
||||||
|
|
||||||
// page.js
|
// page.js
|
||||||
var page = require("page");
|
var page = require('page');
|
||||||
_define("page", function() {
|
_define('page', function() {
|
||||||
return page;
|
return page;
|
||||||
});
|
});
|
||||||
|
|
||||||
var polyfill = require("@babel/polyfill/dist/polyfill");
|
// core-js
|
||||||
_define("polyfill", function () {
|
var polyfill = require('@babel/polyfill/dist/polyfill');
|
||||||
|
_define('polyfill', function () {
|
||||||
return polyfill;
|
return polyfill;
|
||||||
});
|
});
|
||||||
|
|
||||||
// domtokenlist-shim
|
// domtokenlist-shim
|
||||||
var classlist = require("classlist.js");
|
var classlist = require('classlist.js');
|
||||||
_define("classlist-polyfill", function () {
|
_define('classlist-polyfill', function () {
|
||||||
return classlist;
|
return classlist;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Date-FNS
|
// Date-FNS
|
||||||
var date_fns = require("date-fns");
|
var dateFns = require('date-fns');
|
||||||
_define("date-fns", function () {
|
_define('date-fns', function () {
|
||||||
return date_fns;
|
return dateFns;
|
||||||
});
|
});
|
||||||
|
|
||||||
var date_fns_locale = require("date-fns/locale");
|
var dateFnsLocale = require('date-fns/locale');
|
||||||
_define("date-fns/locale", function () {
|
_define('date-fns/locale', function () {
|
||||||
return date_fns_locale;
|
return dateFnsLocale;
|
||||||
|
});
|
||||||
|
|
||||||
|
var fast_text_encoding = require('fast-text-encoding');
|
||||||
|
_define('fast-text-encoding', function () {
|
||||||
|
return fast_text_encoding;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 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;
|
||||||
});
|
});
|
||||||
|
|
98
src/components/accessSchedule/accessSchedule.js
Normal file
98
src/components/accessSchedule/accessSchedule.js
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
/* eslint-disable indent */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module for controlling user parental control from.
|
||||||
|
* @module components/accessSchedule/accessSchedule
|
||||||
|
*/
|
||||||
|
|
||||||
|
import dialogHelper from 'dialogHelper';
|
||||||
|
import datetime from 'datetime';
|
||||||
|
import globalize from 'globalize';
|
||||||
|
import 'emby-select';
|
||||||
|
import 'paper-icon-button-light';
|
||||||
|
import 'formDialogStyle';
|
||||||
|
|
||||||
|
function getDisplayTime(hours) {
|
||||||
|
let minutes = 0;
|
||||||
|
const pct = hours % 1;
|
||||||
|
|
||||||
|
if (pct) {
|
||||||
|
minutes = parseInt(60 * pct);
|
||||||
|
}
|
||||||
|
|
||||||
|
return datetime.getDisplayTime(new Date(2000, 1, 1, hours, minutes, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
function populateHours(context) {
|
||||||
|
let html = '';
|
||||||
|
|
||||||
|
for (let i = 0; i < 24; i++) {
|
||||||
|
html += `<option value="${i}">${getDisplayTime(i)}</option>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
html += `<option value="24">${getDisplayTime(0)}</option>`;
|
||||||
|
context.querySelector('#selectStart').innerHTML = html;
|
||||||
|
context.querySelector('#selectEnd').innerHTML = html;
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadSchedule(context, {DayOfWeek, StartHour, EndHour}) {
|
||||||
|
context.querySelector('#selectDay').value = DayOfWeek || 'Sunday';
|
||||||
|
context.querySelector('#selectStart').value = StartHour || 0;
|
||||||
|
context.querySelector('#selectEnd').value = EndHour || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function submitSchedule(context, options) {
|
||||||
|
const updatedSchedule = {
|
||||||
|
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'));
|
||||||
|
}
|
||||||
|
|
||||||
|
context.submitted = true;
|
||||||
|
options.schedule = Object.assign(options.schedule, updatedSchedule);
|
||||||
|
dialogHelper.close(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function show(options) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// TODO: remove require
|
||||||
|
require(['text!./components/accessSchedule/accessSchedule.template.html'], template => {
|
||||||
|
const dlg = dialogHelper.createDialog({
|
||||||
|
removeOnClose: true,
|
||||||
|
size: 'small'
|
||||||
|
});
|
||||||
|
dlg.classList.add('formDialog');
|
||||||
|
let html = '';
|
||||||
|
html += globalize.translateDocument(template);
|
||||||
|
dlg.innerHTML = html;
|
||||||
|
populateHours(dlg);
|
||||||
|
loadSchedule(dlg, options.schedule);
|
||||||
|
dialogHelper.open(dlg);
|
||||||
|
dlg.addEventListener('close', () => {
|
||||||
|
if (dlg.submitted) {
|
||||||
|
resolve(options.schedule);
|
||||||
|
} else {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dlg.querySelector('.btnCancel').addEventListener('click', () => {
|
||||||
|
dialogHelper.close(dlg);
|
||||||
|
});
|
||||||
|
dlg.querySelector('form').addEventListener('submit', event => {
|
||||||
|
submitSchedule(dlg, options);
|
||||||
|
event.preventDefault();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eslint-enable indent */
|
||||||
|
|
||||||
|
export default {
|
||||||
|
show: show
|
||||||
|
};
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="formDialogHeader">
|
<div class="formDialogHeader">
|
||||||
<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1">
|
<button is="paper-icon-button-light" class="btnCancel autoSize" title="${LabelPrevious}" tabindex="-1">
|
||||||
<i class="material-icons arrow_back"></i>
|
<span class="material-icons arrow_back" aria-hidden="true"></span>
|
||||||
</button>
|
</button>
|
||||||
<h3 class="formDialogHeaderTitle">
|
<h3 class="formDialogHeaderTitle">
|
||||||
${HeaderAccessSchedule}
|
${HeaderAccessSchedule}
|
|
@ -1,89 +0,0 @@
|
||||||
define(["dialogHelper", "datetime", "emby-select", "paper-icon-button-light", "formDialogStyle"], function (dialogHelper, datetime) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
function getDisplayTime(hours) {
|
|
||||||
var minutes = 0;
|
|
||||||
var pct = hours % 1;
|
|
||||||
|
|
||||||
if (pct) {
|
|
||||||
minutes = parseInt(60 * pct);
|
|
||||||
}
|
|
||||||
|
|
||||||
return datetime.getDisplayTime(new Date(2000, 1, 1, hours, minutes, 0, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
function populateHours(context) {
|
|
||||||
var html = "";
|
|
||||||
|
|
||||||
for (var i = 0; i < 24; i++) {
|
|
||||||
html += '<option value="' + i + '">' + getDisplayTime(i) + "</option>";
|
|
||||||
}
|
|
||||||
|
|
||||||
html += '<option value="24">' + getDisplayTime(0) + "</option>";
|
|
||||||
context.querySelector("#selectStart").innerHTML = html;
|
|
||||||
context.querySelector("#selectEnd").innerHTML = html;
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadSchedule(context, schedule) {
|
|
||||||
context.querySelector("#selectDay").value = schedule.DayOfWeek || "Sunday";
|
|
||||||
context.querySelector("#selectStart").value = schedule.StartHour || 0;
|
|
||||||
context.querySelector("#selectEnd").value = schedule.EndHour || 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function submitSchedule(context, options) {
|
|
||||||
var updatedSchedule = {
|
|
||||||
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"));
|
|
||||||
}
|
|
||||||
|
|
||||||
context.submitted = true;
|
|
||||||
options.schedule = Object.assign(options.schedule, updatedSchedule);
|
|
||||||
dialogHelper.close(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
show: function (options) {
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.open("GET", "components/accessschedule/accessschedule.template.html", true);
|
|
||||||
|
|
||||||
xhr.onload = function (e) {
|
|
||||||
var template = this.response;
|
|
||||||
var dlg = dialogHelper.createDialog({
|
|
||||||
removeOnClose: true,
|
|
||||||
size: "small"
|
|
||||||
});
|
|
||||||
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 () {
|
|
||||||
if (dlg.submitted) {
|
|
||||||
resolve(options.schedule);
|
|
||||||
} else {
|
|
||||||
reject();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
dlg.querySelector(".btnCancel").addEventListener("click", function (e) {
|
|
||||||
dialogHelper.close(dlg);
|
|
||||||
});
|
|
||||||
dlg.querySelector("form").addEventListener("submit", function (e) {
|
|
||||||
submitSchedule(dlg, options);
|
|
||||||
e.preventDefault();
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
xhr.send();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
340
src/components/actionSheet/actionSheet.js
Normal file
340
src/components/actionSheet/actionSheet.js
Normal file
|
@ -0,0 +1,340 @@
|
||||||
|
import dialogHelper from 'dialogHelper';
|
||||||
|
import layoutManager from 'layoutManager';
|
||||||
|
import globalize from 'globalize';
|
||||||
|
import dom from 'dom';
|
||||||
|
import 'emby-button';
|
||||||
|
import 'css!./actionSheet';
|
||||||
|
import 'material-icons';
|
||||||
|
import 'scrollStyles';
|
||||||
|
import 'listViewStyle';
|
||||||
|
|
||||||
|
function getOffsets(elems) {
|
||||||
|
|
||||||
|
let results = [];
|
||||||
|
|
||||||
|
if (!document) {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let elem of elems) {
|
||||||
|
let box = elem.getBoundingClientRect();
|
||||||
|
|
||||||
|
results.push({
|
||||||
|
top: box.top,
|
||||||
|
left: box.left,
|
||||||
|
width: box.width,
|
||||||
|
height: box.height
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPosition(options, dlg) {
|
||||||
|
|
||||||
|
const windowSize = dom.getWindowSize();
|
||||||
|
const windowHeight = windowSize.innerHeight;
|
||||||
|
const windowWidth = windowSize.innerWidth;
|
||||||
|
|
||||||
|
let pos = getOffsets([options.positionTo])[0];
|
||||||
|
|
||||||
|
if (options.positionY !== 'top') {
|
||||||
|
pos.top += (pos.height || 0) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos.left += (pos.width || 0) / 2;
|
||||||
|
|
||||||
|
const height = dlg.offsetHeight || 300;
|
||||||
|
const width = dlg.offsetWidth || 160;
|
||||||
|
|
||||||
|
// Account for popup size
|
||||||
|
pos.top -= height / 2;
|
||||||
|
pos.left -= width / 2;
|
||||||
|
|
||||||
|
// Avoid showing too close to the bottom
|
||||||
|
const overflowX = pos.left + width - windowWidth;
|
||||||
|
const overflowY = pos.top + height - windowHeight;
|
||||||
|
|
||||||
|
if (overflowX > 0) {
|
||||||
|
pos.left -= (overflowX + 20);
|
||||||
|
}
|
||||||
|
if (overflowY > 0) {
|
||||||
|
pos.top -= (overflowY + 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos.top += (options.offsetTop || 0);
|
||||||
|
pos.left += (options.offsetLeft || 0);
|
||||||
|
|
||||||
|
// Do some boundary checking
|
||||||
|
pos.top = Math.max(pos.top, 10);
|
||||||
|
pos.left = Math.max(pos.left, 10);
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
function centerFocus(elem, horiz, on) {
|
||||||
|
require(['scrollHelper'], function (scrollHelper) {
|
||||||
|
const fn = on ? 'on' : 'off';
|
||||||
|
scrollHelper.centerFocus[fn](elem, horiz);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function show(options) {
|
||||||
|
|
||||||
|
// items
|
||||||
|
// positionTo
|
||||||
|
// showCancel
|
||||||
|
// title
|
||||||
|
let dialogOptions = {
|
||||||
|
removeOnClose: true,
|
||||||
|
enableHistory: options.enableHistory,
|
||||||
|
scrollY: false
|
||||||
|
};
|
||||||
|
|
||||||
|
let isFullscreen;
|
||||||
|
|
||||||
|
if (layoutManager.tv) {
|
||||||
|
dialogOptions.size = 'fullscreen';
|
||||||
|
isFullscreen = true;
|
||||||
|
dialogOptions.autoFocus = true;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
dialogOptions.modal = false;
|
||||||
|
dialogOptions.entryAnimation = options.entryAnimation;
|
||||||
|
dialogOptions.exitAnimation = options.exitAnimation;
|
||||||
|
dialogOptions.entryAnimationDuration = options.entryAnimationDuration || 140;
|
||||||
|
dialogOptions.exitAnimationDuration = options.exitAnimationDuration || 100;
|
||||||
|
dialogOptions.autoFocus = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let dlg = dialogHelper.createDialog(dialogOptions);
|
||||||
|
|
||||||
|
if (isFullscreen) {
|
||||||
|
dlg.classList.add('actionsheet-fullscreen');
|
||||||
|
} else {
|
||||||
|
dlg.classList.add('actionsheet-not-fullscreen');
|
||||||
|
}
|
||||||
|
|
||||||
|
dlg.classList.add('actionSheet');
|
||||||
|
|
||||||
|
if (options.dialogClass) {
|
||||||
|
dlg.classList.add(options.dialogClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
let html = '';
|
||||||
|
|
||||||
|
const scrollClassName = layoutManager.tv ? 'scrollY smoothScrollY hiddenScrollY' : 'scrollY';
|
||||||
|
let style = '';
|
||||||
|
|
||||||
|
// Admittedly a hack but right now the scrollbar is being factored into the width which is causing truncation
|
||||||
|
if (options.items.length > 20) {
|
||||||
|
const minWidth = dom.getWindowSize().innerWidth >= 300 ? 240 : 200;
|
||||||
|
style += 'min-width:' + minWidth + 'px;';
|
||||||
|
}
|
||||||
|
|
||||||
|
let renderIcon = false;
|
||||||
|
let icons = [];
|
||||||
|
let itemIcon;
|
||||||
|
for (let item of options.items) {
|
||||||
|
|
||||||
|
itemIcon = item.icon || (item.selected ? 'check' : null);
|
||||||
|
|
||||||
|
if (itemIcon) {
|
||||||
|
renderIcon = true;
|
||||||
|
}
|
||||||
|
icons.push(itemIcon || '');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layoutManager.tv) {
|
||||||
|
html += `<button is="paper-icon-button-light" class="btnCloseActionSheet hide-mouse-idle-tv" tabindex="-1">
|
||||||
|
<span class="material-icons arrow_back"></span>
|
||||||
|
</button>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If any items have an icon, give them all an icon just to make sure they're all lined up evenly
|
||||||
|
const center = options.title && (!renderIcon /*|| itemsWithIcons.length != options.items.length*/);
|
||||||
|
|
||||||
|
if (center || layoutManager.tv) {
|
||||||
|
html += '<div class="actionSheetContent actionSheetContent-centered">';
|
||||||
|
} else {
|
||||||
|
html += '<div class="actionSheetContent">';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.title) {
|
||||||
|
|
||||||
|
html += '<h1 class="actionSheetTitle">' + options.title + '</h1>';
|
||||||
|
}
|
||||||
|
if (options.text) {
|
||||||
|
html += '<p class="actionSheetText">' + options.text + '</p>';
|
||||||
|
}
|
||||||
|
|
||||||
|
let scrollerClassName = 'actionSheetScroller';
|
||||||
|
if (layoutManager.tv) {
|
||||||
|
scrollerClassName += ' actionSheetScroller-tv focuscontainer-x focuscontainer-y';
|
||||||
|
}
|
||||||
|
html += '<div class="' + scrollerClassName + ' ' + scrollClassName + '" style="' + style + '">';
|
||||||
|
|
||||||
|
let menuItemClass = 'listItem listItem-button actionSheetMenuItem';
|
||||||
|
|
||||||
|
if (options.border || options.shaded) {
|
||||||
|
menuItemClass += ' listItem-border';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.menuItemClass) {
|
||||||
|
menuItemClass += ' ' + options.menuItemClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layoutManager.tv) {
|
||||||
|
menuItemClass += ' listItem-focusscale';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layoutManager.mobile) {
|
||||||
|
menuItemClass += ' actionsheet-xlargeFont';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'options.items' is HTMLOptionsCollection, so no fancy loops
|
||||||
|
for (let i = 0; i < options.items.length; i++) {
|
||||||
|
const item = options.items[i];
|
||||||
|
|
||||||
|
if (item.divider) {
|
||||||
|
|
||||||
|
html += '<div class="actionsheetDivider"></div>';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const autoFocus = item.selected && layoutManager.tv ? ' autoFocus' : '';
|
||||||
|
|
||||||
|
// Check for null in case int 0 was passed in
|
||||||
|
const optionId = item.id == null || item.id === '' ? item.value : item.id;
|
||||||
|
html += '<button' + autoFocus + ' is="emby-button" type="button" class="' + menuItemClass + '" data-id="' + optionId + '">';
|
||||||
|
|
||||||
|
itemIcon = icons[i];
|
||||||
|
|
||||||
|
if (itemIcon) {
|
||||||
|
html += `<span class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons ${itemIcon}"></span>`;
|
||||||
|
} else if (renderIcon && !center) {
|
||||||
|
html += '<span class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons check" style="visibility:hidden;"></span>';
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '<div class="listItemBody actionsheetListItemBody">';
|
||||||
|
|
||||||
|
html += '<div class="listItemBodyText actionSheetItemText">';
|
||||||
|
html += (item.name || item.textContent || item.innerText);
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
if (item.secondaryText) {
|
||||||
|
html += `<div class="listItemBodyText secondary">${item.secondaryText}</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
if (item.asideText) {
|
||||||
|
html += `<div class="listItemAside actionSheetItemAsideText">${item.asideText}</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '</button>';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.showCancel) {
|
||||||
|
html += '<div class="buttons">';
|
||||||
|
html += `<button is="emby-button" type="button" class="btnCloseActionSheet">${globalize.translate('ButtonCancel')}</button>`;
|
||||||
|
html += '</div>';
|
||||||
|
}
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
dlg.innerHTML = html;
|
||||||
|
|
||||||
|
if (layoutManager.tv) {
|
||||||
|
centerFocus(dlg.querySelector('.actionSheetScroller'), false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
let btnCloseActionSheet = dlg.querySelector('.btnCloseActionSheet');
|
||||||
|
if (btnCloseActionSheet) {
|
||||||
|
btnCloseActionSheet.addEventListener('click', function () {
|
||||||
|
dialogHelper.close(dlg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seeing an issue in some non-chrome browsers where this is requiring a double click
|
||||||
|
//var eventName = browser.firefox ? 'mousedown' : 'click';
|
||||||
|
let selectedId;
|
||||||
|
|
||||||
|
let timeout;
|
||||||
|
if (options.timeout) {
|
||||||
|
timeout = setTimeout(function () {
|
||||||
|
dialogHelper.close(dlg);
|
||||||
|
}, options.timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
|
||||||
|
let isResolved;
|
||||||
|
|
||||||
|
dlg.addEventListener('click', function (e) {
|
||||||
|
|
||||||
|
const actionSheetMenuItem = dom.parentWithClass(e.target, 'actionSheetMenuItem');
|
||||||
|
|
||||||
|
if (actionSheetMenuItem) {
|
||||||
|
selectedId = actionSheetMenuItem.getAttribute('data-id');
|
||||||
|
|
||||||
|
if (options.resolveOnClick) {
|
||||||
|
|
||||||
|
if (options.resolveOnClick.indexOf) {
|
||||||
|
|
||||||
|
if (options.resolveOnClick.indexOf(selectedId) !== -1) {
|
||||||
|
|
||||||
|
resolve(selectedId);
|
||||||
|
isResolved = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
resolve(selectedId);
|
||||||
|
isResolved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dialogHelper.close(dlg);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
dlg.addEventListener('close', function () {
|
||||||
|
|
||||||
|
if (layoutManager.tv) {
|
||||||
|
centerFocus(dlg.querySelector('.actionSheetScroller'), false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeout) {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
timeout = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isResolved) {
|
||||||
|
if (selectedId != null) {
|
||||||
|
if (options.callback) {
|
||||||
|
options.callback(selectedId);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(selectedId);
|
||||||
|
} else {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dialogHelper.open(dlg);
|
||||||
|
|
||||||
|
const pos = options.positionTo && dialogOptions.size !== 'fullscreen' ? getPosition(options, dlg) : null;
|
||||||
|
|
||||||
|
if (pos) {
|
||||||
|
dlg.style.position = 'fixed';
|
||||||
|
dlg.style.margin = 0;
|
||||||
|
dlg.style.left = pos.left + 'px';
|
||||||
|
dlg.style.top = pos.top + 'px';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
show: show
|
||||||
|
};
|
|
@ -1,360 +0,0 @@
|
||||||
define(['dialogHelper', 'layoutManager', 'globalize', 'browser', 'dom', 'emby-button', 'css!./actionsheet', 'material-icons', 'scrollStyles', 'listViewStyle'], function (dialogHelper, layoutManager, globalize, browser, dom) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
function getOffsets(elems) {
|
|
||||||
|
|
||||||
var doc = document;
|
|
||||||
var results = [];
|
|
||||||
|
|
||||||
if (!doc) {
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
var box;
|
|
||||||
var elem;
|
|
||||||
|
|
||||||
for (var i = 0, length = elems.length; i < length; i++) {
|
|
||||||
|
|
||||||
elem = elems[i];
|
|
||||||
// Support: BlackBerry 5, iOS 3 (original iPhone)
|
|
||||||
// If we don't have gBCR, just use 0,0 rather than error
|
|
||||||
if (elem.getBoundingClientRect) {
|
|
||||||
box = elem.getBoundingClientRect();
|
|
||||||
} else {
|
|
||||||
box = { top: 0, left: 0 };
|
|
||||||
}
|
|
||||||
|
|
||||||
results[i] = {
|
|
||||||
top: box.top,
|
|
||||||
left: box.left,
|
|
||||||
width: box.width,
|
|
||||||
height: box.height
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPosition(options, dlg) {
|
|
||||||
|
|
||||||
var windowSize = dom.getWindowSize();
|
|
||||||
var windowHeight = windowSize.innerHeight;
|
|
||||||
var windowWidth = windowSize.innerWidth;
|
|
||||||
|
|
||||||
var pos = getOffsets([options.positionTo])[0];
|
|
||||||
|
|
||||||
if (options.positionY !== 'top') {
|
|
||||||
pos.top += (pos.height || 0) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos.left += (pos.width || 0) / 2;
|
|
||||||
|
|
||||||
var height = dlg.offsetHeight || 300;
|
|
||||||
var width = dlg.offsetWidth || 160;
|
|
||||||
|
|
||||||
// Account for popup size
|
|
||||||
pos.top -= height / 2;
|
|
||||||
pos.left -= width / 2;
|
|
||||||
|
|
||||||
// Avoid showing too close to the bottom
|
|
||||||
var overflowX = pos.left + width - windowWidth;
|
|
||||||
var overflowY = pos.top + height - windowHeight;
|
|
||||||
|
|
||||||
if (overflowX > 0) {
|
|
||||||
pos.left -= (overflowX + 20);
|
|
||||||
}
|
|
||||||
if (overflowY > 0) {
|
|
||||||
pos.top -= (overflowY + 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
pos.top += (options.offsetTop || 0);
|
|
||||||
pos.left += (options.offsetLeft || 0);
|
|
||||||
|
|
||||||
// Do some boundary checking
|
|
||||||
pos.top = Math.max(pos.top, 10);
|
|
||||||
pos.left = Math.max(pos.left, 10);
|
|
||||||
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
function centerFocus(elem, horiz, on) {
|
|
||||||
require(['scrollHelper'], function (scrollHelper) {
|
|
||||||
var fn = on ? 'on' : 'off';
|
|
||||||
scrollHelper.centerFocus[fn](elem, horiz);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function show(options) {
|
|
||||||
|
|
||||||
// items
|
|
||||||
// positionTo
|
|
||||||
// showCancel
|
|
||||||
// title
|
|
||||||
var dialogOptions = {
|
|
||||||
removeOnClose: true,
|
|
||||||
enableHistory: options.enableHistory,
|
|
||||||
scrollY: false
|
|
||||||
};
|
|
||||||
|
|
||||||
var backButton = false;
|
|
||||||
var isFullscreen;
|
|
||||||
|
|
||||||
if (layoutManager.tv) {
|
|
||||||
dialogOptions.size = 'fullscreen';
|
|
||||||
isFullscreen = true;
|
|
||||||
backButton = true;
|
|
||||||
dialogOptions.autoFocus = true;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
dialogOptions.modal = false;
|
|
||||||
dialogOptions.entryAnimation = options.entryAnimation;
|
|
||||||
dialogOptions.exitAnimation = options.exitAnimation;
|
|
||||||
dialogOptions.entryAnimationDuration = options.entryAnimationDuration || 140;
|
|
||||||
dialogOptions.exitAnimationDuration = options.exitAnimationDuration || 100;
|
|
||||||
dialogOptions.autoFocus = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var dlg = dialogHelper.createDialog(dialogOptions);
|
|
||||||
|
|
||||||
if (isFullscreen) {
|
|
||||||
dlg.classList.add('actionsheet-fullscreen');
|
|
||||||
} else {
|
|
||||||
dlg.classList.add('actionsheet-not-fullscreen');
|
|
||||||
}
|
|
||||||
|
|
||||||
dlg.classList.add('actionSheet');
|
|
||||||
|
|
||||||
if (options.dialogClass) {
|
|
||||||
dlg.classList.add(options.dialogClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
var html = '';
|
|
||||||
|
|
||||||
var scrollClassName = layoutManager.tv ? 'scrollY smoothScrollY hiddenScrollY' : 'scrollY';
|
|
||||||
var style = '';
|
|
||||||
|
|
||||||
// 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;";
|
|
||||||
}
|
|
||||||
|
|
||||||
var i;
|
|
||||||
var length;
|
|
||||||
var option;
|
|
||||||
var renderIcon = false;
|
|
||||||
var icons = [];
|
|
||||||
var itemIcon;
|
|
||||||
for (i = 0, length = options.items.length; i < length; i++) {
|
|
||||||
|
|
||||||
option = options.items[i];
|
|
||||||
|
|
||||||
itemIcon = option.icon || (option.selected ? 'check' : null);
|
|
||||||
|
|
||||||
if (itemIcon) {
|
|
||||||
renderIcon = true;
|
|
||||||
}
|
|
||||||
icons.push(itemIcon || '');
|
|
||||||
}
|
|
||||||
|
|
||||||
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>';
|
|
||||||
}
|
|
||||||
|
|
||||||
// If any items have an icon, give them all an icon just to make sure they're all lined up evenly
|
|
||||||
var center = options.title && (!renderIcon /*|| itemsWithIcons.length != options.items.length*/);
|
|
||||||
|
|
||||||
if (center || layoutManager.tv) {
|
|
||||||
html += '<div class="actionSheetContent actionSheetContent-centered">';
|
|
||||||
} else {
|
|
||||||
html += '<div class="actionSheetContent">';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.title) {
|
|
||||||
|
|
||||||
html += '<h1 class="actionSheetTitle">';
|
|
||||||
html += options.title;
|
|
||||||
html += '</h1>';
|
|
||||||
}
|
|
||||||
if (options.text) {
|
|
||||||
html += '<p class="actionSheetText">';
|
|
||||||
html += options.text;
|
|
||||||
html += '</p>';
|
|
||||||
}
|
|
||||||
|
|
||||||
var scrollerClassName = 'actionSheetScroller';
|
|
||||||
if (layoutManager.tv) {
|
|
||||||
scrollerClassName += ' actionSheetScroller-tv focuscontainer-x focuscontainer-y';
|
|
||||||
}
|
|
||||||
html += '<div class="' + scrollerClassName + ' ' + scrollClassName + '" style="' + style + '">';
|
|
||||||
|
|
||||||
var menuItemClass = 'listItem listItem-button actionSheetMenuItem';
|
|
||||||
|
|
||||||
if (options.border || options.shaded) {
|
|
||||||
menuItemClass += ' listItem-border';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.menuItemClass) {
|
|
||||||
menuItemClass += ' ' + options.menuItemClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (layoutManager.tv) {
|
|
||||||
menuItemClass += ' listItem-focusscale';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (layoutManager.mobile) {
|
|
||||||
menuItemClass += ' actionsheet-xlargeFont';
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0, length = options.items.length; i < length; i++) {
|
|
||||||
|
|
||||||
option = options.items[i];
|
|
||||||
|
|
||||||
if (option.divider) {
|
|
||||||
|
|
||||||
html += '<div class="actionsheetDivider"></div>';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var autoFocus = option.selected && layoutManager.tv ? ' autoFocus' : '';
|
|
||||||
|
|
||||||
// Check for null in case int 0 was passed in
|
|
||||||
var optionId = option.id == null || option.id === '' ? option.value : option.id;
|
|
||||||
html += '<button' + autoFocus + ' is="emby-button" type="button" class="' + menuItemClass + '" data-id="' + optionId + '">';
|
|
||||||
|
|
||||||
itemIcon = icons[i];
|
|
||||||
|
|
||||||
if (itemIcon) {
|
|
||||||
|
|
||||||
html += '<i class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons">' + itemIcon + '</i>';
|
|
||||||
} else if (renderIcon && !center) {
|
|
||||||
html += '<i class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons" style="visibility:hidden;">check</i>';
|
|
||||||
}
|
|
||||||
|
|
||||||
html += '<div class="listItemBody actionsheetListItemBody">';
|
|
||||||
|
|
||||||
html += '<div class="listItemBodyText actionSheetItemText">';
|
|
||||||
html += (option.name || option.textContent || option.innerText);
|
|
||||||
html += '</div>';
|
|
||||||
|
|
||||||
if (option.secondaryText) {
|
|
||||||
html += '<div class="listItemBodyText secondary">';
|
|
||||||
html += option.secondaryText;
|
|
||||||
html += '</div>';
|
|
||||||
}
|
|
||||||
|
|
||||||
html += '</div>';
|
|
||||||
|
|
||||||
if (option.asideText) {
|
|
||||||
html += '<div class="listItemAside actionSheetItemAsideText">';
|
|
||||||
html += option.asideText;
|
|
||||||
html += '</div>';
|
|
||||||
}
|
|
||||||
|
|
||||||
html += '</button>';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.showCancel) {
|
|
||||||
html += '<div class="buttons">';
|
|
||||||
html += '<button is="emby-button" type="button" class="btnCloseActionSheet">' + globalize.translate('ButtonCancel') + '</button>';
|
|
||||||
html += '</div>';
|
|
||||||
}
|
|
||||||
html += '</div>';
|
|
||||||
|
|
||||||
dlg.innerHTML = html;
|
|
||||||
|
|
||||||
if (layoutManager.tv) {
|
|
||||||
centerFocus(dlg.querySelector('.actionSheetScroller'), false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
var btnCloseActionSheet = dlg.querySelector('.btnCloseActionSheet');
|
|
||||||
if (btnCloseActionSheet) {
|
|
||||||
dlg.querySelector('.btnCloseActionSheet').addEventListener('click', function () {
|
|
||||||
dialogHelper.close(dlg);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Seeing an issue in some non-chrome browsers where this is requiring a double click
|
|
||||||
//var eventName = browser.firefox ? 'mousedown' : 'click';
|
|
||||||
var selectedId;
|
|
||||||
|
|
||||||
var timeout;
|
|
||||||
if (options.timeout) {
|
|
||||||
timeout = setTimeout(function () {
|
|
||||||
dialogHelper.close(dlg);
|
|
||||||
}, options.timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
|
|
||||||
var isResolved;
|
|
||||||
|
|
||||||
dlg.addEventListener('click', function (e) {
|
|
||||||
|
|
||||||
var actionSheetMenuItem = dom.parentWithClass(e.target, 'actionSheetMenuItem');
|
|
||||||
|
|
||||||
if (actionSheetMenuItem) {
|
|
||||||
selectedId = actionSheetMenuItem.getAttribute('data-id');
|
|
||||||
|
|
||||||
if (options.resolveOnClick) {
|
|
||||||
|
|
||||||
if (options.resolveOnClick.indexOf) {
|
|
||||||
|
|
||||||
if (options.resolveOnClick.indexOf(selectedId) !== -1) {
|
|
||||||
|
|
||||||
resolve(selectedId);
|
|
||||||
isResolved = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
resolve(selectedId);
|
|
||||||
isResolved = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dialogHelper.close(dlg);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
dlg.addEventListener('close', function () {
|
|
||||||
|
|
||||||
if (layoutManager.tv) {
|
|
||||||
centerFocus(dlg.querySelector('.actionSheetScroller'), false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timeout) {
|
|
||||||
clearTimeout(timeout);
|
|
||||||
timeout = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isResolved) {
|
|
||||||
if (selectedId != null) {
|
|
||||||
if (options.callback) {
|
|
||||||
options.callback(selectedId);
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve(selectedId);
|
|
||||||
} else {
|
|
||||||
reject();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
dialogHelper.open(dlg);
|
|
||||||
|
|
||||||
var pos = options.positionTo && dialogOptions.size !== 'fullscreen' ? getPosition(options, dlg) : null;
|
|
||||||
|
|
||||||
if (pos) {
|
|
||||||
dlg.style.position = 'fixed';
|
|
||||||
dlg.style.margin = 0;
|
|
||||||
dlg.style.left = pos.left + 'px';
|
|
||||||
dlg.style.top = pos.top + 'px';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
show: show
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,59 +1,63 @@
|
||||||
define(["events", "globalize", "dom", "date-fns", "dfnshelper", "userSettings", "serverNotifications", "connectionManager", "emby-button", "listViewStyle"], function (events, globalize, dom, datefns, dfnshelper, userSettings, serverNotifications, connectionManager) {
|
define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings', 'serverNotifications', 'connectionManager', 'emby-button', 'listViewStyle'], function (events, globalize, dom, datefns, dfnshelper, userSettings, serverNotifications, connectionManager) {
|
||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
function getEntryHtml(entry, apiClient) {
|
function getEntryHtml(entry, apiClient) {
|
||||||
var html = "";
|
var html = '';
|
||||||
html += '<div class="listItem listItem-border">';
|
html += '<div class="listItem listItem-border">';
|
||||||
var color = "#00a4dc";
|
var color = '#00a4dc';
|
||||||
var icon = "notifications";
|
var icon = 'notifications';
|
||||||
|
|
||||||
if ("Error" == entry.Severity || "Fatal" == entry.Severity || "Warn" == entry.Severity) {
|
if ('Error' == entry.Severity || 'Fatal' == entry.Severity || 'Warn' == entry.Severity) {
|
||||||
color = "#cc0000";
|
color = '#cc0000';
|
||||||
icon = "notification_important";
|
icon = 'notification_important';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.UserId && entry.UserPrimaryImageTag) {
|
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, {
|
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",
|
type: 'Primary',
|
||||||
tag: entry.UserPrimaryImageTag
|
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 {
|
} 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="listItemBody three-line">';
|
||||||
html += '<div class="listItemBodyText">';
|
html += '<div class="listItemBodyText">';
|
||||||
html += entry.Name;
|
html += entry.Name;
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
html += '<div class="listItemBodyText secondary">';
|
html += '<div class="listItemBodyText secondary">';
|
||||||
html += datefns.formatRelative(Date.parse(entry.Date), Date.parse(new Date()), { locale: dfnshelper.getLocale() });
|
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 += '<div class="listItemBodyText secondary listItemBodyText-nowrap">';
|
||||||
html += entry.ShortOverview || "";
|
html += entry.ShortOverview || '';
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
|
|
||||||
if (entry.Overview) {
|
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>";
|
html += '</div>';
|
||||||
|
|
||||||
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderList(elem, apiClient, result, startIndex, limit) {
|
function renderList(elem, apiClient, result, startIndex, limit) {
|
||||||
elem.innerHTML = result.Items.map(function (i) {
|
elem.innerHTML = result.Items.map(function (i) {
|
||||||
return getEntryHtml(i, apiClient);
|
return getEntryHtml(i, apiClient);
|
||||||
}).join("");
|
}).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
function reloadData(instance, elem, apiClient, startIndex, limit) {
|
function reloadData(instance, elem, apiClient, startIndex, limit) {
|
||||||
if (null == startIndex) {
|
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 minDate = new Date();
|
||||||
var hasUserId = "false" !== elem.getAttribute("data-useractivity");
|
var hasUserId = 'false' !== elem.getAttribute('data-useractivity');
|
||||||
|
|
||||||
if (hasUserId) {
|
if (hasUserId) {
|
||||||
minDate.setTime(minDate.getTime() - 24 * 60 * 60 * 1000); // one day back
|
minDate.setTime(minDate.getTime() - 24 * 60 * 60 * 1000); // one day back
|
||||||
|
@ -61,22 +65,22 @@ define(["events", "globalize", "dom", "date-fns", "dfnshelper", "userSettings",
|
||||||
minDate.setTime(minDate.getTime() - 7 * 24 * 60 * 60 * 1000); // one week back
|
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,
|
startIndex: startIndex,
|
||||||
limit: limit,
|
limit: limit,
|
||||||
minDate: minDate.toISOString(),
|
minDate: minDate.toISOString(),
|
||||||
hasUserId: hasUserId
|
hasUserId: hasUserId
|
||||||
})).then(function (result) {
|
})).then(function (result) {
|
||||||
elem.setAttribute("data-activitystartindex", startIndex);
|
elem.setAttribute('data-activitystartindex', startIndex);
|
||||||
elem.setAttribute("data-activitylimit", limit);
|
elem.setAttribute('data-activitylimit', limit);
|
||||||
if (!startIndex) {
|
if (!startIndex) {
|
||||||
var activityContainer = dom.parentWithClass(elem, "activityContainer");
|
var activityContainer = dom.parentWithClass(elem, 'activityContainer');
|
||||||
|
|
||||||
if (activityContainer) {
|
if (activityContainer) {
|
||||||
if (result.Items.length) {
|
if (result.Items.length) {
|
||||||
activityContainer.classList.remove("hide");
|
activityContainer.classList.remove('hide');
|
||||||
} else {
|
} else {
|
||||||
activityContainer.classList.add("hide");
|
activityContainer.classList.add('hide');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,10 +99,10 @@ define(["events", "globalize", "dom", "date-fns", "dfnshelper", "userSettings",
|
||||||
}
|
}
|
||||||
|
|
||||||
function onListClick(e) {
|
function onListClick(e) {
|
||||||
var btnEntryInfo = dom.parentWithClass(e.target, "btnEntryInfo");
|
var btnEntryInfo = dom.parentWithClass(e.target, 'btnEntryInfo');
|
||||||
|
|
||||||
if (btnEntryInfo) {
|
if (btnEntryInfo) {
|
||||||
var id = btnEntryInfo.getAttribute("data-id");
|
var id = btnEntryInfo.getAttribute('data-id');
|
||||||
var items = this.items;
|
var items = this.items;
|
||||||
|
|
||||||
if (items) {
|
if (items) {
|
||||||
|
@ -114,7 +118,7 @@ define(["events", "globalize", "dom", "date-fns", "dfnshelper", "userSettings",
|
||||||
}
|
}
|
||||||
|
|
||||||
function showItemOverview(item) {
|
function showItemOverview(item) {
|
||||||
require(["alert"], function (alert) {
|
require(['alert'], function (alert) {
|
||||||
alert({
|
alert({
|
||||||
text: item.Overview
|
text: item.Overview
|
||||||
});
|
});
|
||||||
|
@ -124,28 +128,28 @@ define(["events", "globalize", "dom", "date-fns", "dfnshelper", "userSettings",
|
||||||
function ActivityLog(options) {
|
function ActivityLog(options) {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
var element = options.element;
|
var element = options.element;
|
||||||
element.classList.add("activityLogListWidget");
|
element.classList.add('activityLogListWidget');
|
||||||
element.addEventListener("click", onListClick.bind(this));
|
element.addEventListener('click', onListClick.bind(this));
|
||||||
var apiClient = connectionManager.getApiClient(options.serverId);
|
var apiClient = connectionManager.getApiClient(options.serverId);
|
||||||
reloadData(this, element, apiClient);
|
reloadData(this, element, apiClient);
|
||||||
var onUpdate = onActivityLogUpdate.bind(this);
|
var onUpdate = onActivityLogUpdate.bind(this);
|
||||||
this.updateFn = onUpdate;
|
this.updateFn = onUpdate;
|
||||||
events.on(serverNotifications, "ActivityLogEntry", onUpdate);
|
events.on(serverNotifications, 'ActivityLogEntry', onUpdate);
|
||||||
apiClient.sendMessage("ActivityLogEntryStart", "0,1500");
|
apiClient.sendMessage('ActivityLogEntryStart', '0,1500');
|
||||||
}
|
}
|
||||||
|
|
||||||
ActivityLog.prototype.destroy = function () {
|
ActivityLog.prototype.destroy = function () {
|
||||||
var options = this.options;
|
var options = this.options;
|
||||||
|
|
||||||
if (options) {
|
if (options) {
|
||||||
options.element.classList.remove("activityLogListWidget");
|
options.element.classList.remove('activityLogListWidget');
|
||||||
connectionManager.getApiClient(options.serverId).sendMessage("ActivityLogEntryStop", "0,1500");
|
connectionManager.getApiClient(options.serverId).sendMessage('ActivityLogEntryStop', '0,1500');
|
||||||
}
|
}
|
||||||
|
|
||||||
var onUpdate = this.updateFn;
|
var onUpdate = this.updateFn;
|
||||||
|
|
||||||
if (onUpdate) {
|
if (onUpdate) {
|
||||||
events.off(serverNotifications, "ActivityLogEntry", onUpdate);
|
events.off(serverNotifications, 'ActivityLogEntry', onUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.items = null;
|
this.items = null;
|
||||||
|
|
|
@ -67,7 +67,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
|
||||||
|
|
||||||
html += '<div class="' + rowClassName + '">';
|
html += '<div class="' + rowClassName + '">';
|
||||||
if (options.mode === 'keyboard') {
|
if (options.mode === 'keyboard') {
|
||||||
html += '<button data-value=" " is="paper-icon-button-light" class="' + alphaPickerButtonClassName + '"><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 {
|
} else {
|
||||||
letters = ['#'];
|
letters = ['#'];
|
||||||
html += mapLetters(letters, vertical).join('');
|
html += mapLetters(letters, vertical).join('');
|
||||||
|
@ -77,7 +77,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
|
||||||
html += mapLetters(letters, vertical).join('');
|
html += mapLetters(letters, vertical).join('');
|
||||||
|
|
||||||
if (options.mode === 'keyboard') {
|
if (options.mode === 'keyboard') {
|
||||||
html += '<button data-value="backspace" is="paper-icon-button-light" class="' + alphaPickerButtonClassName + '"><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>';
|
html += '</div>';
|
||||||
|
|
||||||
letters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
|
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) {
|
if (alphaPickerButton) {
|
||||||
var value = alphaPickerButton.getAttribute('data-value');
|
var value = alphaPickerButton.getAttribute('data-value');
|
||||||
|
|
||||||
element.dispatchEvent(new CustomEvent("alphavalueclicked", {
|
element.dispatchEvent(new CustomEvent('alphavalueclicked', {
|
||||||
cancelable: false,
|
cancelable: false,
|
||||||
detail: {
|
detail: {
|
||||||
value: value
|
value: value
|
||||||
|
@ -262,7 +262,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
|
||||||
}
|
}
|
||||||
|
|
||||||
if (applyValue) {
|
if (applyValue) {
|
||||||
element.dispatchEvent(new CustomEvent("alphavaluechanged", {
|
element.dispatchEvent(new CustomEvent('alphavaluechanged', {
|
||||||
cancelable: false,
|
cancelable: false,
|
||||||
detail: {
|
detail: {
|
||||||
value: value
|
value: value
|
|
@ -1,4 +1,4 @@
|
||||||
define(['browser', 'css!./appfooter'], function (browser) {
|
define(['browser', 'css!./appFooter'], function (browser) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function render(options) {
|
function render(options) {
|
|
@ -1,4 +1,4 @@
|
||||||
define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinManager', 'pluginManager', 'backdrop', 'browser', 'page', 'appSettings', 'apphost', 'connectionManager'], function (loading, globalize, events, viewManager, layoutManager, skinManager, pluginManager, backdrop, browser, page, appSettings, appHost, connectionManager) {
|
define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdrop', 'browser', 'page', 'appSettings', 'apphost', 'connectionManager'], function (loading, globalize, events, viewManager, skinManager, backdrop, browser, page, appSettings, appHost, connectionManager) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var appRouter = {
|
var appRouter = {
|
||||||
|
@ -16,7 +16,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
show('/settings/settings.html');
|
show('/settings/settings.html');
|
||||||
},
|
},
|
||||||
showNowPlaying: function () {
|
showNowPlaying: function () {
|
||||||
show("/nowplaying.html");
|
show('/nowplaying.html');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,11 +26,11 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
connectionManager.connect({
|
connectionManager.connect({
|
||||||
enableAutoLogin: appSettings.enableAutoLogin()
|
enableAutoLogin: appSettings.enableAutoLogin()
|
||||||
}).then(function (result) {
|
}).then(function (result) {
|
||||||
handleConnectionResult(result, loading);
|
handleConnectionResult(result);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleConnectionResult(result, loading) {
|
function handleConnectionResult(result) {
|
||||||
switch (result.State) {
|
switch (result.State) {
|
||||||
case 'SignedIn':
|
case 'SignedIn':
|
||||||
loading.hide();
|
loading.hide();
|
||||||
|
@ -200,8 +200,8 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
|
|
||||||
var apiClient = this;
|
var apiClient = this;
|
||||||
|
|
||||||
if (data.status === 401) {
|
if (data.status === 403) {
|
||||||
if (data.errorCode === "ParentalControl") {
|
if (data.errorCode === 'ParentalControl') {
|
||||||
|
|
||||||
var isCurrentAllowed = currentRouteInfo ? (currentRouteInfo.route.anonymous || currentRouteInfo.route.startup) : true;
|
var isCurrentAllowed = currentRouteInfo ? (currentRouteInfo.route.anonymous || currentRouteInfo.route.startup) : true;
|
||||||
|
|
||||||
|
@ -246,13 +246,11 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setQuality) {
|
if (setQuality) {
|
||||||
|
var quality;
|
||||||
var quality = 100;
|
|
||||||
|
|
||||||
var type = options.type || 'Primary';
|
var type = options.type || 'Primary';
|
||||||
|
|
||||||
if (browser.tv || browser.slow) {
|
if (browser.tv || browser.slow) {
|
||||||
|
// TODO: wtf
|
||||||
if (browser.chrome) {
|
if (browser.chrome) {
|
||||||
// webp support
|
// webp support
|
||||||
quality = type === 'Primary' ? 40 : 50;
|
quality = type === 'Primary' ? 40 : 50;
|
||||||
|
@ -268,6 +266,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMaxBandwidth() {
|
function getMaxBandwidth() {
|
||||||
|
/* eslint-disable compat/compat */
|
||||||
if (navigator.connection) {
|
if (navigator.connection) {
|
||||||
var max = navigator.connection.downlinkMax;
|
var max = navigator.connection.downlinkMax;
|
||||||
if (max && max > 0 && max < Number.POSITIVE_INFINITY) {
|
if (max && max > 0 && max < Number.POSITIVE_INFINITY) {
|
||||||
|
@ -279,6 +278,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* eslint-enable compat/compat */
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -382,7 +382,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
|
|
||||||
if (firstResult.State !== 'SignedIn' && !route.anonymous) {
|
if (firstResult.State !== 'SignedIn' && !route.anonymous) {
|
||||||
|
|
||||||
handleConnectionResult(firstResult, loading);
|
handleConnectionResult(firstResult);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -461,7 +461,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
var isHandlingBackToDefault;
|
|
||||||
var isDummyBackToHome;
|
var isDummyBackToHome;
|
||||||
|
|
||||||
function loadContent(ctx, route, html, request) {
|
function loadContent(ctx, route, html, request) {
|
||||||
|
@ -539,15 +538,15 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
}
|
}
|
||||||
|
|
||||||
function param(name, url) {
|
function param(name, url) {
|
||||||
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
|
name = name.replace(/[\[]/, '\\\[').replace(/[\]]/, '\\\]');
|
||||||
var regexS = "[\\?&]" + name + "=([^&#]*)";
|
var regexS = '[\\?&]' + name + '=([^&#]*)';
|
||||||
var regex = new RegExp(regexS, "i");
|
var regex = new RegExp(regexS, 'i');
|
||||||
|
|
||||||
var results = regex.exec(url || getWindowLocationSearch());
|
var results = regex.exec(url || getWindowLocationSearch());
|
||||||
if (results == null) {
|
if (results == null) {
|
||||||
return "";
|
return '';
|
||||||
} else {
|
} else {
|
||||||
return decodeURIComponent(results[1].replace(/\+/g, " "));
|
return decodeURIComponent(results[1].replace(/\+/g, ' '));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -577,7 +576,8 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
|
|
||||||
function showDirect(path) {
|
function showDirect(path) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
resolveOnNextShow = resolve, page.show(baseUrl()+path);
|
resolveOnNextShow = resolve;
|
||||||
|
page.show(baseUrl() + path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -586,8 +586,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
path = '/' + path;
|
path = '/' + path;
|
||||||
}
|
}
|
||||||
|
|
||||||
var baseRoute = baseUrl();
|
path = path.replace(baseUrl(), '');
|
||||||
path = path.replace(baseRoute, '');
|
|
||||||
|
|
||||||
if (currentRouteInfo && currentRouteInfo.path === path) {
|
if (currentRouteInfo && currentRouteInfo.path === path) {
|
||||||
// can't use this with home right now due to the back menu
|
// can't use this with home right now due to the back menu
|
||||||
|
@ -618,10 +617,11 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
}
|
}
|
||||||
|
|
||||||
function showItem(item, serverId, options) {
|
function showItem(item, serverId, options) {
|
||||||
|
// TODO: Refactor this so it only gets items, not strings.
|
||||||
if (typeof (item) === 'string') {
|
if (typeof (item) === 'string') {
|
||||||
var apiClient = serverId ? connectionManager.getApiClient(serverId) : connectionManager.currentApiClient();
|
var apiClient = serverId ? connectionManager.getApiClient(serverId) : connectionManager.currentApiClient();
|
||||||
apiClient.getItem(apiClient.getCurrentUserId(), item).then(function (item) {
|
apiClient.getItem(apiClient.getCurrentUserId(), item).then(function (itemObject) {
|
||||||
appRouter.showItem(item, options);
|
appRouter.showItem(itemObject, options);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (arguments.length === 2) {
|
if (arguments.length === 2) {
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], function (appSettings, browser, events, htmlMediaHelper, webSettings) {
|
define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'globalize'], function (appSettings, browser, events, htmlMediaHelper, webSettings, globalize) {
|
||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
function getBaseProfileOptions(item) {
|
function getBaseProfileOptions(item) {
|
||||||
var disableHlsVideoAudioCodecs = [];
|
var disableHlsVideoAudioCodecs = [];
|
||||||
|
|
||||||
if (item && htmlMediaHelper.enableHlsJsPlayer(item.RunTimeTicks, item.MediaType)) {
|
if (item && htmlMediaHelper.enableHlsJsPlayer(item.RunTimeTicks, item.MediaType)) {
|
||||||
if (browser.edge || browser.msie) {
|
if (browser.edge) {
|
||||||
disableHlsVideoAudioCodecs.push("mp3");
|
disableHlsVideoAudioCodecs.push('mp3');
|
||||||
}
|
}
|
||||||
|
|
||||||
disableHlsVideoAudioCodecs.push("ac3");
|
disableHlsVideoAudioCodecs.push('ac3');
|
||||||
disableHlsVideoAudioCodecs.push("eac3");
|
disableHlsVideoAudioCodecs.push('eac3');
|
||||||
disableHlsVideoAudioCodecs.push("opus");
|
disableHlsVideoAudioCodecs.push('opus');
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -22,7 +22,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
|
||||||
|
|
||||||
function getDeviceProfileForWindowsUwp(item) {
|
function getDeviceProfileForWindowsUwp(item) {
|
||||||
return new Promise(function (resolve, reject) {
|
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);
|
var profileOptions = getBaseProfileOptions(item);
|
||||||
profileOptions.supportsDts = uwpMediaCaps.supportsDTS();
|
profileOptions.supportsDts = uwpMediaCaps.supportsDTS();
|
||||||
profileOptions.supportsTrueHd = uwpMediaCaps.supportsDolby();
|
profileOptions.supportsTrueHd = uwpMediaCaps.supportsDolby();
|
||||||
|
@ -40,26 +40,15 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Promise(function (resolve) {
|
return new Promise(function (resolve) {
|
||||||
require(["browserdeviceprofile"], function (profileBuilder) {
|
require(['browserdeviceprofile'], function (profileBuilder) {
|
||||||
var profile;
|
var profile;
|
||||||
|
|
||||||
if (window.NativeShell) {
|
if (window.NativeShell) {
|
||||||
profile = window.NativeShell.AppHost.getDeviceProfile(profileBuilder);
|
profile = window.NativeShell.AppHost.getDeviceProfile(profileBuilder);
|
||||||
} else {
|
} else {
|
||||||
profile = profileBuilder(getBaseProfileOptions(item));
|
var builderOpts = getBaseProfileOptions(item);
|
||||||
|
builderOpts.enableSsaRender = (item && !options.isRetry && 'allcomplexformats' !== appSettings.get('subtitleburnin'));
|
||||||
if (item && !options.isRetry && "allcomplexformats" !== appSettings.get("subtitleburnin")) {
|
profile = profileBuilder(builderOpts);
|
||||||
if (!browser.orsay && !browser.tizen) {
|
|
||||||
profile.SubtitleProfiles.push({
|
|
||||||
Format: "ass",
|
|
||||||
Method: "External"
|
|
||||||
});
|
|
||||||
profile.SubtitleProfiles.push({
|
|
||||||
Format: "ssa",
|
|
||||||
Method: "External"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve(profile);
|
resolve(profile);
|
||||||
|
@ -68,12 +57,12 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
|
||||||
}
|
}
|
||||||
|
|
||||||
function escapeRegExp(str) {
|
function escapeRegExp(str) {
|
||||||
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
|
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1');
|
||||||
}
|
}
|
||||||
|
|
||||||
function replaceAll(originalString, strReplace, strWith) {
|
function replaceAll(originalString, strReplace, strWith) {
|
||||||
var strReplace2 = escapeRegExp(strReplace);
|
var strReplace2 = escapeRegExp(strReplace);
|
||||||
var reg = new RegExp(strReplace2, "ig");
|
var reg = new RegExp(strReplace2, 'ig');
|
||||||
return originalString.replace(reg, strWith);
|
return originalString.replace(reg, strWith);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +70,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
|
||||||
var keys = [];
|
var keys = [];
|
||||||
|
|
||||||
if (keys.push(navigator.userAgent), keys.push(new Date().getTime()), self.btoa) {
|
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);
|
return Promise.resolve(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +78,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDeviceId() {
|
function getDeviceId() {
|
||||||
var key = "_deviceId2";
|
var key = '_deviceId2';
|
||||||
var deviceId = appSettings.get(key);
|
var deviceId = appSettings.get(key);
|
||||||
|
|
||||||
if (deviceId) {
|
if (deviceId) {
|
||||||
|
@ -104,18 +93,36 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
|
||||||
|
|
||||||
function getDeviceName() {
|
function getDeviceName() {
|
||||||
var deviceName;
|
var deviceName;
|
||||||
deviceName = browser.tizen ? "Samsung Smart TV" : browser.web0s ? "LG Smart TV" : browser.operaTv ? "Opera TV" : browser.xboxOne ? "Xbox One" : browser.ps4 ? "Sony PS4" : browser.chrome ? "Chrome" : browser.edge ? "Edge" : browser.firefox ? "Firefox" : browser.msie ? "Internet Explorer" : browser.opera ? "Opera" : browser.safari ? "Safari" : "Web Browser";
|
if (browser.tizen) {
|
||||||
|
deviceName = 'Samsung Smart TV';
|
||||||
|
} else if (browser.web0s) {
|
||||||
|
deviceName = 'LG Smart TV';
|
||||||
|
} else if (browser.operaTv) {
|
||||||
|
deviceName = 'Opera TV';
|
||||||
|
} else if (browser.xboxOne) {
|
||||||
|
deviceName = 'Xbox One';
|
||||||
|
} else if (browser.ps4) {
|
||||||
|
deviceName = 'Sony PS4';
|
||||||
|
} else if (browser.chrome) {
|
||||||
|
deviceName = 'Chrome';
|
||||||
|
} else if (browser.edge) {
|
||||||
|
deviceName = 'Edge';
|
||||||
|
} else if (browser.firefox) {
|
||||||
|
deviceName = 'Firefox';
|
||||||
|
} else if (browser.opera) {
|
||||||
|
deviceName = 'Opera';
|
||||||
|
} else if (browser.safari) {
|
||||||
|
deviceName = 'Safari';
|
||||||
|
} else {
|
||||||
|
deviceName = 'Web Browser';
|
||||||
|
}
|
||||||
|
|
||||||
if (browser.ipad) {
|
if (browser.ipad) {
|
||||||
deviceName += " iPad";
|
deviceName += ' iPad';
|
||||||
} else {
|
} else if (browser.iphone) {
|
||||||
if (browser.iphone) {
|
deviceName += ' iPhone';
|
||||||
deviceName += " iPhone";
|
} else if (browser.android) {
|
||||||
} else {
|
deviceName += ' Android';
|
||||||
if (browser.android) {
|
|
||||||
deviceName += " Android";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return deviceName;
|
return deviceName;
|
||||||
|
@ -135,12 +142,12 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
|
||||||
}
|
}
|
||||||
|
|
||||||
var element = document.documentElement;
|
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() {
|
function getSyncProfile() {
|
||||||
return new Promise(function (resolve) {
|
return new Promise(function (resolve) {
|
||||||
require(["browserdeviceprofile", "appSettings"], function (profileBuilder, appSettings) {
|
require(['browserdeviceprofile', 'appSettings'], function (profileBuilder, appSettings) {
|
||||||
var profile;
|
var profile;
|
||||||
|
|
||||||
if (window.NativeShell) {
|
if (window.NativeShell) {
|
||||||
|
@ -156,7 +163,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDefaultLayout() {
|
function getDefaultLayout() {
|
||||||
return "desktop";
|
return 'desktop';
|
||||||
}
|
}
|
||||||
|
|
||||||
function supportsHtmlMediaAutoplay() {
|
function supportsHtmlMediaAutoplay() {
|
||||||
|
@ -173,20 +180,20 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
|
||||||
|
|
||||||
function supportsCue() {
|
function supportsCue() {
|
||||||
try {
|
try {
|
||||||
var video = document.createElement("video");
|
var video = document.createElement('video');
|
||||||
var style = document.createElement("style");
|
var style = document.createElement('style');
|
||||||
|
|
||||||
style.textContent = "video::cue {background: inherit}";
|
style.textContent = 'video::cue {background: inherit}';
|
||||||
document.body.appendChild(style);
|
document.body.appendChild(style);
|
||||||
document.body.appendChild(video);
|
document.body.appendChild(video);
|
||||||
|
|
||||||
var cue = window.getComputedStyle(video, "::cue").background;
|
var cue = window.getComputedStyle(video, '::cue').background;
|
||||||
document.body.removeChild(style);
|
document.body.removeChild(style);
|
||||||
document.body.removeChild(video);
|
document.body.removeChild(video);
|
||||||
|
|
||||||
return !!cue.length;
|
return !!cue.length;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("error detecting cue support: " + err);
|
console.error('error detecting cue support: ' + err);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -194,15 +201,15 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
|
||||||
function onAppVisible() {
|
function onAppVisible() {
|
||||||
if (isHidden) {
|
if (isHidden) {
|
||||||
isHidden = false;
|
isHidden = false;
|
||||||
console.debug("triggering app resume event");
|
console.debug('triggering app resume event');
|
||||||
events.trigger(appHost, "resume");
|
events.trigger(appHost, 'resume');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onAppHidden() {
|
function onAppHidden() {
|
||||||
if (!isHidden) {
|
if (!isHidden) {
|
||||||
isHidden = true;
|
isHidden = true;
|
||||||
console.debug("app is hidden");
|
console.debug('app is hidden');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,92 +217,88 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
|
||||||
var features = [];
|
var features = [];
|
||||||
|
|
||||||
if (navigator.share) {
|
if (navigator.share) {
|
||||||
features.push("sharing");
|
features.push('sharing');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!browser.edgeUwp && !browser.tv && !browser.xboxOne && !browser.ps4) {
|
if (!browser.edgeUwp && !browser.tv && !browser.xboxOne && !browser.ps4) {
|
||||||
features.push("filedownload");
|
features.push('filedownload');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (browser.operaTv || browser.tizen || browser.orsay || browser.web0s) {
|
if (browser.operaTv || browser.tizen || browser.orsay || browser.web0s) {
|
||||||
features.push("exit");
|
features.push('exit');
|
||||||
} else {
|
} else {
|
||||||
features.push("exitmenu");
|
features.push('exitmenu');
|
||||||
features.push("plugins");
|
features.push('plugins');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!browser.operaTv && !browser.tizen && !browser.orsay && !browser.web0s && !browser.ps4) {
|
if (!browser.operaTv && !browser.tizen && !browser.orsay && !browser.web0s && !browser.ps4) {
|
||||||
features.push("externallinks");
|
features.push('externallinks');
|
||||||
features.push("externalpremium");
|
features.push('externalpremium');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!browser.operaTv) {
|
if (!browser.operaTv) {
|
||||||
features.push("externallinkdisplay");
|
features.push('externallinkdisplay');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (supportsVoiceInput()) {
|
if (supportsVoiceInput()) {
|
||||||
features.push("voiceinput");
|
features.push('voiceinput');
|
||||||
}
|
|
||||||
|
|
||||||
if (!browser.tv && !browser.xboxOne) {
|
|
||||||
browser.ps4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (supportsHtmlMediaAutoplay()) {
|
if (supportsHtmlMediaAutoplay()) {
|
||||||
features.push("htmlaudioautoplay");
|
features.push('htmlaudioautoplay');
|
||||||
features.push("htmlvideoautoplay");
|
features.push('htmlvideoautoplay');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (browser.edgeUwp) {
|
if (browser.edgeUwp) {
|
||||||
features.push("sync");
|
features.push('sync');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (supportsFullscreen()) {
|
if (supportsFullscreen()) {
|
||||||
features.push("fullscreenchange");
|
features.push('fullscreenchange');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (browser.chrome || browser.edge && !browser.slow) {
|
if (browser.chrome || browser.edge && !browser.slow) {
|
||||||
if (!browser.noAnimation && !browser.edgeUwp && !browser.xboxOne) {
|
if (!browser.noAnimation && !browser.edgeUwp && !browser.xboxOne) {
|
||||||
features.push("imageanalysis");
|
features.push('imageanalysis');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (browser.tv || browser.xboxOne || browser.ps4 || browser.mobile) {
|
if (browser.tv || browser.xboxOne || browser.ps4 || browser.mobile) {
|
||||||
features.push("physicalvolumecontrol");
|
features.push('physicalvolumecontrol');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!browser.tv && !browser.xboxOne && !browser.ps4) {
|
if (!browser.tv && !browser.xboxOne && !browser.ps4) {
|
||||||
features.push("remotecontrol");
|
features.push('remotecontrol');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!browser.operaTv && !browser.tizen && !browser.orsay && !browser.web0s && !browser.edgeUwp) {
|
if (!browser.operaTv && !browser.tizen && !browser.orsay && !browser.web0s && !browser.edgeUwp) {
|
||||||
features.push("remotevideo");
|
features.push('remotevideo');
|
||||||
}
|
}
|
||||||
|
|
||||||
features.push("displaylanguage");
|
features.push('displaylanguage');
|
||||||
features.push("otherapppromotions");
|
features.push('otherapppromotions');
|
||||||
features.push("displaymode");
|
features.push('displaymode');
|
||||||
features.push("targetblank");
|
features.push('targetblank');
|
||||||
features.push("screensaver");
|
features.push('screensaver');
|
||||||
|
|
||||||
webSettings.enableMultiServer().then(enabled => {
|
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())) {
|
if (!browser.orsay && (browser.firefox || browser.ps4 || browser.edge || supportsCue())) {
|
||||||
features.push("subtitleappearancesettings");
|
features.push('subtitleappearancesettings');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!browser.orsay) {
|
if (!browser.orsay) {
|
||||||
features.push("subtitleburnsettings");
|
features.push('subtitleburnsettings');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!browser.tv && !browser.ps4 && !browser.xboxOne) {
|
if (!browser.tv && !browser.ps4 && !browser.xboxOne) {
|
||||||
features.push("fileinput");
|
features.push('fileinput');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (browser.chrome) {
|
if (browser.chrome) {
|
||||||
features.push("chromecast");
|
features.push('chromecast');
|
||||||
}
|
}
|
||||||
|
|
||||||
return features;
|
return features;
|
||||||
|
@ -316,7 +319,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
|
||||||
window.close();
|
window.close();
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("error closing application: " + err);
|
console.error('error closing application: ' + err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,15 +333,15 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
require(["actionsheet"], function (actionsheet) {
|
require(['actionsheet'], function (actionsheet) {
|
||||||
exitPromise = actionsheet.show({
|
exitPromise = actionsheet.show({
|
||||||
title: Globalize.translate("MessageConfirmAppExit"),
|
title: globalize.translate('MessageConfirmAppExit'),
|
||||||
items: [
|
items: [
|
||||||
{id: "yes", name: Globalize.translate("Yes")},
|
{id: 'yes', name: globalize.translate('Yes')},
|
||||||
{id: "no", name: Globalize.translate("No")}
|
{id: 'no', name: globalize.translate('No')}
|
||||||
]
|
]
|
||||||
}).then(function (value) {
|
}).then(function (value) {
|
||||||
if (value === "yes") {
|
if (value === 'yes') {
|
||||||
doExit();
|
doExit();
|
||||||
}
|
}
|
||||||
}).finally(function () {
|
}).finally(function () {
|
||||||
|
@ -349,17 +352,15 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
|
||||||
|
|
||||||
var deviceId;
|
var deviceId;
|
||||||
var deviceName;
|
var deviceName;
|
||||||
var appName = "Jellyfin Web";
|
var appName = 'Jellyfin Web';
|
||||||
var appVersion = "10.5.0";
|
var appVersion = '10.6.0';
|
||||||
var visibilityChange;
|
|
||||||
var visibilityState;
|
|
||||||
|
|
||||||
var appHost = {
|
var appHost = {
|
||||||
getWindowState: function () {
|
getWindowState: function () {
|
||||||
return document.windowState || "Normal";
|
return document.windowState || 'Normal';
|
||||||
},
|
},
|
||||||
setWindowState: function (state) {
|
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 () {
|
exit: function () {
|
||||||
if (!!window.appMode && browser.tizen) {
|
if (!!window.appMode && browser.tizen) {
|
||||||
|
@ -376,7 +377,6 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
|
||||||
return -1 !== supportedFeatures.indexOf(command.toLowerCase());
|
return -1 !== supportedFeatures.indexOf(command.toLowerCase());
|
||||||
},
|
},
|
||||||
preferVisualCards: browser.android || browser.chrome,
|
preferVisualCards: browser.android || browser.chrome,
|
||||||
moreIcon: browser.android ? "more_vert" : "more_horiz",
|
|
||||||
getSyncProfile: getSyncProfile,
|
getSyncProfile: getSyncProfile,
|
||||||
getDefaultLayout: function () {
|
getDefaultLayout: function () {
|
||||||
if (window.NativeShell) {
|
if (window.NativeShell) {
|
||||||
|
@ -412,58 +412,44 @@ define(["appSettings", "browser", "events", "htmlMediaHelper", "webSettings"], f
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
setThemeColor: function (color) {
|
setThemeColor: function (color) {
|
||||||
var metaThemeColor = document.querySelector("meta[name=theme-color]");
|
var metaThemeColor = document.querySelector('meta[name=theme-color]');
|
||||||
|
|
||||||
if (metaThemeColor) {
|
if (metaThemeColor) {
|
||||||
metaThemeColor.setAttribute("content", color);
|
metaThemeColor.setAttribute('content', color);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setUserScalable: function (scalable) {
|
setUserScalable: function (scalable) {
|
||||||
if (!browser.tv) {
|
if (!browser.tv) {
|
||||||
var att = scalable ? "width=device-width, initial-scale=1, minimum-scale=1, user-scalable=yes" : "width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no";
|
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);
|
document.querySelector('meta[name=viewport]').setAttribute('content', att);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var doc = self.document;
|
|
||||||
var isHidden = false;
|
var isHidden = false;
|
||||||
|
var hidden;
|
||||||
|
var visibilityChange;
|
||||||
|
|
||||||
if (doc) {
|
if (typeof document.hidden !== 'undefined') { /* eslint-disable-line compat/compat */
|
||||||
if (void 0 !== doc.visibilityState) {
|
hidden = 'hidden';
|
||||||
visibilityChange = "visibilitychange";
|
visibilityChange = 'visibilitychange';
|
||||||
visibilityState = "hidden";
|
} else if (typeof document.webkitHidden !== 'undefined') {
|
||||||
} else {
|
hidden = 'webkitHidden';
|
||||||
if (void 0 !== doc.mozHidden) {
|
visibilityChange = 'webkitvisibilitychange';
|
||||||
visibilityChange = "mozvisibilitychange";
|
|
||||||
visibilityState = "mozVisibilityState";
|
|
||||||
} else {
|
|
||||||
if (void 0 !== doc.msHidden) {
|
|
||||||
visibilityChange = "msvisibilitychange";
|
|
||||||
visibilityState = "msVisibilityState";
|
|
||||||
} else {
|
|
||||||
if (void 0 !== doc.webkitHidden) {
|
|
||||||
visibilityChange = "webkitvisibilitychange";
|
|
||||||
visibilityState = "webkitVisibilityState";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doc) {
|
document.addEventListener(visibilityChange, function () {
|
||||||
doc.addEventListener(visibilityChange, function () {
|
/* eslint-disable-next-line compat/compat */
|
||||||
if (document[visibilityState]) {
|
if (document[hidden]) {
|
||||||
onAppHidden();
|
onAppHidden();
|
||||||
} else {
|
} else {
|
||||||
onAppVisible();
|
onAppVisible();
|
||||||
}
|
}
|
||||||
});
|
}, false);
|
||||||
}
|
|
||||||
|
|
||||||
if (self.addEventListener) {
|
if (self.addEventListener) {
|
||||||
self.addEventListener("focus", onAppVisible);
|
self.addEventListener('focus', onAppVisible);
|
||||||
self.addEventListener("blur", onAppHidden);
|
self.addEventListener('blur', onAppHidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
return appHost;
|
return appHost;
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
* @module components/autoFocuser
|
* @module components/autoFocuser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import focusManager from "focusManager";
|
import focusManager from 'focusManager';
|
||||||
import layoutManager from "layoutManager";
|
import layoutManager from 'layoutManager';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Previously selected element.
|
* Previously selected element.
|
||||||
|
@ -28,11 +28,11 @@ import layoutManager from "layoutManager";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("focusin", function (e) {
|
window.addEventListener('focusin', function (e) {
|
||||||
activeElement = e.target;
|
activeElement = e.target;
|
||||||
});
|
});
|
||||||
|
|
||||||
console.debug("AutoFocuser enabled");
|
console.debug('AutoFocuser enabled');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,21 +51,21 @@ import layoutManager from "layoutManager";
|
||||||
|
|
||||||
if (activeElement) {
|
if (activeElement) {
|
||||||
// These elements are recreated
|
// These elements are recreated
|
||||||
if (activeElement.classList.contains("btnPreviousPage")) {
|
if (activeElement.classList.contains('btnPreviousPage')) {
|
||||||
candidates.push(container.querySelector(".btnPreviousPage"));
|
candidates.push(container.querySelector('.btnPreviousPage'));
|
||||||
candidates.push(container.querySelector(".btnNextPage"));
|
candidates.push(container.querySelector('.btnNextPage'));
|
||||||
} else if (activeElement.classList.contains("btnNextPage")) {
|
} else if (activeElement.classList.contains('btnNextPage')) {
|
||||||
candidates.push(container.querySelector(".btnNextPage"));
|
candidates.push(container.querySelector('.btnNextPage'));
|
||||||
candidates.push(container.querySelector(".btnPreviousPage"));
|
candidates.push(container.querySelector('.btnPreviousPage'));
|
||||||
} else if (activeElement.classList.contains("btnSelectView")) {
|
} else if (activeElement.classList.contains('btnSelectView')) {
|
||||||
candidates.push(container.querySelector(".btnSelectView"));
|
candidates.push(container.querySelector('.btnSelectView'));
|
||||||
}
|
}
|
||||||
|
|
||||||
candidates.push(activeElement);
|
candidates.push(activeElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
candidates = candidates.concat(Array.from(container.querySelectorAll(".btnResume")));
|
candidates = candidates.concat(Array.from(container.querySelectorAll('.btnResume')));
|
||||||
candidates = candidates.concat(Array.from(container.querySelectorAll(".btnPlay")));
|
candidates = candidates.concat(Array.from(container.querySelectorAll('.btnPlay')));
|
||||||
|
|
||||||
let focusedElement;
|
let focusedElement;
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ import layoutManager from "layoutManager";
|
||||||
|
|
||||||
if (!focusedElement) {
|
if (!focusedElement) {
|
||||||
// FIXME: Multiple itemsContainers
|
// FIXME: Multiple itemsContainers
|
||||||
const itemsContainer = container.querySelector(".itemsContainer");
|
const itemsContainer = container.querySelector('.itemsContainer');
|
||||||
|
|
||||||
if (itemsContainer) {
|
if (itemsContainer) {
|
||||||
focusedElement = focusManager.autoFocus(itemsContainer);
|
focusedElement = focusManager.autoFocus(itemsContainer);
|
||||||
|
|
|
@ -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';
|
'use strict';
|
||||||
|
|
||||||
function enableAnimation(elem) {
|
function enableAnimation(elem) {
|
||||||
|
@ -180,7 +180,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', "userSettings"
|
||||||
if (item.BackdropImageTags && item.BackdropImageTags.length > 0) {
|
if (item.BackdropImageTags && item.BackdropImageTags.length > 0) {
|
||||||
return item.BackdropImageTags.map(function (imgTag, index) {
|
return item.BackdropImageTags.map(function (imgTag, index) {
|
||||||
return apiClient.getScaledImageUrl(item.BackdropItemId || item.Id, Object.assign(imageOptions, {
|
return apiClient.getScaledImageUrl(item.BackdropItemId || item.Id, Object.assign(imageOptions, {
|
||||||
type: "Backdrop",
|
type: 'Backdrop',
|
||||||
tag: imgTag,
|
tag: imgTag,
|
||||||
maxWidth: dom.getScreenWidth(),
|
maxWidth: dom.getScreenWidth(),
|
||||||
index: index
|
index: index
|
||||||
|
@ -191,7 +191,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', "userSettings"
|
||||||
if (item.ParentBackdropItemId && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) {
|
if (item.ParentBackdropItemId && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) {
|
||||||
return item.ParentBackdropImageTags.map(function (imgTag, index) {
|
return item.ParentBackdropImageTags.map(function (imgTag, index) {
|
||||||
return apiClient.getScaledImageUrl(item.ParentBackdropItemId, Object.assign(imageOptions, {
|
return apiClient.getScaledImageUrl(item.ParentBackdropItemId, Object.assign(imageOptions, {
|
||||||
type: "Backdrop",
|
type: 'Backdrop',
|
||||||
tag: imgTag,
|
tag: imgTag,
|
||||||
maxWidth: dom.getScreenWidth(),
|
maxWidth: dom.getScreenWidth(),
|
||||||
index: index
|
index: index
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
define(["connectionManager"], function (connectionManager) {
|
|
||||||
|
|
||||||
return function () {
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
self.name = "Backdrop ScreenSaver";
|
|
||||||
self.type = "screensaver";
|
|
||||||
self.id = "backdropscreensaver";
|
|
||||||
self.supportsAnonymous = false;
|
|
||||||
|
|
||||||
var currentSlideshow;
|
|
||||||
|
|
||||||
self.show = function () {
|
|
||||||
|
|
||||||
var query = {
|
|
||||||
ImageTypes: "Backdrop",
|
|
||||||
EnableImageTypes: "Backdrop",
|
|
||||||
IncludeItemTypes: "Movie,Series,MusicArtist",
|
|
||||||
SortBy: "Random",
|
|
||||||
Recursive: true,
|
|
||||||
Fields: "Taglines",
|
|
||||||
ImageTypeLimit: 1,
|
|
||||||
StartIndex: 0,
|
|
||||||
Limit: 200
|
|
||||||
};
|
|
||||||
|
|
||||||
var apiClient = connectionManager.currentApiClient();
|
|
||||||
apiClient.getItems(apiClient.getCurrentUserId(), query).then(function (result) {
|
|
||||||
|
|
||||||
if (result.Items.length) {
|
|
||||||
|
|
||||||
require(["slideshow"], function (slideshow) {
|
|
||||||
|
|
||||||
var newSlideShow = new slideshow({
|
|
||||||
showTitle: true,
|
|
||||||
cover: true,
|
|
||||||
items: result.Items
|
|
||||||
});
|
|
||||||
|
|
||||||
newSlideShow.show();
|
|
||||||
currentSlideshow = newSlideShow;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
self.hide = function () {
|
|
||||||
|
|
||||||
if (currentSlideshow) {
|
|
||||||
currentSlideshow.hide();
|
|
||||||
currentSlideshow = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -306,6 +306,10 @@ button::-moz-focus-inner {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dialog .cardText {
|
||||||
|
text-overflow: initial;
|
||||||
|
}
|
||||||
|
|
||||||
.cardText-secondary {
|
.cardText-secondary {
|
||||||
font-size: 86%;
|
font-size: 86%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -286,7 +286,7 @@ import 'programStyles';
|
||||||
* @param {Object} options - Options for handling the items.
|
* @param {Object} options - Options for handling the items.
|
||||||
*/
|
*/
|
||||||
function setCardData(items, options) {
|
function setCardData(items, options) {
|
||||||
options.shape = options.shape || "auto";
|
options.shape = options.shape || 'auto';
|
||||||
|
|
||||||
const primaryImageAspectRatio = imageLoader.getPrimaryImageAspectRatio(items);
|
const primaryImageAspectRatio = imageLoader.getPrimaryImageAspectRatio(items);
|
||||||
|
|
||||||
|
@ -503,94 +503,49 @@ import 'programStyles';
|
||||||
const primaryImageAspectRatio = item.PrimaryImageAspectRatio;
|
const primaryImageAspectRatio = item.PrimaryImageAspectRatio;
|
||||||
let forceName = false;
|
let forceName = false;
|
||||||
let imgUrl = null;
|
let imgUrl = null;
|
||||||
|
let imgTag = null;
|
||||||
let coverImage = false;
|
let coverImage = false;
|
||||||
let uiAspect = null;
|
let uiAspect = null;
|
||||||
|
let imgType = null;
|
||||||
|
let itemId = null;
|
||||||
|
|
||||||
if (options.preferThumb && item.ImageTags && item.ImageTags.Thumb) {
|
if (options.preferThumb && item.ImageTags && item.ImageTags.Thumb) {
|
||||||
|
imgType = 'Thumb';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.Id, {
|
imgTag = item.ImageTags.Thumb;
|
||||||
type: "Thumb",
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ImageTags.Thumb
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if ((options.preferBanner || shape === 'banner') && item.ImageTags && item.ImageTags.Banner) {
|
} else if ((options.preferBanner || shape === 'banner') && item.ImageTags && item.ImageTags.Banner) {
|
||||||
|
imgType = 'Banner';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.Id, {
|
imgTag = item.ImageTags.Banner;
|
||||||
type: "Banner",
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ImageTags.Banner
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (options.preferDisc && item.ImageTags && item.ImageTags.Disc) {
|
} else if (options.preferDisc && item.ImageTags && item.ImageTags.Disc) {
|
||||||
|
imgType = 'Disc';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.Id, {
|
imgTag = item.ImageTags.Disc;
|
||||||
type: "Disc",
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ImageTags.Disc
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (options.preferLogo && item.ImageTags && item.ImageTags.Logo) {
|
} else if (options.preferLogo && item.ImageTags && item.ImageTags.Logo) {
|
||||||
|
imgType = 'Logo';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.Id, {
|
imgTag = item.ImageTags.Logo;
|
||||||
type: "Logo",
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ImageTags.Logo
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (options.preferLogo && item.ParentLogoImageTag && item.ParentLogoItemId) {
|
} else if (options.preferLogo && item.ParentLogoImageTag && item.ParentLogoItemId) {
|
||||||
|
imgType = 'Logo';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.ParentLogoItemId, {
|
imgTag = item.ParentLogoImageTag;
|
||||||
type: "Logo",
|
itemId = item.ParentLogoItemId;
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ParentLogoImageTag
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (options.preferThumb && item.SeriesThumbImageTag && options.inheritThumb !== false) {
|
} else if (options.preferThumb && item.SeriesThumbImageTag && options.inheritThumb !== false) {
|
||||||
|
imgType = 'Thumb';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.SeriesId, {
|
imgTag = item.SeriesThumbImageTag;
|
||||||
type: "Thumb",
|
itemId = item.SeriesId;
|
||||||
maxWidth: width,
|
|
||||||
tag: item.SeriesThumbImageTag
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (options.preferThumb && item.ParentThumbItemId && options.inheritThumb !== false && item.MediaType !== 'Photo') {
|
} else if (options.preferThumb && item.ParentThumbItemId && options.inheritThumb !== false && item.MediaType !== 'Photo') {
|
||||||
|
imgType = 'Thumb';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.ParentThumbItemId, {
|
imgTag = item.ParentThumbImageTag;
|
||||||
type: "Thumb",
|
itemId = item.ParentThumbItemId;
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ParentThumbImageTag
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (options.preferThumb && item.BackdropImageTags && item.BackdropImageTags.length) {
|
} else if (options.preferThumb && item.BackdropImageTags && item.BackdropImageTags.length) {
|
||||||
|
imgType = 'Backdrop';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.Id, {
|
imgTag = item.BackdropImageTags[0];
|
||||||
type: "Backdrop",
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.BackdropImageTags[0]
|
|
||||||
});
|
|
||||||
|
|
||||||
forceName = true;
|
forceName = true;
|
||||||
|
|
||||||
} else if (options.preferThumb && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length && options.inheritThumb !== false && item.Type === 'Episode') {
|
} else if (options.preferThumb && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length && options.inheritThumb !== false && item.Type === 'Episode') {
|
||||||
|
imgType = 'Backdrop';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.ParentBackdropItemId, {
|
imgTag = item.ParentBackdropImageTags[0];
|
||||||
type: "Backdrop",
|
itemId = item.ParentBackdropItemId;
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ParentBackdropImageTags[0]
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (item.ImageTags && item.ImageTags.Primary) {
|
} else if (item.ImageTags && item.ImageTags.Primary) {
|
||||||
|
imgType = 'Primary';
|
||||||
|
imgTag = item.ImageTags.Primary;
|
||||||
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
|
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
|
||||||
|
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.Id, {
|
|
||||||
type: "Primary",
|
|
||||||
maxHeight: height,
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ImageTags.Primary
|
|
||||||
});
|
|
||||||
|
|
||||||
if (options.preferThumb && options.showTitle !== false) {
|
if (options.preferThumb && options.showTitle !== false) {
|
||||||
forceName = true;
|
forceName = true;
|
||||||
}
|
}
|
||||||
|
@ -603,16 +558,11 @@ import 'programStyles';
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (item.PrimaryImageTag) {
|
} else if (item.PrimaryImageTag) {
|
||||||
|
imgType = 'Primary';
|
||||||
|
imgTag = item.PrimaryImageTag;
|
||||||
|
itemId = item.PrimaryImageItemId;
|
||||||
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
|
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
|
||||||
|
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.PrimaryImageItemId || item.Id || item.ItemId, {
|
|
||||||
type: "Primary",
|
|
||||||
maxHeight: height,
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.PrimaryImageTag
|
|
||||||
});
|
|
||||||
|
|
||||||
if (options.preferThumb && options.showTitle !== false) {
|
if (options.preferThumb && options.showTitle !== false) {
|
||||||
forceName = true;
|
forceName = true;
|
||||||
}
|
}
|
||||||
|
@ -624,30 +574,19 @@ import 'programStyles';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (item.ParentPrimaryImageTag) {
|
} else if (item.ParentPrimaryImageTag) {
|
||||||
|
imgType = 'Primary';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.ParentPrimaryImageItemId, {
|
imgTag = item.ParentPrimaryImageTag;
|
||||||
type: "Primary",
|
itemId = item.ParentPrimaryImageItemId;
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ParentPrimaryImageTag
|
|
||||||
});
|
|
||||||
} else if (item.SeriesPrimaryImageTag) {
|
} else if (item.SeriesPrimaryImageTag) {
|
||||||
|
imgType = 'Primary';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.SeriesId, {
|
imgTag = item.SeriesPrimaryImageTag;
|
||||||
type: "Primary",
|
itemId = item.SeriesId;
|
||||||
maxWidth: width,
|
|
||||||
tag: item.SeriesPrimaryImageTag
|
|
||||||
});
|
|
||||||
} else if (item.AlbumId && item.AlbumPrimaryImageTag) {
|
} else if (item.AlbumId && item.AlbumPrimaryImageTag) {
|
||||||
|
imgType = 'Primary';
|
||||||
|
imgTag = item.AlbumPrimaryImageTag;
|
||||||
|
itemId = item.AlbumId;
|
||||||
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
|
height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null;
|
||||||
|
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.AlbumId, {
|
|
||||||
type: "Primary",
|
|
||||||
maxHeight: height,
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.AlbumPrimaryImageTag
|
|
||||||
});
|
|
||||||
|
|
||||||
if (primaryImageAspectRatio) {
|
if (primaryImageAspectRatio) {
|
||||||
uiAspect = getDesiredAspect(shape);
|
uiAspect = getDesiredAspect(shape);
|
||||||
if (uiAspect) {
|
if (uiAspect) {
|
||||||
|
@ -655,57 +594,46 @@ import 'programStyles';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (item.Type === 'Season' && item.ImageTags && item.ImageTags.Thumb) {
|
} else if (item.Type === 'Season' && item.ImageTags && item.ImageTags.Thumb) {
|
||||||
|
imgType = 'Thumb';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.Id, {
|
imgTag = item.ImageTags.Thumb;
|
||||||
type: "Thumb",
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ImageTags.Thumb
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (item.BackdropImageTags && item.BackdropImageTags.length) {
|
} else if (item.BackdropImageTags && item.BackdropImageTags.length) {
|
||||||
|
imgType = 'Backdrop';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.Id, {
|
imgTag = item.BackdropImageTags[0];
|
||||||
type: "Backdrop",
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.BackdropImageTags[0]
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (item.ImageTags && item.ImageTags.Thumb) {
|
} else if (item.ImageTags && item.ImageTags.Thumb) {
|
||||||
|
imgType = 'Thumb';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.Id, {
|
imgTag = item.ImageTags.Thumb;
|
||||||
type: "Thumb",
|
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ImageTags.Thumb
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (item.SeriesThumbImageTag && options.inheritThumb !== false) {
|
} else if (item.SeriesThumbImageTag && options.inheritThumb !== false) {
|
||||||
|
imgType = 'Thumb';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.SeriesId, {
|
imgTag = item.SeriesThumbImageTag;
|
||||||
type: "Thumb",
|
itemId = item.SeriesId;
|
||||||
maxWidth: width,
|
|
||||||
tag: item.SeriesThumbImageTag
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (item.ParentThumbItemId && options.inheritThumb !== false) {
|
} else if (item.ParentThumbItemId && options.inheritThumb !== false) {
|
||||||
|
imgType = 'Thumb';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.ParentThumbItemId, {
|
imgTag = item.ParentThumbImageTag;
|
||||||
type: "Thumb",
|
itemId = item.ParentThumbItemId;
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ParentThumbImageTag
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (item.ParentBackdropImageTags && item.ParentBackdropImageTags.length && options.inheritThumb !== false) {
|
} else if (item.ParentBackdropImageTags && item.ParentBackdropImageTags.length && options.inheritThumb !== false) {
|
||||||
|
imgType = 'Backdrop';
|
||||||
imgUrl = apiClient.getScaledImageUrl(item.ParentBackdropItemId, {
|
imgTag = item.ParentBackdropImageTags[0];
|
||||||
type: "Backdrop",
|
itemId = item.ParentBackdropItemId;
|
||||||
maxWidth: width,
|
|
||||||
tag: item.ParentBackdropImageTags[0]
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!itemId) {
|
||||||
|
itemId = item.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imgTag && imgType) {
|
||||||
|
imgUrl = apiClient.getScaledImageUrl(itemId, {
|
||||||
|
type: imgType,
|
||||||
|
maxHeight: height,
|
||||||
|
maxWidth: width,
|
||||||
|
tag: imgTag
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let blurHashes = options.imageBlurhashes || item.ImageBlurHashes || {};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
imgUrl: imgUrl,
|
imgUrl: imgUrl,
|
||||||
|
blurhash: (blurHashes[imgType] || {})[imgTag],
|
||||||
forceName: forceName,
|
forceName: forceName,
|
||||||
coverImage: coverImage
|
coverImage: coverImage
|
||||||
};
|
};
|
||||||
|
@ -778,7 +706,7 @@ import 'programStyles';
|
||||||
if (text) {
|
if (text) {
|
||||||
html += "<div class='" + currentCssClass + "'>";
|
html += "<div class='" + currentCssClass + "'>";
|
||||||
html += text;
|
html += text;
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
valid++;
|
valid++;
|
||||||
|
|
||||||
if (maxLines && valid >= maxLines) {
|
if (maxLines && valid >= maxLines) {
|
||||||
|
@ -835,7 +763,7 @@ import 'programStyles';
|
||||||
airTimeText += ' - ' + datetime.getDisplayTime(date);
|
airTimeText += ' - ' + datetime.getDisplayTime(date);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("error parsing date: " + item.StartDate);
|
console.error('error parsing date: ' + item.StartDate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -869,11 +797,11 @@ import 'programStyles';
|
||||||
if (isOuterFooter && options.cardLayout && layoutManager.mobile) {
|
if (isOuterFooter && options.cardLayout && layoutManager.mobile) {
|
||||||
|
|
||||||
if (options.cardFooterAside !== 'none') {
|
if (options.cardFooterAside !== 'none') {
|
||||||
html += '<button is="paper-icon-button-light" class="itemAction btnCardOptions cardText-secondary" data-action="menu"><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_vert"></span></button>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const cssClass = options.centerText ? "cardText cardTextCentered" : "cardText";
|
const cssClass = options.centerText ? 'cardText cardTextCentered' : 'cardText';
|
||||||
const serverId = item.ServerId || options.serverId;
|
const serverId = item.ServerId || options.serverId;
|
||||||
|
|
||||||
let lines = [];
|
let lines = [];
|
||||||
|
@ -907,7 +835,7 @@ import 'programStyles';
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
const parentTitle = item.SeriesName || item.Series || item.Album || item.AlbumArtist || "";
|
const parentTitle = item.SeriesName || item.Series || item.Album || item.AlbumArtist || '';
|
||||||
|
|
||||||
if (parentTitle || showTitle) {
|
if (parentTitle || showTitle) {
|
||||||
lines.push(parentTitle);
|
lines.push(parentTitle);
|
||||||
|
@ -946,7 +874,7 @@ import 'programStyles';
|
||||||
item.AlbumArtists[0].IsFolder = true;
|
item.AlbumArtists[0].IsFolder = true;
|
||||||
lines.push(getTextActionButton(item.AlbumArtists[0], null, serverId));
|
lines.push(getTextActionButton(item.AlbumArtists[0], null, serverId));
|
||||||
} else {
|
} 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 +921,7 @@ import 'programStyles';
|
||||||
if (options.showYear || options.showSeriesYear) {
|
if (options.showYear || options.showSeriesYear) {
|
||||||
|
|
||||||
if (item.Type === 'Series') {
|
if (item.Type === 'Series') {
|
||||||
if (item.Status === "Continuing") {
|
if (item.Status === 'Continuing') {
|
||||||
|
|
||||||
lines.push(globalize.translate('SeriesYearToPresent', item.ProductionYear || ''));
|
lines.push(globalize.translate('SeriesYearToPresent', item.ProductionYear || ''));
|
||||||
|
|
||||||
|
@ -1105,7 +1033,7 @@ import 'programStyles';
|
||||||
html = '<div class="' + footerClass + '">' + html;
|
html = '<div class="' + footerClass + '">' + html;
|
||||||
|
|
||||||
//cardFooter
|
//cardFooter
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1191,7 +1119,7 @@ import 'programStyles';
|
||||||
counts.push(childText);
|
counts.push(childText);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (item.Type === 'MusicGenre' || options.context === "MusicArtist") {
|
} else if (item.Type === 'MusicGenre' || options.context === 'MusicArtist') {
|
||||||
|
|
||||||
if (item.AlbumCount) {
|
if (item.AlbumCount) {
|
||||||
|
|
||||||
|
@ -1304,7 +1232,7 @@ import 'programStyles';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.cardClass) {
|
if (options.cardClass) {
|
||||||
className += " " + options.cardClass;
|
className += ' ' + options.cardClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layoutManager.desktop) {
|
if (layoutManager.desktop) {
|
||||||
|
@ -1321,6 +1249,7 @@ import 'programStyles';
|
||||||
|
|
||||||
const imgInfo = getCardImageUrl(item, apiClient, options, shape);
|
const imgInfo = getCardImageUrl(item, apiClient, options, shape);
|
||||||
const imgUrl = imgInfo.imgUrl;
|
const imgUrl = imgInfo.imgUrl;
|
||||||
|
const blurhash = imgInfo.blurhash;
|
||||||
|
|
||||||
const forceName = imgInfo.forceName;
|
const forceName = imgInfo.forceName;
|
||||||
|
|
||||||
|
@ -1356,13 +1285,13 @@ import 'programStyles';
|
||||||
|
|
||||||
if (options.showChannelLogo && item.ChannelPrimaryImageTag) {
|
if (options.showChannelLogo && item.ChannelPrimaryImageTag) {
|
||||||
logoUrl = apiClient.getScaledImageUrl(item.ChannelId, {
|
logoUrl = apiClient.getScaledImageUrl(item.ChannelId, {
|
||||||
type: "Primary",
|
type: 'Primary',
|
||||||
height: logoHeight,
|
height: logoHeight,
|
||||||
tag: item.ChannelPrimaryImageTag
|
tag: item.ChannelPrimaryImageTag
|
||||||
});
|
});
|
||||||
} else if (options.showLogo && item.ParentLogoImageTag) {
|
} else if (options.showLogo && item.ParentLogoImageTag) {
|
||||||
logoUrl = apiClient.getScaledImageUrl(item.ParentLogoItemId, {
|
logoUrl = apiClient.getScaledImageUrl(item.ParentLogoItemId, {
|
||||||
type: "Logo",
|
type: 'Logo',
|
||||||
height: logoHeight,
|
height: logoHeight,
|
||||||
tag: item.ParentLogoImageTag
|
tag: item.ParentLogoImageTag
|
||||||
});
|
});
|
||||||
|
@ -1418,15 +1347,15 @@ import 'programStyles';
|
||||||
const btnCssClass = 'cardOverlayButton cardOverlayButton-br itemAction';
|
const btnCssClass = 'cardOverlayButton cardOverlayButton-br itemAction';
|
||||||
|
|
||||||
if (options.centerPlayButton) {
|
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') {
|
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) {
|
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_vert"></span></button>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1445,15 +1374,20 @@ import 'programStyles';
|
||||||
cardContentClass += ' cardContent-shadow';
|
cardContentClass += ' cardContent-shadow';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let blurhashAttrib = '';
|
||||||
|
if (blurhash && blurhash.length > 0) {
|
||||||
|
blurhashAttrib = 'data-blurhash="' + blurhash + '"';
|
||||||
|
}
|
||||||
|
|
||||||
if (layoutManager.tv) {
|
if (layoutManager.tv) {
|
||||||
|
|
||||||
// Don't use the IMG tag with safari because it puts a white border around it
|
// Don't use the IMG tag with safari because it puts a white border around it
|
||||||
cardImageContainerOpen = imgUrl ? ('<div class="' + cardImageContainerClass + ' ' + cardContentClass + ' lazy" data-src="' + imgUrl + '">') : ('<div class="' + cardImageContainerClass + ' ' + cardContentClass + '">');
|
cardImageContainerOpen = imgUrl ? ('<div class="' + cardImageContainerClass + ' ' + cardContentClass + ' lazy" data-src="' + imgUrl + '" ' + blurhashAttrib + '>') : ('<div class="' + cardImageContainerClass + ' ' + cardContentClass + '">');
|
||||||
|
|
||||||
cardImageContainerClose = '</div>';
|
cardImageContainerClose = '</div>';
|
||||||
} else {
|
} else {
|
||||||
// Don't use the IMG tag with safari because it puts a white border around it
|
// Don't use the IMG tag with safari because it puts a white border around it
|
||||||
cardImageContainerOpen = imgUrl ? ('<button data-action="' + action + '" class="cardContent-button ' + cardImageContainerClass + ' ' + cardContentClass + ' itemAction lazy" data-src="' + imgUrl + '">') : ('<button data-action="' + action + '" class="cardContent-button ' + cardImageContainerClass + ' ' + cardContentClass + ' itemAction">');
|
cardImageContainerOpen = imgUrl ? ('<button data-action="' + action + '" class="cardContent-button ' + cardImageContainerClass + ' ' + cardContentClass + ' itemAction lazy" data-src="' + imgUrl + '" ' + blurhashAttrib + '>') : ('<button data-action="' + action + '" class="cardContent-button ' + cardImageContainerClass + ' ' + cardContentClass + ' itemAction">');
|
||||||
|
|
||||||
cardImageContainerClose = '</button>';
|
cardImageContainerClose = '</button>';
|
||||||
}
|
}
|
||||||
|
@ -1518,7 +1452,7 @@ import 'programStyles';
|
||||||
let actionAttribute;
|
let actionAttribute;
|
||||||
|
|
||||||
if (tagName === 'button') {
|
if (tagName === 'button') {
|
||||||
className += " itemAction";
|
className += ' itemAction';
|
||||||
actionAttribute = ' data-action="' + action + '"';
|
actionAttribute = ' data-action="' + action + '"';
|
||||||
} else {
|
} else {
|
||||||
actionAttribute = '';
|
actionAttribute = '';
|
||||||
|
@ -1560,7 +1494,7 @@ import 'programStyles';
|
||||||
const btnCssClass = 'cardOverlayButton cardOverlayButton-hover itemAction paper-icon-button-light';
|
const btnCssClass = 'cardOverlayButton cardOverlayButton-hover itemAction paper-icon-button-light';
|
||||||
|
|
||||||
if (playbackManager.canPlay(item)) {
|
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">';
|
html += '<div class="cardOverlayButton-br flex">';
|
||||||
|
@ -1569,7 +1503,7 @@ import 'programStyles';
|
||||||
|
|
||||||
if (itemHelper.canMarkPlayed(item)) {
|
if (itemHelper.canMarkPlayed(item)) {
|
||||||
require(['emby-playstatebutton']);
|
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)) {
|
if (itemHelper.canRate(item)) {
|
||||||
|
@ -1577,10 +1511,10 @@ import 'programStyles';
|
||||||
const likes = userData.Likes == null ? '' : userData.Likes;
|
const likes = userData.Likes == null ? '' : userData.Likes;
|
||||||
|
|
||||||
require(['emby-ratingbutton']);
|
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_vert"></span></button>';
|
||||||
|
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
@ -1596,27 +1530,27 @@ import 'programStyles';
|
||||||
*/
|
*/
|
||||||
export function getDefaultText(item, options) {
|
export function getDefaultText(item, options) {
|
||||||
if (item.CollectionType) {
|
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) {
|
switch (item.Type) {
|
||||||
case 'MusicAlbum':
|
case 'MusicAlbum':
|
||||||
return '<i class="cardImageIcon material-icons">album</i>';
|
return '<span class="cardImageIcon material-icons album"></span>';
|
||||||
case 'MusicArtist':
|
case 'MusicArtist':
|
||||||
case 'Person':
|
case 'Person':
|
||||||
return '<i class="cardImageIcon material-icons">person</i>';
|
return '<span class="cardImageIcon material-icons person"></span>';
|
||||||
case 'Movie':
|
case 'Movie':
|
||||||
return '<i class="cardImageIcon material-icons">movie</i>';
|
return '<span class="cardImageIcon material-icons movie"></span>';
|
||||||
case 'Series':
|
case 'Series':
|
||||||
return '<i class="cardImageIcon material-icons">tv</i>';
|
return '<span class="cardImageIcon material-icons tv"></span>';
|
||||||
case 'Book':
|
case 'Book':
|
||||||
return '<i class="cardImageIcon material-icons">book</i>';
|
return '<span class="cardImageIcon material-icons book"></span>';
|
||||||
case 'Folder':
|
case 'Folder':
|
||||||
return '<i class="cardImageIcon material-icons">folder</i>';
|
return '<span class="cardImageIcon material-icons folder"></span>';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options && options.defaultCardImageIcon) {
|
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);
|
const defaultName = isUsingLiveTvNaming(item) ? item.Name : itemHelper.getDisplayName(item);
|
||||||
|
@ -1718,7 +1652,7 @@ import 'programStyles';
|
||||||
indicatorsElem = ensureIndicators(card, indicatorsElem);
|
indicatorsElem = ensureIndicators(card, indicatorsElem);
|
||||||
indicatorsElem.appendChild(playedIndicator);
|
indicatorsElem.appendChild(playedIndicator);
|
||||||
}
|
}
|
||||||
playedIndicator.innerHTML = '<i class="material-icons indicatorIcon">check</i>';
|
playedIndicator.innerHTML = '<span class="material-icons indicatorIcon check"></span>';
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
playedIndicator = card.querySelector('.playedIndicator');
|
playedIndicator = card.querySelector('.playedIndicator');
|
||||||
|
@ -1808,7 +1742,7 @@ import 'programStyles';
|
||||||
const icon = cell.querySelector('.timerIndicator');
|
const icon = cell.querySelector('.timerIndicator');
|
||||||
if (!icon) {
|
if (!icon) {
|
||||||
const indicatorsElem = ensureIndicators(cell);
|
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);
|
cell.setAttribute('data-timerid', newTimerId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,23 @@
|
||||||
define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browser'], function (datetime, imageLoader, connectionManager, layoutManager, browser) {
|
/* eslint-disable indent */
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var enableFocusTransform = !browser.slow && !browser.edge;
|
/**
|
||||||
|
* Module for building cards from item data.
|
||||||
|
* @module components/cardBuilder/chaptercardbuilder
|
||||||
|
*/
|
||||||
|
|
||||||
|
import datetime from 'datetime';
|
||||||
|
import imageLoader from 'imageLoader';
|
||||||
|
import connectionManager from 'connectionManager';
|
||||||
|
import layoutManager from 'layoutManager';
|
||||||
|
import browser from 'browser';
|
||||||
|
|
||||||
|
const enableFocusTransform = !browser.slow && !browser.edge;
|
||||||
|
|
||||||
function buildChapterCardsHtml(item, chapters, options) {
|
function buildChapterCardsHtml(item, chapters, options) {
|
||||||
|
|
||||||
// TODO move card creation code to Card component
|
// TODO move card creation code to Card component
|
||||||
|
|
||||||
var className = 'card itemAction chapterCard';
|
let className = 'card itemAction chapterCard';
|
||||||
|
|
||||||
if (layoutManager.tv) {
|
if (layoutManager.tv) {
|
||||||
className += ' show-focus';
|
className += ' show-focus';
|
||||||
|
@ -17,12 +27,12 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var mediaStreams = ((item.MediaSources || [])[0] || {}).MediaStreams || [];
|
const mediaStreams = ((item.MediaSources || [])[0] || {}).MediaStreams || [];
|
||||||
var videoStream = mediaStreams.filter(function (i) {
|
const videoStream = mediaStreams.filter(({Type}) => {
|
||||||
return i.Type === 'Video';
|
return Type === 'Video';
|
||||||
})[0] || {};
|
})[0] || {};
|
||||||
|
|
||||||
var shape = (options.backdropShape || 'backdrop');
|
let shape = (options.backdropShape || 'backdrop');
|
||||||
|
|
||||||
if (videoStream.Width && videoStream.Height) {
|
if (videoStream.Width && videoStream.Height) {
|
||||||
|
|
||||||
|
@ -31,24 +41,24 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
className += ' ' + shape + 'Card';
|
className += ` ${shape}Card`;
|
||||||
|
|
||||||
if (options.block || options.rows) {
|
if (options.block || options.rows) {
|
||||||
className += ' block';
|
className += ' block';
|
||||||
}
|
}
|
||||||
|
|
||||||
var html = '';
|
let html = '';
|
||||||
var itemsInRow = 0;
|
let itemsInRow = 0;
|
||||||
|
|
||||||
var apiClient = connectionManager.getApiClient(item.ServerId);
|
const apiClient = connectionManager.getApiClient(item.ServerId);
|
||||||
|
|
||||||
for (var i = 0, length = chapters.length; i < length; i++) {
|
for (let i = 0, length = chapters.length; i < length; i++) {
|
||||||
|
|
||||||
if (options.rows && itemsInRow === 0) {
|
if (options.rows && itemsInRow === 0) {
|
||||||
html += '<div class="cardColumn">';
|
html += '<div class="cardColumn">';
|
||||||
}
|
}
|
||||||
|
|
||||||
var chapter = chapters[i];
|
const chapter = chapters[i];
|
||||||
|
|
||||||
html += buildChapterCard(item, apiClient, chapter, i, options, className, shape);
|
html += buildChapterCard(item, apiClient, chapter, i, options, className, shape);
|
||||||
itemsInRow++;
|
itemsInRow++;
|
||||||
|
@ -62,50 +72,50 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browse
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getImgUrl(item, chapter, index, maxWidth, apiClient) {
|
function getImgUrl({Id}, {ImageTag}, index, maxWidth, apiClient) {
|
||||||
|
|
||||||
if (chapter.ImageTag) {
|
if (ImageTag) {
|
||||||
|
|
||||||
return apiClient.getScaledImageUrl(item.Id, {
|
return apiClient.getScaledImageUrl(Id, {
|
||||||
|
|
||||||
maxWidth: maxWidth * 2,
|
maxWidth: maxWidth * 2,
|
||||||
tag: chapter.ImageTag,
|
tag: ImageTag,
|
||||||
type: "Chapter",
|
type: 'Chapter',
|
||||||
index: index
|
index
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildChapterCard(item, apiClient, chapter, index, options, className, shape) {
|
function buildChapterCard(item, apiClient, chapter, index, {width, coverImage}, className, shape) {
|
||||||
|
|
||||||
var imgUrl = getImgUrl(item, chapter, index, options.width || 400, apiClient);
|
const imgUrl = getImgUrl(item, chapter, index, width || 400, apiClient);
|
||||||
|
|
||||||
var cardImageContainerClass = 'cardContent cardContent-shadow cardImageContainer chapterCardImageContainer';
|
let cardImageContainerClass = 'cardContent cardContent-shadow cardImageContainer chapterCardImageContainer';
|
||||||
if (options.coverImage) {
|
if (coverImage) {
|
||||||
cardImageContainerClass += ' coveredImage';
|
cardImageContainerClass += ' coveredImage';
|
||||||
}
|
}
|
||||||
var dataAttributes = ' data-action="play" data-isfolder="' + item.IsFolder + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-type="' + item.Type + '" data-mediatype="' + item.MediaType + '" data-positionticks="' + chapter.StartPositionTicks + '"';
|
const dataAttributes = ` data-action="play" data-isfolder="${item.IsFolder}" data-id="${item.Id}" data-serverid="${item.ServerId}" data-type="${item.Type}" data-mediatype="${item.MediaType}" data-positionticks="${chapter.StartPositionTicks}"`;
|
||||||
var cardImageContainer = imgUrl ? ('<div class="' + cardImageContainerClass + ' lazy" data-src="' + imgUrl + '">') : ('<div class="' + cardImageContainerClass + '">');
|
let cardImageContainer = imgUrl ? (`<div class="${cardImageContainerClass} lazy" data-src="${imgUrl}">`) : (`<div class="${cardImageContainerClass}">`);
|
||||||
|
|
||||||
if (!imgUrl) {
|
if (!imgUrl) {
|
||||||
cardImageContainer += '<i class="material-icons cardImageIcon local_movies"></i>';
|
cardImageContainer += '<span class="material-icons cardImageIcon local_movies"></span>';
|
||||||
}
|
}
|
||||||
|
|
||||||
var nameHtml = '';
|
let nameHtml = '';
|
||||||
nameHtml += '<div class="cardText">' + chapter.Name + '</div>';
|
nameHtml += `<div class="cardText">${chapter.Name}</div>`;
|
||||||
nameHtml += '<div class="cardText">' + datetime.getDisplayRunningTime(chapter.StartPositionTicks) + '</div>';
|
nameHtml += `<div class="cardText">${datetime.getDisplayRunningTime(chapter.StartPositionTicks)}</div>`;
|
||||||
|
|
||||||
var cardBoxCssClass = 'cardBox';
|
const cardBoxCssClass = 'cardBox';
|
||||||
var cardScalableClass = 'cardScalable';
|
const cardScalableClass = 'cardScalable';
|
||||||
|
|
||||||
var html = '<button type="button" class="' + className + '"' + dataAttributes + '><div class="' + cardBoxCssClass + '"><div class="' + cardScalableClass + '"><div class="cardPadder-' + shape + '"></div>' + cardImageContainer + '</div><div class="innerCardFooter">' + nameHtml + '</div></div></div></button>';
|
const html = `<button type="button" class="${className}"${dataAttributes}><div class="${cardBoxCssClass}"><div class="${cardScalableClass}"><div class="cardPadder-${shape}"></div>${cardImageContainer}</div><div class="innerCardFooter">${nameHtml}</div></div></div></button>`;
|
||||||
|
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildChapterCards(item, chapters, options) {
|
export function buildChapterCards(item, chapters, options) {
|
||||||
|
|
||||||
if (options.parentContainer) {
|
if (options.parentContainer) {
|
||||||
// Abort if the container has been disposed
|
// Abort if the container has been disposed
|
||||||
|
@ -121,15 +131,16 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var html = buildChapterCardsHtml(item, chapters, options);
|
const html = buildChapterCardsHtml(item, chapters, options);
|
||||||
|
|
||||||
options.itemsContainer.innerHTML = html;
|
options.itemsContainer.innerHTML = html;
|
||||||
|
|
||||||
imageLoader.lazyChildren(options.itemsContainer);
|
imageLoader.lazyChildren(options.itemsContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
/* eslint-enable indent */
|
||||||
buildChapterCards: buildChapterCards
|
|
||||||
};
|
export default {
|
||||||
|
buildChapterCards: buildChapterCards
|
||||||
|
};
|
||||||
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
define(['cardBuilder'], function (cardBuilder) {
|
/* eslint-disable indent */
|
||||||
'use strict';
|
|
||||||
|
|
||||||
function buildPeopleCards(items, options) {
|
/**
|
||||||
|
* Module for building cards from item data.
|
||||||
|
* @module components/cardBuilder/peoplecardbuilder
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cardBuilder from 'cardBuilder';
|
||||||
|
|
||||||
|
export function buildPeopleCards(items, options) {
|
||||||
|
|
||||||
options = Object.assign(options || {}, {
|
options = Object.assign(options || {}, {
|
||||||
cardLayout: false,
|
cardLayout: false,
|
||||||
|
@ -15,8 +21,8 @@ define(['cardBuilder'], function (cardBuilder) {
|
||||||
cardBuilder.buildCards(items, options);
|
cardBuilder.buildCards(items, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
/* eslint-enable indent */
|
||||||
buildPeopleCards: buildPeopleCards
|
|
||||||
};
|
|
||||||
|
|
||||||
});
|
export default {
|
||||||
|
buildPeopleCards: buildPeopleCards
|
||||||
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
define([], function() {
|
define([], function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
if (window.appMode === "cordova" || window.appMode === "android") {
|
if (window.appMode === 'cordova' || window.appMode === 'android') {
|
||||||
return {
|
return {
|
||||||
load: function () {
|
load: function () {
|
||||||
window.chrome = window.chrome || {};
|
window.chrome = window.chrome || {};
|
||||||
|
@ -17,16 +17,16 @@ define([], function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
var fileref = document.createElement("script");
|
var fileref = document.createElement('script');
|
||||||
fileref.setAttribute("type", "text/javascript");
|
fileref.setAttribute('type', 'text/javascript');
|
||||||
|
|
||||||
fileref.onload = function () {
|
fileref.onload = function () {
|
||||||
ccLoaded = true;
|
ccLoaded = true;
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
|
|
||||||
fileref.setAttribute("src", "https://www.gstatic.com/cv/js/sender/v1/cast_sender.js");
|
fileref.setAttribute('src', 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js');
|
||||||
document.querySelector("head").appendChild(fileref);
|
document.querySelector('head').appendChild(fileref);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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) {
|
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";
|
'use strict';
|
||||||
|
|
||||||
return function (options) {
|
return function (options) {
|
||||||
function mapChannel(button, channelId, providerChannelId) {
|
function mapChannel(button, channelId, providerChannelId) {
|
||||||
loading.show();
|
loading.show();
|
||||||
var providerId = options.providerId;
|
var providerId = options.providerId;
|
||||||
connectionManager.getApiClient(options.serverId).ajax({
|
connectionManager.getApiClient(options.serverId).ajax({
|
||||||
type: "POST",
|
type: 'POST',
|
||||||
url: ApiClient.getUrl("LiveTv/ChannelMappings"),
|
url: ApiClient.getUrl('LiveTv/ChannelMappings'),
|
||||||
data: {
|
data: {
|
||||||
providerId: providerId,
|
providerId: providerId,
|
||||||
tunerChannelId: channelId,
|
tunerChannelId: channelId,
|
||||||
providerChannelId: providerChannelId
|
providerChannelId: providerChannelId
|
||||||
},
|
},
|
||||||
dataType: "json"
|
dataType: 'json'
|
||||||
}).then(function (mapping) {
|
}).then(function (mapping) {
|
||||||
var listItem = dom.parentWithClass(button, "listItem");
|
var listItem = dom.parentWithClass(button, 'listItem');
|
||||||
button.setAttribute("data-providerid", mapping.ProviderChannelId);
|
button.setAttribute('data-providerid', mapping.ProviderChannelId);
|
||||||
listItem.querySelector(".secondary").innerHTML = getMappingSecondaryName(mapping, currentMappingOptions.ProviderName);
|
listItem.querySelector('.secondary').innerHTML = getMappingSecondaryName(mapping, currentMappingOptions.ProviderName);
|
||||||
loading.hide();
|
loading.hide();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onChannelsElementClick(e) {
|
function onChannelsElementClick(e) {
|
||||||
var btnMap = dom.parentWithClass(e.target, "btnMap");
|
var btnMap = dom.parentWithClass(e.target, 'btnMap');
|
||||||
|
|
||||||
if (btnMap) {
|
if (btnMap) {
|
||||||
var channelId = btnMap.getAttribute("data-id");
|
var channelId = btnMap.getAttribute('data-id');
|
||||||
var providerChannelId = btnMap.getAttribute("data-providerid");
|
var providerChannelId = btnMap.getAttribute('data-providerid');
|
||||||
var menuItems = currentMappingOptions.ProviderChannels.map(function (m) {
|
var menuItems = currentMappingOptions.ProviderChannels.map(function (m) {
|
||||||
return {
|
return {
|
||||||
name: m.Name,
|
name: m.Name,
|
||||||
|
@ -48,56 +48,56 @@ define(["dom", "dialogHelper", "loading", "connectionManager", "globalize", "act
|
||||||
|
|
||||||
function getChannelMappingOptions(serverId, providerId) {
|
function getChannelMappingOptions(serverId, providerId) {
|
||||||
var apiClient = connectionManager.getApiClient(serverId);
|
var apiClient = connectionManager.getApiClient(serverId);
|
||||||
return apiClient.getJSON(apiClient.getUrl("LiveTv/ChannelMappingOptions", {
|
return apiClient.getJSON(apiClient.getUrl('LiveTv/ChannelMappingOptions', {
|
||||||
providerId: providerId
|
providerId: providerId
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMappingSecondaryName(mapping, providerName) {
|
function getMappingSecondaryName(mapping, providerName) {
|
||||||
return (mapping.ProviderChannelName || "") + " - " + providerName;
|
return (mapping.ProviderChannelName || '') + ' - ' + providerName;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTunerChannelHtml(channel, providerName) {
|
function getTunerChannelHtml(channel, providerName) {
|
||||||
var html = "";
|
var html = '';
|
||||||
html += '<div class="listItem">';
|
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 += '<div class="listItemBody two-line">';
|
||||||
html += '<h3 class="listItemBodyText">';
|
html += '<h3 class="listItemBodyText">';
|
||||||
html += channel.Name;
|
html += channel.Name;
|
||||||
html += "</h3>";
|
html += '</h3>';
|
||||||
html += '<div class="secondary listItemBodyText">';
|
html += '<div class="secondary listItemBodyText">';
|
||||||
|
|
||||||
if (channel.ProviderChannelName) {
|
if (channel.ProviderChannelName) {
|
||||||
html += getMappingSecondaryName(channel, providerName);
|
html += getMappingSecondaryName(channel, providerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
html += '<button class="btnMap autoSize" is="paper-icon-button-light" type="button" data-id="' + channel.Id + '" data-providerid="' + channel.ProviderChannelId + '"><i class="material-icons mode_edit"></i></button>';
|
html += '<button class="btnMap autoSize" is="paper-icon-button-light" type="button" data-id="' + channel.Id + '" data-providerid="' + channel.ProviderChannelId + '"><span class="material-icons mode_edit"></span></button>';
|
||||||
return html += "</div>";
|
return html += '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getEditorHtml() {
|
function getEditorHtml() {
|
||||||
var html = "";
|
var html = '';
|
||||||
html += '<div class="formDialogContent">';
|
html += '<div class="formDialogContent smoothScrollY">';
|
||||||
html += '<div class="dialogContentInner dialog-content-centered">';
|
html += '<div class="dialogContentInner dialog-content-centered">';
|
||||||
html += '<form style="margin:auto;">';
|
html += '<form style="margin:auto;">';
|
||||||
html += "<h1>" + globalize.translate("HeaderChannels") + "</h1>";
|
html += '<h1>' + globalize.translate('HeaderChannels') + '</h1>';
|
||||||
html += '<div class="channels paperList">';
|
html += '<div class="channels paperList">';
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
html += "</form>";
|
html += '</form>';
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
return html += "</div>";
|
return html += '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
function initEditor(dlg, options) {
|
function initEditor(dlg, options) {
|
||||||
getChannelMappingOptions(options.serverId, options.providerId).then(function (result) {
|
getChannelMappingOptions(options.serverId, options.providerId).then(function (result) {
|
||||||
currentMappingOptions = result;
|
currentMappingOptions = result;
|
||||||
var channelsElement = dlg.querySelector(".channels");
|
var channelsElement = dlg.querySelector('.channels');
|
||||||
channelsElement.innerHTML = result.TunerChannels.map(function (channel) {
|
channelsElement.innerHTML = result.TunerChannels.map(function (channel) {
|
||||||
return getTunerChannelHtml(channel, result.ProviderName);
|
return getTunerChannelHtml(channel, result.ProviderName);
|
||||||
}).join("");
|
}).join('');
|
||||||
channelsElement.addEventListener("click", onChannelsElementClick);
|
channelsElement.addEventListener('click', onChannelsElementClick);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,27 +108,27 @@ define(["dom", "dialogHelper", "loading", "connectionManager", "globalize", "act
|
||||||
var dialogOptions = {
|
var dialogOptions = {
|
||||||
removeOnClose: true
|
removeOnClose: true
|
||||||
};
|
};
|
||||||
dialogOptions.size = "small";
|
dialogOptions.size = 'small';
|
||||||
var dlg = dialogHelper.createDialog(dialogOptions);
|
var dlg = dialogHelper.createDialog(dialogOptions);
|
||||||
dlg.classList.add("formDialog");
|
dlg.classList.add('formDialog');
|
||||||
dlg.classList.add("ui-body-a");
|
dlg.classList.add('ui-body-a');
|
||||||
dlg.classList.add("background-theme-a");
|
dlg.classList.add('background-theme-a');
|
||||||
var html = "";
|
var html = '';
|
||||||
var title = globalize.translate("MapChannels");
|
var title = globalize.translate('MapChannels');
|
||||||
html += '<div class="formDialogHeader">';
|
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 += '<h3 class="formDialogHeaderTitle">';
|
||||||
html += title;
|
html += title;
|
||||||
html += "</h3>";
|
html += '</h3>';
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
html += getEditorHtml();
|
html += getEditorHtml();
|
||||||
dlg.innerHTML = html;
|
dlg.innerHTML = html;
|
||||||
initEditor(dlg, options);
|
initEditor(dlg, options);
|
||||||
dlg.querySelector(".btnCancel").addEventListener("click", function () {
|
dlg.querySelector('.btnCancel').addEventListener('click', function () {
|
||||||
dialogHelper.close(dlg);
|
dialogHelper.close(dlg);
|
||||||
});
|
});
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
dlg.addEventListener("close", resolve);
|
dlg.addEventListener('close', resolve);
|
||||||
dialogHelper.open(dlg);
|
dialogHelper.open(dlg);
|
||||||
});
|
});
|
||||||
};
|
};
|
|
@ -24,7 +24,7 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
|
||||||
|
|
||||||
function createCollection(apiClient, dlg) {
|
function createCollection(apiClient, dlg) {
|
||||||
|
|
||||||
var url = apiClient.getUrl("Collections", {
|
var url = apiClient.getUrl('Collections', {
|
||||||
|
|
||||||
Name: dlg.querySelector('#txtNewCollectionName').value,
|
Name: dlg.querySelector('#txtNewCollectionName').value,
|
||||||
IsLocked: !dlg.querySelector('#chkEnableInternetMetadata').checked,
|
IsLocked: !dlg.querySelector('#chkEnableInternetMetadata').checked,
|
||||||
|
@ -32,9 +32,9 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
|
||||||
});
|
});
|
||||||
|
|
||||||
apiClient.ajax({
|
apiClient.ajax({
|
||||||
type: "POST",
|
type: 'POST',
|
||||||
url: url,
|
url: url,
|
||||||
dataType: "json"
|
dataType: 'json'
|
||||||
|
|
||||||
}).then(function (result) {
|
}).then(function (result) {
|
||||||
|
|
||||||
|
@ -56,13 +56,13 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
|
||||||
|
|
||||||
function addToCollection(apiClient, dlg, id) {
|
function addToCollection(apiClient, dlg, id) {
|
||||||
|
|
||||||
var url = apiClient.getUrl("Collections/" + id + "/Items", {
|
var url = apiClient.getUrl('Collections/' + id + '/Items', {
|
||||||
|
|
||||||
Ids: dlg.querySelector('.fldSelectedItemIds').value || ''
|
Ids: dlg.querySelector('.fldSelectedItemIds').value || ''
|
||||||
});
|
});
|
||||||
|
|
||||||
apiClient.ajax({
|
apiClient.ajax({
|
||||||
type: "POST",
|
type: 'POST',
|
||||||
url: url
|
url: url
|
||||||
|
|
||||||
}).then(function () {
|
}).then(function () {
|
||||||
|
@ -93,8 +93,8 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
|
||||||
var options = {
|
var options = {
|
||||||
|
|
||||||
Recursive: true,
|
Recursive: true,
|
||||||
IncludeItemTypes: "BoxSet",
|
IncludeItemTypes: 'BoxSet',
|
||||||
SortBy: "SortName",
|
SortBy: 'SortName',
|
||||||
EnableTotalRecordCount: false
|
EnableTotalRecordCount: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -230,13 +230,13 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
|
||||||
var title = items.length ? globalize.translate('HeaderAddToCollection') : globalize.translate('NewCollection');
|
var title = items.length ? globalize.translate('HeaderAddToCollection') : globalize.translate('NewCollection');
|
||||||
|
|
||||||
html += '<div class="formDialogHeader">';
|
html += '<div class="formDialogHeader">';
|
||||||
html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><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 += '<h3 class="formDialogHeaderTitle">';
|
||||||
html += title;
|
html += title;
|
||||||
html += '</h3>';
|
html += '</h3>';
|
||||||
|
|
||||||
if (appHost.supports('externallinks')) {
|
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>';
|
html += '</div>';
|
|
@ -1,4 +1,4 @@
|
||||||
define(["browser", "dialog", "globalize"], function(browser, dialog, globalize) {
|
define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function replaceAll(str, find, replace) {
|
function replaceAll(str, find, replace) {
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
define(['connectionManager', 'confirm', 'appRouter', 'globalize'], function (connectionManager, confirm, appRouter, globalize) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
function alertText(options) {
|
|
||||||
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
|
|
||||||
require(['alert'], function (alert) {
|
|
||||||
alert(options).then(resolve, resolve);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteItem(options) {
|
|
||||||
|
|
||||||
var item = options.item;
|
|
||||||
var itemId = item.Id;
|
|
||||||
var parentId = item.SeasonId || item.SeriesId || item.ParentId;
|
|
||||||
var serverId = item.ServerId;
|
|
||||||
|
|
||||||
var msg = globalize.translate('ConfirmDeleteItem');
|
|
||||||
var title = globalize.translate('HeaderDeleteItem');
|
|
||||||
var apiClient = connectionManager.getApiClient(item.ServerId);
|
|
||||||
|
|
||||||
return confirm({
|
|
||||||
|
|
||||||
title: title,
|
|
||||||
text: msg,
|
|
||||||
confirmText: globalize.translate('Delete'),
|
|
||||||
primary: 'delete'
|
|
||||||
|
|
||||||
}).then(function () {
|
|
||||||
|
|
||||||
return apiClient.deleteItem(itemId).then(function () {
|
|
||||||
|
|
||||||
if (options.navigate) {
|
|
||||||
if (parentId) {
|
|
||||||
appRouter.showItem(parentId, serverId);
|
|
||||||
} else {
|
|
||||||
appRouter.goHome();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, function (err) {
|
|
||||||
|
|
||||||
var result = function () {
|
|
||||||
return Promise.reject(err);
|
|
||||||
};
|
|
||||||
|
|
||||||
return alertText(globalize.translate('ErrorDeletingItem')).then(result, result);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
deleteItem: deleteItem
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -141,7 +141,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||||
animateDialogOpen(dlg);
|
animateDialogOpen(dlg);
|
||||||
|
|
||||||
if (isHistoryEnabled(dlg)) {
|
if (isHistoryEnabled(dlg)) {
|
||||||
appRouter.pushState({ dialogId: hash }, "Dialog", '#' + hash);
|
appRouter.pushState({ dialogId: hash }, 'Dialog', '#' + hash);
|
||||||
|
|
||||||
window.addEventListener('popstate', onHashChange);
|
window.addEventListener('popstate', onHashChange);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -126,25 +126,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (min-width: 80em) and (min-height: 45em) {
|
@media all and (min-width: 80em) and (min-height: 45em) {
|
||||||
.dialog-medium {
|
|
||||||
width: 80%;
|
|
||||||
height: 80%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-medium-tall {
|
|
||||||
width: 80%;
|
|
||||||
height: 90%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-small {
|
.dialog-small {
|
||||||
width: 60%;
|
width: 60%;
|
||||||
height: 80%;
|
height: 80%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-fullscreen-border {
|
|
||||||
width: 90%;
|
|
||||||
height: 90%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.noScroll {
|
.noScroll {
|
||||||
|
|
|
@ -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';
|
'use strict';
|
||||||
|
|
||||||
function getSystemInfo() {
|
function getSystemInfo() {
|
||||||
|
@ -16,14 +16,14 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
|
||||||
|
|
||||||
function refreshDirectoryBrowser(page, path, fileOptions, updatePathOnError) {
|
function refreshDirectoryBrowser(page, path, fileOptions, updatePathOnError) {
|
||||||
if (path && typeof path !== 'string') {
|
if (path && typeof path !== 'string') {
|
||||||
throw new Error("invalid path");
|
throw new Error('invalid path');
|
||||||
}
|
}
|
||||||
|
|
||||||
loading.show();
|
loading.show();
|
||||||
|
|
||||||
var promises = [];
|
var promises = [];
|
||||||
|
|
||||||
if ("Network" === path) {
|
if ('Network' === path) {
|
||||||
promises.push(ApiClient.getNetworkDevices());
|
promises.push(ApiClient.getNetworkDevices());
|
||||||
} else {
|
} else {
|
||||||
if (path) {
|
if (path) {
|
||||||
|
@ -37,31 +37,31 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
|
||||||
Promise.all(promises).then(
|
Promise.all(promises).then(
|
||||||
function(responses) {
|
function(responses) {
|
||||||
var folders = responses[0];
|
var folders = responses[0];
|
||||||
var parentPath = responses[1] || "";
|
var parentPath = responses[1] || '';
|
||||||
var html = "";
|
var html = '';
|
||||||
|
|
||||||
page.querySelector(".results").scrollTop = 0;
|
page.querySelector('.results').scrollTop = 0;
|
||||||
page.querySelector("#txtDirectoryPickerPath").value = path || "";
|
page.querySelector('#txtDirectoryPickerPath').value = path || '';
|
||||||
|
|
||||||
if (path) {
|
if (path) {
|
||||||
html += getItem("lnkPath lnkDirectory", "", parentPath, "...");
|
html += getItem('lnkPath lnkDirectory', '', parentPath, '...');
|
||||||
}
|
}
|
||||||
for (var i = 0, length = folders.length; i < length; i++) {
|
for (var i = 0, length = folders.length; i < length; i++) {
|
||||||
var folder = folders[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);
|
html += getItem(cssClass, folder.Type, folder.Path, folder.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!path) {
|
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();
|
loading.hide();
|
||||||
}, function() {
|
}, function() {
|
||||||
if (updatePathOnError) {
|
if (updatePathOnError) {
|
||||||
page.querySelector("#txtDirectoryPickerPath").value = "";
|
page.querySelector('#txtDirectoryPickerPath').value = '';
|
||||||
page.querySelector(".results").innerHTML = "";
|
page.querySelector('.results').innerHTML = '';
|
||||||
loading.hide();
|
loading.hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,74 +69,73 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
|
||||||
}
|
}
|
||||||
|
|
||||||
function getItem(cssClass, type, path, name) {
|
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="listItem listItem-border ' + cssClass + '" data-type="' + type + '" data-path="' + path + '">';
|
||||||
html += '<div class="listItemBody" style="padding-left:0;padding-top:.5em;padding-bottom:.5em;">';
|
html += '<div class="listItemBody" style="padding-left:0;padding-top:.5em;padding-bottom:.5em;">';
|
||||||
html += '<div class="listItemBodyText">';
|
html += '<div class="listItemBodyText">';
|
||||||
html += name;
|
html += name;
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
html += '<i class="material-icons arrow_forward" style="font-size:inherit;"></i>';
|
html += '<span class="material-icons arrow_forward" style="font-size:inherit;"></span>';
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getEditorHtml(options, systemInfo) {
|
function getEditorHtml(options, systemInfo) {
|
||||||
var html = "";
|
var html = '';
|
||||||
html += '<div class="formDialogContent scrollY">';
|
html += '<div class="formDialogContent scrollY">';
|
||||||
html += '<div class="dialogContentInner dialog-content-centered" style="padding-top:2em;">';
|
html += '<div class="dialogContentInner dialog-content-centered" style="padding-top:2em;">';
|
||||||
if (!options.pathReadOnly) {
|
if (!options.pathReadOnly) {
|
||||||
var instruction = options.instruction ? options.instruction + "<br/><br/>" : "";
|
var instruction = options.instruction ? options.instruction + '<br/><br/>' : '';
|
||||||
html += '<div class="infoBanner" style="margin-bottom:1.5em;">';
|
html += '<div class="infoBanner" style="margin-bottom:1.5em;">';
|
||||||
html += instruction;
|
html += instruction;
|
||||||
html += Globalize.translate("MessageDirectoryPickerInstruction", "<b>\\\\server</b>", "<b>\\\\192.168.1.101</b>");
|
if ('bsd' === systemInfo.OperatingSystem.toLowerCase()) {
|
||||||
if ("bsd" === systemInfo.OperatingSystem.toLowerCase()) {
|
html += '<br/>';
|
||||||
html += "<br/>";
|
html += '<br/>';
|
||||||
html += "<br/>";
|
html += globalize.translate('MessageDirectoryPickerBSDInstruction');
|
||||||
html += Globalize.translate("MessageDirectoryPickerBSDInstruction");
|
html += '<br/>';
|
||||||
html += "<br/>";
|
} else if ('linux' === systemInfo.OperatingSystem.toLowerCase()) {
|
||||||
} else if ("linux" === systemInfo.OperatingSystem.toLowerCase()) {
|
html += '<br/>';
|
||||||
html += "<br/>";
|
html += '<br/>';
|
||||||
html += "<br/>";
|
html += globalize.translate('MessageDirectoryPickerLinuxInstruction');
|
||||||
html += Globalize.translate("MessageDirectoryPickerLinuxInstruction");
|
html += '<br/>';
|
||||||
html += "<br/>";
|
|
||||||
}
|
}
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
}
|
}
|
||||||
html += '<form style="margin:auto;">';
|
html += '<form style="margin:auto;">';
|
||||||
html += '<div class="inputContainer" style="display: flex; align-items: center;">';
|
html += '<div class="inputContainer" style="display: flex; align-items: center;">';
|
||||||
html += '<div style="flex-grow:1;">';
|
html += '<div style="flex-grow:1;">';
|
||||||
var labelKey;
|
var labelKey;
|
||||||
if (options.includeFiles !== true) {
|
if (options.includeFiles !== true) {
|
||||||
labelKey = "LabelFolder";
|
labelKey = 'LabelFolder';
|
||||||
} else {
|
} else {
|
||||||
labelKey = "LabelPath";
|
labelKey = 'LabelPath';
|
||||||
}
|
}
|
||||||
var readOnlyAttribute = options.pathReadOnly ? " readonly" : "";
|
var readOnlyAttribute = options.pathReadOnly ? ' readonly' : '';
|
||||||
html += '<input is="emby-input" id="txtDirectoryPickerPath" type="text" required="required" ' + readOnlyAttribute + ' label="' + Globalize.translate(labelKey) + '"/>';
|
html += '<input is="emby-input" id="txtDirectoryPickerPath" type="text" required="required" ' + readOnlyAttribute + ' label="' + globalize.translate(labelKey) + '"/>';
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
if (!readOnlyAttribute) {
|
if (!readOnlyAttribute) {
|
||||||
html += '<button type="button" is="paper-icon-button-light" class="btnRefreshDirectories emby-input-iconbutton" title="' + Globalize.translate("ButtonRefresh") + '"><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) {
|
if (!readOnlyAttribute) {
|
||||||
html += '<div class="results paperList" style="max-height: 200px; overflow-y: auto;"></div>';
|
html += '<div class="results paperList" style="max-height: 200px; overflow-y: auto;"></div>';
|
||||||
}
|
}
|
||||||
if (options.enableNetworkSharePath) {
|
if (options.enableNetworkSharePath) {
|
||||||
html += '<div class="inputContainer" style="margin-top:2em;">';
|
html += '<div class="inputContainer" style="margin-top:2em;">';
|
||||||
html += '<input is="emby-input" id="txtNetworkPath" type="text" label="' + Globalize.translate("LabelOptionalNetworkPath") + '"/>';
|
html += '<input is="emby-input" id="txtNetworkPath" type="text" label="' + globalize.translate('LabelOptionalNetworkPath') + '"/>';
|
||||||
html += '<div class="fieldDescription">';
|
html += '<div class="fieldDescription">';
|
||||||
html += Globalize.translate("LabelOptionalNetworkPathHelp");
|
html += globalize.translate('LabelOptionalNetworkPathHelp', '<b>\\\\server</b>', '<b>\\\\192.168.1.101</b>');
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
}
|
}
|
||||||
html += '<div class="formDialogFooter">';
|
html += '<div class="formDialogFooter">';
|
||||||
html += '<button is="emby-button" type="submit" class="raised button-submit block formDialogFooterItem">' + Globalize.translate("ButtonOk") + "</button>";
|
html += '<button is="emby-button" type="submit" class="raised button-submit block formDialogFooterItem">' + globalize.translate('ButtonOk') + '</button>';
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
html += "</form>";
|
html += '</form>';
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
|
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
@ -148,15 +147,15 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
|
||||||
}
|
}
|
||||||
|
|
||||||
function alertTextWithOptions(options) {
|
function alertTextWithOptions(options) {
|
||||||
require(["alert"], function(alert) {
|
require(['alert'], function(alert) {
|
||||||
alert(options);
|
alert(options);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function validatePath(path, validateWriteable, apiClient) {
|
function validatePath(path, validateWriteable, apiClient) {
|
||||||
return apiClient.ajax({
|
return apiClient.ajax({
|
||||||
type: "POST",
|
type: 'POST',
|
||||||
url: apiClient.getUrl("Environment/ValidatePath"),
|
url: apiClient.getUrl('Environment/ValidatePath'),
|
||||||
data: {
|
data: {
|
||||||
ValidateWriteable: validateWriteable,
|
ValidateWriteable: validateWriteable,
|
||||||
Path: path
|
Path: path
|
||||||
|
@ -164,14 +163,14 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
|
||||||
}).catch(function(response) {
|
}).catch(function(response) {
|
||||||
if (response) {
|
if (response) {
|
||||||
if (response.status === 404) {
|
if (response.status === 404) {
|
||||||
alertText(Globalize.translate("PathNotFound"));
|
alertText(globalize.translate('PathNotFound'));
|
||||||
return Promise.reject();
|
return Promise.reject();
|
||||||
}
|
}
|
||||||
if (response.status === 500) {
|
if (response.status === 500) {
|
||||||
if (validateWriteable) {
|
if (validateWriteable) {
|
||||||
alertText(Globalize.translate("WriteAccessRequired"));
|
alertText(globalize.translate('WriteAccessRequired'));
|
||||||
} else {
|
} else {
|
||||||
alertText(Globalize.translate("PathNotFound"));
|
alertText(globalize.translate('PathNotFound'));
|
||||||
}
|
}
|
||||||
return Promise.reject();
|
return Promise.reject();
|
||||||
}
|
}
|
||||||
|
@ -181,37 +180,37 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
|
||||||
}
|
}
|
||||||
|
|
||||||
function initEditor(content, options, fileOptions) {
|
function initEditor(content, options, fileOptions) {
|
||||||
content.addEventListener("click", function(e) {
|
content.addEventListener('click', function(e) {
|
||||||
var lnkPath = dom.parentWithClass(e.target, "lnkPath");
|
var lnkPath = dom.parentWithClass(e.target, 'lnkPath');
|
||||||
if (lnkPath) {
|
if (lnkPath) {
|
||||||
var path = lnkPath.getAttribute("data-path");
|
var path = lnkPath.getAttribute('data-path');
|
||||||
if (lnkPath.classList.contains("lnkFile")) {
|
if (lnkPath.classList.contains('lnkFile')) {
|
||||||
content.querySelector("#txtDirectoryPickerPath").value = path;
|
content.querySelector('#txtDirectoryPickerPath').value = path;
|
||||||
} else {
|
} else {
|
||||||
refreshDirectoryBrowser(content, path, fileOptions, true);
|
refreshDirectoryBrowser(content, path, fileOptions, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
content.addEventListener("click", function(e) {
|
content.addEventListener('click', function(e) {
|
||||||
if (dom.parentWithClass(e.target, "btnRefreshDirectories")) {
|
if (dom.parentWithClass(e.target, 'btnRefreshDirectories')) {
|
||||||
var path = content.querySelector("#txtDirectoryPickerPath").value;
|
var path = content.querySelector('#txtDirectoryPickerPath').value;
|
||||||
refreshDirectoryBrowser(content, path, fileOptions);
|
refreshDirectoryBrowser(content, path, fileOptions);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
content.addEventListener("change", function(e) {
|
content.addEventListener('change', function(e) {
|
||||||
var txtDirectoryPickerPath = dom.parentWithTag(e.target, "INPUT");
|
var txtDirectoryPickerPath = dom.parentWithTag(e.target, 'INPUT');
|
||||||
if (txtDirectoryPickerPath && "txtDirectoryPickerPath" === txtDirectoryPickerPath.id) {
|
if (txtDirectoryPickerPath && 'txtDirectoryPickerPath' === txtDirectoryPickerPath.id) {
|
||||||
refreshDirectoryBrowser(content, txtDirectoryPickerPath.value, fileOptions);
|
refreshDirectoryBrowser(content, txtDirectoryPickerPath.value, fileOptions);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
content.querySelector("form").addEventListener("submit", function(e) {
|
content.querySelector('form').addEventListener('submit', function(e) {
|
||||||
if (options.callback) {
|
if (options.callback) {
|
||||||
var networkSharePath = this.querySelector("#txtNetworkPath");
|
var networkSharePath = this.querySelector('#txtNetworkPath');
|
||||||
networkSharePath = networkSharePath ? networkSharePath.value : null;
|
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));
|
validatePath(path, options.validateWriteable, ApiClient).then(options.callback(path, networkSharePath));
|
||||||
}
|
}
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -224,11 +223,11 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
|
||||||
if (options.path) {
|
if (options.path) {
|
||||||
return Promise.resolve(options.path);
|
return Promise.resolve(options.path);
|
||||||
} else {
|
} else {
|
||||||
return ApiClient.getJSON(ApiClient.getUrl("Environment/DefaultDirectoryBrowser")).then(
|
return ApiClient.getJSON(ApiClient.getUrl('Environment/DefaultDirectoryBrowser')).then(
|
||||||
function(result) {
|
function(result) {
|
||||||
return result.Path || "";
|
return result.Path || '';
|
||||||
}, function() {
|
}, function() {
|
||||||
return "";
|
return '';
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -253,35 +252,35 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
|
||||||
var systemInfo = responses[0];
|
var systemInfo = responses[0];
|
||||||
var initialPath = responses[1];
|
var initialPath = responses[1];
|
||||||
var dlg = dialogHelper.createDialog({
|
var dlg = dialogHelper.createDialog({
|
||||||
size: "medium-tall",
|
size: 'small',
|
||||||
removeOnClose: true,
|
removeOnClose: true,
|
||||||
scrollY: false
|
scrollY: false
|
||||||
});
|
});
|
||||||
dlg.classList.add("ui-body-a");
|
dlg.classList.add('ui-body-a');
|
||||||
dlg.classList.add("background-theme-a");
|
dlg.classList.add('background-theme-a');
|
||||||
dlg.classList.add("directoryPicker");
|
dlg.classList.add('directoryPicker');
|
||||||
dlg.classList.add("formDialog");
|
dlg.classList.add('formDialog');
|
||||||
|
|
||||||
var html = "";
|
var html = '';
|
||||||
html += '<div class="formDialogHeader">';
|
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 += '<h3 class="formDialogHeaderTitle">';
|
||||||
html += options.header || Globalize.translate("HeaderSelectPath");
|
html += options.header || globalize.translate('HeaderSelectPath');
|
||||||
html += "</h3>";
|
html += '</h3>';
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
html += getEditorHtml(options, systemInfo);
|
html += getEditorHtml(options, systemInfo);
|
||||||
dlg.innerHTML = html;
|
dlg.innerHTML = html;
|
||||||
initEditor(dlg, options, fileOptions);
|
initEditor(dlg, options, fileOptions);
|
||||||
dlg.addEventListener("close", onDialogClosed);
|
dlg.addEventListener('close', onDialogClosed);
|
||||||
dialogHelper.open(dlg);
|
dialogHelper.open(dlg);
|
||||||
dlg.querySelector(".btnCloseDialog").addEventListener("click", function() {
|
dlg.querySelector('.btnCloseDialog').addEventListener('click', function() {
|
||||||
dialogHelper.close(dlg);
|
dialogHelper.close(dlg);
|
||||||
});
|
});
|
||||||
currentDialog = dlg;
|
currentDialog = dlg;
|
||||||
dlg.querySelector("#txtDirectoryPickerPath").value = initialPath;
|
dlg.querySelector('#txtDirectoryPickerPath').value = initialPath;
|
||||||
var txtNetworkPath = dlg.querySelector("#txtNetworkPath");
|
var txtNetworkPath = dlg.querySelector('#txtNetworkPath');
|
||||||
if (txtNetworkPath) {
|
if (txtNetworkPath) {
|
||||||
txtNetworkPath.value = options.networkSharePath || "";
|
txtNetworkPath.value = options.networkSharePath || '';
|
||||||
}
|
}
|
||||||
if (!options.pathReadOnly) {
|
if (!options.pathReadOnly) {
|
||||||
refreshDirectoryBrowser(dlg, initialPath, fileOptions, true);
|
refreshDirectoryBrowser(dlg, initialPath, fileOptions, true);
|
||||||
|
|
|
@ -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) {
|
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) {
|
function fillThemes(select, isDashboard) {
|
||||||
select.innerHTML = skinManager.getThemes().map(function (t) {
|
select.innerHTML = skinManager.getThemes().map(function (t) {
|
||||||
|
@ -181,11 +181,15 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
|
||||||
context.querySelector('#chkThemeSong').checked = userSettings.enableThemeSongs();
|
context.querySelector('#chkThemeSong').checked = userSettings.enableThemeSongs();
|
||||||
context.querySelector('#chkThemeVideo').checked = userSettings.enableThemeVideos();
|
context.querySelector('#chkThemeVideo').checked = userSettings.enableThemeVideos();
|
||||||
context.querySelector('#chkFadein').checked = userSettings.enableFastFadein();
|
context.querySelector('#chkFadein').checked = userSettings.enableFastFadein();
|
||||||
|
context.querySelector('#chkBlurhash').checked = userSettings.enableBlurhash();
|
||||||
context.querySelector('#chkBackdrops').checked = userSettings.enableBackdrops();
|
context.querySelector('#chkBackdrops').checked = userSettings.enableBackdrops();
|
||||||
|
context.querySelector('#chkDetailsBanner').checked = userSettings.detailsBanner();
|
||||||
|
|
||||||
context.querySelector('#selectLanguage').value = userSettings.language() || '';
|
context.querySelector('#selectLanguage').value = userSettings.language() || '';
|
||||||
context.querySelector('.selectDateTimeLocale').value = userSettings.dateTimeLocale() || '';
|
context.querySelector('.selectDateTimeLocale').value = userSettings.dateTimeLocale() || '';
|
||||||
|
|
||||||
|
context.querySelector('#txtLibraryPageSize').value = userSettings.libraryPageSize();
|
||||||
|
|
||||||
selectDashboardTheme.value = userSettings.dashboardTheme() || '';
|
selectDashboardTheme.value = userSettings.dashboardTheme() || '';
|
||||||
selectTheme.value = userSettings.theme() || '';
|
selectTheme.value = userSettings.theme() || '';
|
||||||
|
|
||||||
|
@ -215,10 +219,14 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
|
||||||
userSettingsInstance.soundEffects(context.querySelector('.selectSoundEffects').value);
|
userSettingsInstance.soundEffects(context.querySelector('.selectSoundEffects').value);
|
||||||
userSettingsInstance.screensaver(context.querySelector('.selectScreensaver').value);
|
userSettingsInstance.screensaver(context.querySelector('.selectScreensaver').value);
|
||||||
|
|
||||||
|
userSettingsInstance.libraryPageSize(context.querySelector('#txtLibraryPageSize').value);
|
||||||
|
|
||||||
userSettingsInstance.skin(context.querySelector('.selectSkin').value);
|
userSettingsInstance.skin(context.querySelector('.selectSkin').value);
|
||||||
|
|
||||||
userSettingsInstance.enableFastFadein(context.querySelector('#chkFadein').checked);
|
userSettingsInstance.enableFastFadein(context.querySelector('#chkFadein').checked);
|
||||||
|
userSettingsInstance.enableBlurhash(context.querySelector('#chkBlurhash').checked);
|
||||||
userSettingsInstance.enableBackdrops(context.querySelector('#chkBackdrops').checked);
|
userSettingsInstance.enableBackdrops(context.querySelector('#chkBackdrops').checked);
|
||||||
|
userSettingsInstance.detailsBanner(context.querySelector('#chkDetailsBanner').checked);
|
||||||
|
|
||||||
if (user.Id === apiClient.getCurrentUserId()) {
|
if (user.Id === apiClient.getCurrentUserId()) {
|
||||||
skinManager.setTheme(userSettingsInstance.theme());
|
skinManager.setTheme(userSettingsInstance.theme());
|
||||||
|
@ -265,7 +273,7 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
|
||||||
}
|
}
|
||||||
|
|
||||||
function embed(options, self) {
|
function embed(options, self) {
|
||||||
require(['text!./displaysettings.template.html'], function (template) {
|
require(['text!./displaySettings.template.html'], function (template) {
|
||||||
options.element.innerHTML = globalize.translateDocument(template, 'core');
|
options.element.innerHTML = globalize.translateDocument(template, 'core');
|
||||||
options.element.querySelector('form').addEventListener('submit', onSubmit.bind(self));
|
options.element.querySelector('form').addEventListener('submit', onSubmit.bind(self));
|
||||||
if (options.enableSaveButton) {
|
if (options.enableSaveButton) {
|
|
@ -56,7 +56,7 @@
|
||||||
<div class="fieldDescription">
|
<div class="fieldDescription">
|
||||||
<div>${LabelDisplayLanguageHelp}</div>
|
<div>${LabelDisplayLanguageHelp}</div>
|
||||||
<div class="learnHowToContributeContainer hide" style="margin-top: .25em;">
|
<div class="learnHowToContributeContainer hide" style="margin-top: .25em;">
|
||||||
<a is="emby-linkbutton" class="button-link" href="https://github.com/jellyfin/jellyfin" target="_blank">${LearnHowYouCanContribute}</a>
|
<a is="emby-linkbutton" rel="noopener noreferrer" class="button-link" href="https://github.com/jellyfin/jellyfin" target="_blank">${LearnHowYouCanContribute}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -143,12 +143,33 @@
|
||||||
<select is="emby-select" class="selectSoundEffects" label="${LabelSoundEffects}"></select>
|
<select is="emby-select" class="selectSoundEffects" label="${LabelSoundEffects}"></select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription fldFadein">
|
<div class="inputContainer inputContainer-withDescription">
|
||||||
|
<input is="emby-input" type="number" id="txtLibraryPageSize" pattern="[0-9]*" required="required" min="0" max="1000" step="1" label="${LabelLibraryPageSize}" />
|
||||||
|
<div class="fieldDescription">${LabelLibraryPageSizeHelp}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="checkboxContainer checkboxContainer-withDescription">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" is="emby-checkbox" id="chkFadein" />
|
<input type="checkbox" is="emby-checkbox" id="chkFadein" />
|
||||||
<span>${EnableFastImageFadeIn}</span>
|
<span>${EnableFasterAnimations}</span>
|
||||||
</label>
|
</label>
|
||||||
<div class="fieldDescription checkboxFieldDescription">${EnableFastImageFadeInHelp}</div>
|
<div class="fieldDescription checkboxFieldDescription">${EnableFasterAnimationsHelp}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="checkboxContainer checkboxContainer-withDescription">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" is="emby-checkbox" id="chkBlurhash" />
|
||||||
|
<span>${EnableBlurhash}</span>
|
||||||
|
</label>
|
||||||
|
<div class="fieldDescription checkboxFieldDescription">${EnableBlurhashHelp}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="checkboxContainer checkboxContainer-withDescription">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" is="emby-checkbox" id="chkDetailsBanner" />
|
||||||
|
<span>${EnableDetailsBanner}</span>
|
||||||
|
</label>
|
||||||
|
<div class="fieldDescription checkboxFieldDescription">${EnableDetailsBannerHelp}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription fldBackdrops hide">
|
<div class="checkboxContainer checkboxContainer-withDescription fldBackdrops hide">
|
|
@ -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) {
|
define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoader', 'globalize', 'layoutManager', 'scrollStyles', 'emby-itemscontainer'], function (loading, libraryBrowser, cardBuilder, dom, appHost, imageLoader, globalize, layoutManager) {
|
||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
function enableScrollX() {
|
function enableScrollX() {
|
||||||
return !layoutManager.desktop;
|
return !layoutManager.desktop;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getThumbShape() {
|
function getThumbShape() {
|
||||||
return enableScrollX() ? "overflowBackdrop" : "backdrop";
|
return enableScrollX() ? 'overflowBackdrop' : 'backdrop';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPosterShape() {
|
function getPosterShape() {
|
||||||
return enableScrollX() ? "overflowPortrait" : "portrait";
|
return enableScrollX() ? 'overflowPortrait' : 'portrait';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSquareShape() {
|
function getSquareShape() {
|
||||||
return enableScrollX() ? "overflowSquare" : "square";
|
return enableScrollX() ? 'overflowSquare' : 'square';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSections() {
|
function getSections() {
|
||||||
return [{
|
return [{
|
||||||
name: "HeaderFavoriteMovies",
|
name: 'HeaderFavoriteMovies',
|
||||||
types: "Movie",
|
types: 'Movie',
|
||||||
id: "favoriteMovies",
|
id: 'favoriteMovies',
|
||||||
shape: getPosterShape(),
|
shape: getPosterShape(),
|
||||||
showTitle: false,
|
showTitle: false,
|
||||||
overlayPlayButton: true
|
overlayPlayButton: true
|
||||||
}, {
|
}, {
|
||||||
name: "HeaderFavoriteShows",
|
name: 'HeaderFavoriteShows',
|
||||||
types: "Series",
|
types: 'Series',
|
||||||
id: "favoriteShows",
|
id: 'favoriteShows',
|
||||||
shape: getPosterShape(),
|
shape: getPosterShape(),
|
||||||
showTitle: false,
|
showTitle: false,
|
||||||
overlayPlayButton: true
|
overlayPlayButton: true
|
||||||
}, {
|
}, {
|
||||||
name: "HeaderFavoriteEpisodes",
|
name: 'HeaderFavoriteEpisodes',
|
||||||
types: "Episode",
|
types: 'Episode',
|
||||||
id: "favoriteEpisode",
|
id: 'favoriteEpisode',
|
||||||
shape: getThumbShape(),
|
shape: getThumbShape(),
|
||||||
preferThumb: false,
|
preferThumb: false,
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
|
@ -44,9 +44,9 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
||||||
overlayText: false,
|
overlayText: false,
|
||||||
centerText: true
|
centerText: true
|
||||||
}, {
|
}, {
|
||||||
name: "HeaderFavoriteVideos",
|
name: 'HeaderFavoriteVideos',
|
||||||
types: "Video,MusicVideo",
|
types: 'Video,MusicVideo',
|
||||||
id: "favoriteVideos",
|
id: 'favoriteVideos',
|
||||||
shape: getThumbShape(),
|
shape: getThumbShape(),
|
||||||
preferThumb: true,
|
preferThumb: true,
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
|
@ -54,9 +54,9 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
||||||
overlayText: false,
|
overlayText: false,
|
||||||
centerText: true
|
centerText: true
|
||||||
}, {
|
}, {
|
||||||
name: "HeaderFavoriteArtists",
|
name: 'HeaderFavoriteArtists',
|
||||||
types: "MusicArtist",
|
types: 'MusicArtist',
|
||||||
id: "favoriteArtists",
|
id: 'favoriteArtists',
|
||||||
shape: getSquareShape(),
|
shape: getSquareShape(),
|
||||||
preferThumb: false,
|
preferThumb: false,
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
|
@ -66,9 +66,9 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
||||||
overlayPlayButton: true,
|
overlayPlayButton: true,
|
||||||
coverImage: true
|
coverImage: true
|
||||||
}, {
|
}, {
|
||||||
name: "HeaderFavoriteAlbums",
|
name: 'HeaderFavoriteAlbums',
|
||||||
types: "MusicAlbum",
|
types: 'MusicAlbum',
|
||||||
id: "favoriteAlbums",
|
id: 'favoriteAlbums',
|
||||||
shape: getSquareShape(),
|
shape: getSquareShape(),
|
||||||
preferThumb: false,
|
preferThumb: false,
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
|
@ -78,9 +78,9 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
||||||
overlayPlayButton: true,
|
overlayPlayButton: true,
|
||||||
coverImage: true
|
coverImage: true
|
||||||
}, {
|
}, {
|
||||||
name: "HeaderFavoriteSongs",
|
name: 'HeaderFavoriteSongs',
|
||||||
types: "Audio",
|
types: 'Audio',
|
||||||
id: "favoriteSongs",
|
id: 'favoriteSongs',
|
||||||
shape: getSquareShape(),
|
shape: getSquareShape(),
|
||||||
preferThumb: false,
|
preferThumb: false,
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
|
@ -88,7 +88,7 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
||||||
showParentTitle: true,
|
showParentTitle: true,
|
||||||
centerText: true,
|
centerText: true,
|
||||||
overlayMoreButton: true,
|
overlayMoreButton: true,
|
||||||
action: "instantmix",
|
action: 'instantmix',
|
||||||
coverImage: true
|
coverImage: true
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
@ -96,13 +96,13 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
||||||
function loadSection(elem, userId, topParentId, section, isSingleSection) {
|
function loadSection(elem, userId, topParentId, section, isSingleSection) {
|
||||||
var screenWidth = dom.getWindowSize().innerWidth;
|
var screenWidth = dom.getWindowSize().innerWidth;
|
||||||
var options = {
|
var options = {
|
||||||
SortBy: "SortName",
|
SortBy: 'SortName',
|
||||||
SortOrder: "Ascending",
|
SortOrder: 'Ascending',
|
||||||
Filters: "IsFavorite",
|
Filters: 'IsFavorite',
|
||||||
Recursive: true,
|
Recursive: true,
|
||||||
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
|
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
|
||||||
CollapseBoxSetItems: false,
|
CollapseBoxSetItems: false,
|
||||||
ExcludeLocationTypes: "Virtual",
|
ExcludeLocationTypes: 'Virtual',
|
||||||
EnableTotalRecordCount: false
|
EnableTotalRecordCount: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
||||||
|
|
||||||
var promise;
|
var promise;
|
||||||
|
|
||||||
if ("MusicArtist" === section.types) {
|
if ('MusicArtist' === section.types) {
|
||||||
promise = ApiClient.getArtists(userId, options);
|
promise = ApiClient.getArtists(userId, options);
|
||||||
} else {
|
} else {
|
||||||
options.IncludeItemTypes = section.types;
|
options.IncludeItemTypes = section.types;
|
||||||
|
@ -128,25 +128,25 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
||||||
}
|
}
|
||||||
|
|
||||||
return promise.then(function (result) {
|
return promise.then(function (result) {
|
||||||
var html = "";
|
var html = '';
|
||||||
|
|
||||||
if (result.Items.length) {
|
if (result.Items.length) {
|
||||||
if (html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">', !layoutManager.tv && options.Limit && result.Items.length >= options.Limit) {
|
if (html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">', !layoutManager.tv && options.Limit && result.Items.length >= options.Limit) {
|
||||||
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 += '<h2 class="sectionTitle sectionTitle-cards">';
|
||||||
html += globalize.translate(section.name);
|
html += globalize.translate(section.name);
|
||||||
html += "</h2>";
|
html += '</h2>';
|
||||||
html += '<i class="material-icons chevron_right"></i>';
|
html += '<span class="material-icons chevron_right"></span>';
|
||||||
html += "</a>";
|
html += '</a>';
|
||||||
} else {
|
} 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()) {
|
if (enableScrollX()) {
|
||||||
var scrollXClass = "scrollX hiddenScrollX";
|
var scrollXClass = 'scrollX hiddenScrollX';
|
||||||
if (layoutManager.tv) {
|
if (layoutManager.tv) {
|
||||||
scrollXClass += " smoothScrollX";
|
scrollXClass += ' smoothScrollX';
|
||||||
}
|
}
|
||||||
|
|
||||||
html += '<div is="emby-itemscontainer" class="itemsContainer ' + scrollXClass + ' padded-left padded-right">';
|
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">';
|
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;
|
var cardLayout = (appHost.preferVisualCards || supportsImageAnalysis) && section.autoCardLayout && section.showTitle;
|
||||||
cardLayout = false;
|
cardLayout = false;
|
||||||
html += cardBuilder.getCardsHtml(result.Items, {
|
html += cardBuilder.getCardsHtml(result.Items, {
|
||||||
|
@ -172,7 +172,7 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
||||||
allowBottomPadding: !enableScrollX(),
|
allowBottomPadding: !enableScrollX(),
|
||||||
cardLayout: cardLayout
|
cardLayout: cardLayout
|
||||||
});
|
});
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
elem.innerHTML = html;
|
elem.innerHTML = html;
|
||||||
|
@ -183,7 +183,7 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
||||||
function loadSections(page, userId, topParentId, types) {
|
function loadSections(page, userId, topParentId, types) {
|
||||||
loading.show();
|
loading.show();
|
||||||
var sections = getSections();
|
var sections = getSections();
|
||||||
var sectionid = getParameterByName("sectionid");
|
var sectionid = getParameterByName('sectionid');
|
||||||
|
|
||||||
if (sectionid) {
|
if (sectionid) {
|
||||||
sections = sections.filter(function (s) {
|
sections = sections.filter(function (s) {
|
||||||
|
@ -199,10 +199,10 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
||||||
|
|
||||||
var i;
|
var i;
|
||||||
var length;
|
var length;
|
||||||
var elem = page.querySelector(".favoriteSections");
|
var elem = page.querySelector('.favoriteSections');
|
||||||
|
|
||||||
if (!elem.innerHTML) {
|
if (!elem.innerHTML) {
|
||||||
var html = "";
|
var html = '';
|
||||||
|
|
||||||
for (i = 0, length = sections.length; i < length; i++) {
|
for (i = 0, length = sections.length; i < length; i++) {
|
||||||
html += '<div class="verticalSection section' + sections[i].id + '"></div>';
|
html += '<div class="verticalSection section' + sections[i].id + '"></div>';
|
||||||
|
@ -215,7 +215,7 @@ define(["loading", "libraryBrowser", "cardBuilder", "dom", "apphost", "imageLoad
|
||||||
|
|
||||||
for (i = 0, length = sections.length; i < length; i++) {
|
for (i = 0, length = sections.length; i < length; i++) {
|
||||||
var section = sections[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));
|
promises.push(loadSection(elem, userId, topParentId, section, 1 === sections.length));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,19 @@
|
||||||
define([], function () {
|
/* eslint-disable indent */
|
||||||
'use strict';
|
export function getFetchPromise(request) {
|
||||||
|
|
||||||
function getFetchPromise(request) {
|
const headers = request.headers || {};
|
||||||
|
|
||||||
var headers = request.headers || {};
|
|
||||||
|
|
||||||
if (request.dataType === 'json') {
|
if (request.dataType === 'json') {
|
||||||
headers.accept = 'application/json';
|
headers.accept = 'application/json';
|
||||||
}
|
}
|
||||||
|
|
||||||
var fetchRequest = {
|
const fetchRequest = {
|
||||||
headers: headers,
|
headers: headers,
|
||||||
method: request.type,
|
method: request.type,
|
||||||
credentials: 'same-origin'
|
credentials: 'same-origin'
|
||||||
};
|
};
|
||||||
|
|
||||||
var contentType = request.contentType;
|
let contentType = request.contentType;
|
||||||
|
|
||||||
if (request.data) {
|
if (request.data) {
|
||||||
|
|
||||||
|
@ -33,12 +31,12 @@ define([], function () {
|
||||||
headers['Content-Type'] = contentType;
|
headers['Content-Type'] = contentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = request.url;
|
let url = request.url;
|
||||||
|
|
||||||
if (request.query) {
|
if (request.query) {
|
||||||
var paramString = paramsToString(request.query);
|
const paramString = paramsToString(request.query);
|
||||||
if (paramString) {
|
if (paramString) {
|
||||||
url += '?' + paramString;
|
url += `?${paramString}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,11 +49,11 @@ define([], function () {
|
||||||
|
|
||||||
function fetchWithTimeout(url, options, timeoutMs) {
|
function fetchWithTimeout(url, options, timeoutMs) {
|
||||||
|
|
||||||
console.debug('fetchWithTimeout: timeoutMs: ' + timeoutMs + ', url: ' + url);
|
console.debug(`fetchWithTimeout: timeoutMs: ${timeoutMs}, url: ${url}`);
|
||||||
|
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
|
|
||||||
var timeout = setTimeout(reject, timeoutMs);
|
const timeout = setTimeout(reject, timeoutMs);
|
||||||
|
|
||||||
options = options || {};
|
options = options || {};
|
||||||
options.credentials = 'same-origin';
|
options.credentials = 'same-origin';
|
||||||
|
@ -63,50 +61,47 @@ define([], function () {
|
||||||
fetch(url, options).then(function (response) {
|
fetch(url, options).then(function (response) {
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
|
|
||||||
console.debug('fetchWithTimeout: succeeded connecting to url: ' + url);
|
console.debug(`fetchWithTimeout: succeeded connecting to url: ${url}`);
|
||||||
|
|
||||||
resolve(response);
|
resolve(response);
|
||||||
}, function (error) {
|
}, function (error) {
|
||||||
|
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
|
|
||||||
console.debug('fetchWithTimeout: timed out connecting to url: ' + url);
|
console.debug(`fetchWithTimeout: timed out connecting to url: ${url}`);
|
||||||
|
|
||||||
reject();
|
reject(error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param params {Record<string, string | number | boolean>}
|
||||||
|
* @returns {string} Query string
|
||||||
|
*/
|
||||||
function paramsToString(params) {
|
function paramsToString(params) {
|
||||||
|
return Object.entries(params)
|
||||||
var values = [];
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
.filter(([_, v]) => v !== null && v !== undefined && v !== '')
|
||||||
for (var key in params) {
|
.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
|
||||||
|
.join('&');
|
||||||
var value = params[key];
|
|
||||||
|
|
||||||
if (value !== null && value !== undefined && value !== '') {
|
|
||||||
values.push(encodeURIComponent(key) + "=" + encodeURIComponent(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return values.join('&');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function ajax(request) {
|
export function ajax(request) {
|
||||||
if (!request) {
|
if (!request) {
|
||||||
throw new Error("Request cannot be null");
|
throw new Error('Request cannot be null');
|
||||||
}
|
}
|
||||||
|
|
||||||
request.headers = request.headers || {};
|
request.headers = request.headers || {};
|
||||||
|
|
||||||
console.debug('requesting url: ' + request.url);
|
console.debug(`requesting url: ${request.url}`);
|
||||||
|
|
||||||
return getFetchPromise(request).then(function (response) {
|
return getFetchPromise(request).then(function (response) {
|
||||||
console.debug('response status: ' + response.status + ', url: ' + request.url);
|
console.debug(`response status: ${response.status}, url: ${request.url}`);
|
||||||
if (response.status < 400) {
|
if (response.status < 400) {
|
||||||
if (request.dataType === 'json' || request.headers.accept === 'application/json') {
|
if (request.dataType === 'json' || request.headers.accept === 'application/json') {
|
||||||
return response.json();
|
return response.json();
|
||||||
} else if (request.dataType === 'text' || (response.headers.get('Content-Type') || '').toLowerCase().indexOf('text/') === 0) {
|
} else if (request.dataType === 'text' || (response.headers.get('Content-Type') || '').toLowerCase().startsWith('text/')) {
|
||||||
return response.text();
|
return response.text();
|
||||||
} else {
|
} else {
|
||||||
return response;
|
return response;
|
||||||
|
@ -115,12 +110,8 @@ define([], function () {
|
||||||
return Promise.reject(response);
|
return Promise.reject(response);
|
||||||
}
|
}
|
||||||
}, function (err) {
|
}, function (err) {
|
||||||
console.error('request failed to url: ' + request.url);
|
console.error(`request failed to url: ${request.url}`);
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return {
|
/* eslint-enable indent */
|
||||||
getFetchPromise: getFetchPromise,
|
|
||||||
ajax: ajax
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,52 +1,59 @@
|
||||||
define(["dom", "dialogHelper", "globalize", "connectionManager", "events", "browser", "require", "emby-checkbox", "emby-collapse", "css!./style"], function (dom, dialogHelper, globalize, connectionManager, events, browser, require) {
|
import dom from 'dom';
|
||||||
"use strict";
|
import dialogHelper from 'dialogHelper';
|
||||||
|
import globalize from 'globalize';
|
||||||
|
import connectionManager from 'connectionManager';
|
||||||
|
import events from 'events';
|
||||||
|
import 'emby-checkbox';
|
||||||
|
import 'emby-collapse';
|
||||||
|
import 'css!./style.css';
|
||||||
|
|
||||||
|
/* eslint-disable indent */
|
||||||
function renderOptions(context, selector, cssClass, items, isCheckedFn) {
|
function renderOptions(context, selector, cssClass, items, isCheckedFn) {
|
||||||
var elem = context.querySelector(selector);
|
const elem = context.querySelector(selector);
|
||||||
if (items.length) {
|
if (items.length) {
|
||||||
elem.classList.remove("hide");
|
elem.classList.remove('hide');
|
||||||
} else {
|
} else {
|
||||||
elem.classList.add("hide");
|
elem.classList.add('hide');
|
||||||
}
|
}
|
||||||
var html = "";
|
let html = '';
|
||||||
html += '<div class="checkboxList">';
|
html += '<div class="checkboxList">';
|
||||||
html += items.map(function (filter) {
|
html += items.map(function (filter) {
|
||||||
var itemHtml = "";
|
let itemHtml = '';
|
||||||
var checkedHtml = isCheckedFn(filter) ? " checked" : "";
|
const checkedHtml = isCheckedFn(filter) ? 'checked' : '';
|
||||||
itemHtml += "<label>";
|
itemHtml += '<label>';
|
||||||
itemHtml += '<input is="emby-checkbox" type="checkbox"' + checkedHtml + ' data-filter="' + filter + '" class="' + cssClass + '"/>';
|
itemHtml += `<input is="emby-checkbox" type="checkbox" ${checkedHtml} data-filter="${filter}" class="${cssClass}"/>`;
|
||||||
itemHtml += "<span>" + filter + "</span>";
|
itemHtml += `<span>${filter}</span>`;
|
||||||
itemHtml += "</label>";
|
itemHtml += '</label>';
|
||||||
return itemHtml;
|
return itemHtml;
|
||||||
}).join("");
|
}).join('');
|
||||||
html += "</div>";
|
html += '</div>';
|
||||||
elem.querySelector(".filterOptions").innerHTML = html;
|
elem.querySelector('.filterOptions').innerHTML = html;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderFilters(context, result, query) {
|
function renderFilters(context, result, query) {
|
||||||
if (result.Tags) {
|
if (result.Tags) {
|
||||||
result.Tags.length = Math.min(result.Tags.length, 50);
|
result.Tags.length = Math.min(result.Tags.length, 50);
|
||||||
}
|
}
|
||||||
renderOptions(context, ".genreFilters", "chkGenreFilter", result.Genres, function (i) {
|
renderOptions(context, '.genreFilters', 'chkGenreFilter', result.Genres, function (i) {
|
||||||
var delimeter = "|";
|
const delimeter = '|';
|
||||||
return (delimeter + (query.Genres || "") + delimeter).indexOf(delimeter + i + delimeter) != -1;
|
return (delimeter + (query.Genres || '') + delimeter).includes(delimeter + i + delimeter);
|
||||||
});
|
});
|
||||||
renderOptions(context, ".officialRatingFilters", "chkOfficialRatingFilter", result.OfficialRatings, function (i) {
|
renderOptions(context, '.officialRatingFilters', 'chkOfficialRatingFilter', result.OfficialRatings, function (i) {
|
||||||
var delimeter = "|";
|
const delimeter = '|';
|
||||||
return (delimeter + (query.OfficialRatings || "") + delimeter).indexOf(delimeter + i + delimeter) != -1;
|
return (delimeter + (query.OfficialRatings || '') + delimeter).includes(delimeter + i + delimeter);
|
||||||
});
|
});
|
||||||
renderOptions(context, ".tagFilters", "chkTagFilter", result.Tags, function (i) {
|
renderOptions(context, '.tagFilters', 'chkTagFilter', result.Tags, function (i) {
|
||||||
var delimeter = "|";
|
const delimeter = '|';
|
||||||
return (delimeter + (query.Tags || "") + delimeter).indexOf(delimeter + i + delimeter) != -1;
|
return (delimeter + (query.Tags || '') + delimeter).includes(delimeter + i + delimeter);
|
||||||
});
|
});
|
||||||
renderOptions(context, ".yearFilters", "chkYearFilter", result.Years, function (i) {
|
renderOptions(context, '.yearFilters', 'chkYearFilter', result.Years, function (i) {
|
||||||
var delimeter = ",";
|
const delimeter = ',';
|
||||||
return (delimeter + (query.Years || "") + delimeter).indexOf(delimeter + i + delimeter) != -1;
|
return (delimeter + (query.Years || '') + delimeter).includes(delimeter + i + delimeter);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadDynamicFilters(context, apiClient, userId, itemQuery) {
|
function loadDynamicFilters(context, apiClient, userId, itemQuery) {
|
||||||
return apiClient.getJSON(apiClient.getUrl("Items/Filters", {
|
return apiClient.getJSON(apiClient.getUrl('Items/Filters', {
|
||||||
UserId: userId,
|
UserId: userId,
|
||||||
ParentId: itemQuery.ParentId,
|
ParentId: itemQuery.ParentId,
|
||||||
IncludeItemTypes: itemQuery.IncludeItemTypes
|
IncludeItemTypes: itemQuery.IncludeItemTypes
|
||||||
|
@ -55,346 +62,372 @@ define(["dom", "dialogHelper", "globalize", "connectionManager", "events", "brow
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param context {HTMLDivElement} Dialog
|
||||||
|
* @param options {any} Options
|
||||||
|
*/
|
||||||
function updateFilterControls(context, options) {
|
function updateFilterControls(context, options) {
|
||||||
var elems;
|
const query = options.query;
|
||||||
var i;
|
|
||||||
var length;
|
|
||||||
var query = options.query;
|
|
||||||
|
|
||||||
if (options.mode == "livetvchannels") {
|
if (options.mode === 'livetvchannels') {
|
||||||
context.querySelector(".chkFavorite").checked = query.IsFavorite == true;
|
context.querySelector('.chkFavorite').checked = query.IsFavorite === true;
|
||||||
context.querySelector(".chkLikes").checked = query.IsLiked == true;
|
context.querySelector('.chkLikes').checked = query.IsLiked === true;
|
||||||
context.querySelector(".chkDislikes").checked = query.IsDisliked == true;
|
context.querySelector('.chkDislikes').checked = query.IsDisliked === true;
|
||||||
} else {
|
} else {
|
||||||
elems = context.querySelectorAll(".chkStandardFilter");
|
for (const elem of context.querySelectorAll('.chkStandardFilter')) {
|
||||||
for (i = 0, length = elems.length; i < length; i++) {
|
const filters = `,${query.Filters || ''}`;
|
||||||
var chkStandardFilter = elems[i];
|
const filterName = elem.getAttribute('data-filter');
|
||||||
var filters = "," + (query.Filters || "");
|
elem.checked = filters.includes(`,${filterName}`);
|
||||||
var filterName = chkStandardFilter.getAttribute("data-filter");
|
|
||||||
chkStandardFilter.checked = filters.indexOf("," + filterName) != -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
elems = context.querySelectorAll(".chkVideoTypeFilter");
|
for (const elem of context.querySelectorAll('.chkVideoTypeFilter')) {
|
||||||
for (i = 0, length = elems.length; i < length; i++) {
|
const filters = `,${query.VideoTypes || ''}`;
|
||||||
var chkVideoTypeFilter = elems[i];
|
const filterName = elem.getAttribute('data-filter');
|
||||||
var filters = "," + (query.VideoTypes || "");
|
elem.checked = filters.includes(`,${filterName}`);
|
||||||
var filterName = chkVideoTypeFilter.getAttribute("data-filter");
|
|
||||||
chkVideoTypeFilter.checked = filters.indexOf("," + filterName) != -1;
|
|
||||||
}
|
}
|
||||||
context.querySelector(".chk3DFilter").checked = query.Is3D == true;
|
context.querySelector('.chk3DFilter').checked = query.Is3D === true;
|
||||||
context.querySelector(".chkHDFilter").checked = query.IsHD == true;
|
context.querySelector('.chkHDFilter').checked = query.IsHD === true;
|
||||||
context.querySelector(".chk4KFilter").checked = query.Is4K == true;
|
context.querySelector('.chk4KFilter').checked = query.Is4K === true;
|
||||||
context.querySelector(".chkSDFilter").checked = query.IsHD == true;
|
context.querySelector('.chkSDFilter').checked = query.IsHD === true;
|
||||||
context.querySelector("#chkSubtitle").checked = query.HasSubtitles == true;
|
context.querySelector('#chkSubtitle').checked = query.HasSubtitles === true;
|
||||||
context.querySelector("#chkTrailer").checked = query.HasTrailer == true;
|
context.querySelector('#chkTrailer').checked = query.HasTrailer === true;
|
||||||
context.querySelector("#chkThemeSong").checked = query.HasThemeSong == true;
|
context.querySelector('#chkThemeSong').checked = query.HasThemeSong === true;
|
||||||
context.querySelector("#chkThemeVideo").checked = query.HasThemeVideo == true;
|
context.querySelector('#chkThemeVideo').checked = query.HasThemeVideo === true;
|
||||||
context.querySelector("#chkSpecialFeature").checked = query.HasSpecialFeature == true;
|
context.querySelector('#chkSpecialFeature').checked = query.HasSpecialFeature === true;
|
||||||
context.querySelector("#chkSpecialEpisode").checked = query.ParentIndexNumber == 0;
|
context.querySelector('#chkSpecialEpisode').checked = query.ParentIndexNumber === 0;
|
||||||
context.querySelector("#chkMissingEpisode").checked = query.IsMissing == true;
|
context.querySelector('#chkMissingEpisode').checked = query.IsMissing === true;
|
||||||
context.querySelector("#chkFutureEpisode").checked = query.IsUnaired == true;
|
context.querySelector('#chkFutureEpisode').checked = query.IsUnaired === true;
|
||||||
for (i = 0, length = elems.length; i < length; i++) {
|
for (const elem of context.querySelectorAll('.chkStatus')) {
|
||||||
var chkStatus = elems[i];
|
const filters = `,${query.SeriesStatus || ''}`;
|
||||||
var filters = "," + (query.SeriesStatus || "");
|
const filterName = elem.getAttribute('data-filter');
|
||||||
var filterName = chkStatus.getAttribute("data-filter");
|
elem.checked = filters.includes(`,${filterName}`);
|
||||||
chkStatus.checked = filters.indexOf("," + filterName) != -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param instance {FilterDialog} An instance of FilterDialog
|
||||||
|
*/
|
||||||
function triggerChange(instance) {
|
function triggerChange(instance) {
|
||||||
events.trigger(instance, "filterchange");
|
events.trigger(instance, 'filterchange');
|
||||||
}
|
}
|
||||||
|
|
||||||
function setVisibility(context, options) {
|
function setVisibility(context, options) {
|
||||||
if (options.mode == "livetvchannels" || options.mode == "albums" || options.mode == "artists" || options.mode == "albumartists" || options.mode == "songs") {
|
if (options.mode === 'livetvchannels' || options.mode === 'albums' || options.mode === 'artists' || options.mode === 'albumartists' || options.mode === 'songs') {
|
||||||
hideByClass(context, "videoStandard");
|
hideByClass(context, 'videoStandard');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enableDynamicFilters(options.mode)) {
|
if (enableDynamicFilters(options.mode)) {
|
||||||
context.querySelector(".genreFilters").classList.remove("hide");
|
context.querySelector('.genreFilters').classList.remove('hide');
|
||||||
context.querySelector(".officialRatingFilters").classList.remove("hide");
|
context.querySelector('.officialRatingFilters').classList.remove('hide');
|
||||||
context.querySelector(".tagFilters").classList.remove("hide");
|
context.querySelector('.tagFilters').classList.remove('hide');
|
||||||
context.querySelector(".yearFilters").classList.remove("hide");
|
context.querySelector('.yearFilters').classList.remove('hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.mode == "movies" || options.mode == "episodes") {
|
if (options.mode === 'movies' || options.mode === 'episodes') {
|
||||||
context.querySelector(".videoTypeFilters").classList.remove("hide");
|
context.querySelector('.videoTypeFilters').classList.remove('hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.mode == "movies" || options.mode == "series" || options.mode == "episodes") {
|
if (options.mode === 'movies' || options.mode === 'series' || options.mode === 'episodes') {
|
||||||
context.querySelector(".features").classList.remove("hide");
|
context.querySelector('.features').classList.remove('hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.mode == "series") {
|
if (options.mode === 'series') {
|
||||||
context.querySelector(".seriesStatus").classList.remove("hide");
|
context.querySelector('.seriesStatus').classList.remove('hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.mode == "episodes") {
|
if (options.mode === 'episodes') {
|
||||||
showByClass(context, "episodeFilter");
|
showByClass(context, 'episodeFilter');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showByClass(context, className) {
|
function showByClass(context, className) {
|
||||||
var elems = context.querySelectorAll("." + className);
|
for (const elem of context.querySelectorAll(`.${className}`)) {
|
||||||
|
elem.classList.remove('hide');
|
||||||
for (var i = 0, length = elems.length; i < length; i++) {
|
|
||||||
elems[i].classList.remove("hide");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideByClass(context, className) {
|
function hideByClass(context, className) {
|
||||||
var elems = context.querySelectorAll("." + className);
|
for (const elem of context.querySelectorAll(`.${className}`)) {
|
||||||
|
elem.classList.add('hide');
|
||||||
for (var i = 0, length = elems.length; i < length; i++) {
|
|
||||||
elems[i].classList.add("hide");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function enableDynamicFilters(mode) {
|
function enableDynamicFilters(mode) {
|
||||||
return mode == "movies" || mode == "series" || mode == "albums" || mode == "albumartists" || mode == "artists" || mode == "songs" || mode == "episodes";
|
return mode === 'movies' || mode === 'series' || mode === 'albums' || mode === 'albumartists' || mode === 'artists' || mode === 'songs' || mode === 'episodes';
|
||||||
}
|
}
|
||||||
|
|
||||||
return function (options) {
|
class FilterDialog {
|
||||||
function onFavoriteChange() {
|
constructor(options) {
|
||||||
var query = options.query;
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
onFavoriteChange(elem) {
|
||||||
|
const query = this.options.query;
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.IsFavorite = !!this.checked || null;
|
query.IsFavorite = !!elem.checked || null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onStandardFilterChange() {
|
/**
|
||||||
var query = options.query;
|
* @private
|
||||||
var filterName = this.getAttribute("data-filter");
|
*/
|
||||||
var filters = query.Filters || "";
|
onStandardFilterChange(elem) {
|
||||||
filters = ("," + filters).replace("," + filterName, "").substring(1);
|
const query = this.options.query;
|
||||||
|
const filterName = elem.getAttribute('data-filter');
|
||||||
|
let filters = query.Filters || '';
|
||||||
|
filters = (`,${filters}`).replace(`,${filterName}`, '').substring(1);
|
||||||
|
|
||||||
if (this.checked) {
|
if (elem.checked) {
|
||||||
filters = filters ? filters + "," + filterName : filterName;
|
filters = filters ? `${filters},${filterName}` : filterName;
|
||||||
}
|
}
|
||||||
|
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.Filters = filters;
|
query.Filters = filters;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onVideoTypeFilterChange() {
|
/**
|
||||||
var query = options.query;
|
* @private
|
||||||
var filterName = this.getAttribute("data-filter");
|
*/
|
||||||
var filters = query.VideoTypes || "";
|
onVideoTypeFilterChange(elem) {
|
||||||
filters = ("," + filters).replace("," + filterName, "").substring(1);
|
const query = this.options.query;
|
||||||
|
const filterName = elem.getAttribute('data-filter');
|
||||||
|
let filters = query.VideoTypes || '';
|
||||||
|
filters = (`,${filters}`).replace(`,${filterName}`, '').substring(1);
|
||||||
|
|
||||||
if (this.checked) {
|
if (elem.checked) {
|
||||||
filters = filters ? filters + "," + filterName : filterName;
|
filters = filters ? `${filters},${filterName}` : filterName;
|
||||||
}
|
}
|
||||||
|
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.VideoTypes = filters;
|
query.VideoTypes = filters;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onStatusChange() {
|
/**
|
||||||
var query = options.query;
|
* @private
|
||||||
var filterName = this.getAttribute("data-filter");
|
*/
|
||||||
var filters = query.SeriesStatus || "";
|
onStatusChange(elem) {
|
||||||
filters = ("," + filters).replace("," + filterName, "").substring(1);
|
const query = this.options.query;
|
||||||
|
const filterName = elem.getAttribute('data-filter');
|
||||||
|
let filters = query.SeriesStatus || '';
|
||||||
|
filters = (`,${filters}`).replace(`,${filterName}`, '').substring(1);
|
||||||
|
|
||||||
if (this.checked) {
|
if (elem.checked) {
|
||||||
filters = filters ? filters + "," + filterName : filterName;
|
filters = filters ? `${filters},${filterName}` : filterName;
|
||||||
}
|
}
|
||||||
|
|
||||||
query.SeriesStatus = filters;
|
query.SeriesStatus = filters;
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
function bindEvents(context) {
|
/**
|
||||||
var elems;
|
* @param context {HTMLDivElement} The dialog
|
||||||
var i;
|
*/
|
||||||
var length;
|
bindEvents(context) {
|
||||||
var query = options.query;
|
const query = this.options.query;
|
||||||
|
|
||||||
if (options.mode == "livetvchannels") {
|
if (this.options.mode === 'livetvchannels') {
|
||||||
elems = context.querySelectorAll(".chkFavorite");
|
for (const elem of context.querySelectorAll('.chkFavorite')) {
|
||||||
for (i = 0, length = elems.length; i < length; i++) {
|
elem.addEventListener('change', () => this.onFavoriteChange(elem));
|
||||||
elems[i].addEventListener("change", onFavoriteChange);
|
|
||||||
}
|
}
|
||||||
context.querySelector(".chkLikes").addEventListener("change", function () {
|
|
||||||
|
const chkLikes = context.querySelector('.chkLikes');
|
||||||
|
chkLikes.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.IsLiked = this.checked ? true : null;
|
query.IsLiked = chkLikes.checked ? true : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector(".chkDislikes").addEventListener("change", function () {
|
const chkDislikes = context.querySelector('.chkDislikes');
|
||||||
|
chkDislikes.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.IsDisliked = this.checked ? true : null;
|
query.IsDisliked = chkDislikes.checked ? true : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
elems = context.querySelectorAll(".chkStandardFilter");
|
for (const elem of context.querySelectorAll('.chkStandardFilter')) {
|
||||||
for (i = 0, length = elems.length; i < length; i++) {
|
elem.addEventListener('change', () => this.onStandardFilterChange(elem));
|
||||||
elems[i].addEventListener("change", onStandardFilterChange);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elems = context.querySelectorAll(".chkVideoTypeFilter");
|
|
||||||
for (i = 0, length = elems.length; i < length; i++) {
|
for (const elem of context.querySelectorAll('.chkVideoTypeFilter')) {
|
||||||
elems[i].addEventListener("change", onVideoTypeFilterChange);
|
elem.addEventListener('change', () => this.onVideoTypeFilterChange(elem));
|
||||||
}
|
}
|
||||||
context.querySelector(".chk3DFilter").addEventListener("change", function () {
|
const chk3DFilter = context.querySelector('.chk3DFilter');
|
||||||
|
chk3DFilter.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.Is3D = this.checked ? true : null;
|
query.Is3D = chk3DFilter.checked ? true : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector(".chk4KFilter").addEventListener("change", function () {
|
const chk4KFilter = context.querySelector('.chk4KFilter');
|
||||||
|
chk4KFilter.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.Is4K = this.checked ? true : null;
|
query.Is4K = chk4KFilter.checked ? true : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector(".chkHDFilter").addEventListener("change", function () {
|
const chkHDFilter = context.querySelector('.chkHDFilter');
|
||||||
|
chkHDFilter.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.IsHD = this.checked ? true : null;
|
query.IsHD = chkHDFilter.checked ? true : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector(".chkSDFilter").addEventListener("change", function () {
|
const chkSDFilter = context.querySelector('.chkSDFilter');
|
||||||
|
chkSDFilter.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.IsHD = this.checked ? false : null;
|
query.IsHD = chkSDFilter.checked ? false : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
elems = context.querySelectorAll(".chkStatus");
|
for (const elem of context.querySelectorAll('.chkStatus')) {
|
||||||
for (i = 0, length = elems.length; i < length; i++) {
|
elem.addEventListener('change', () => this.onStatusChange(elem));
|
||||||
elems[i].addEventListener("change", onStatusChange);
|
|
||||||
}
|
}
|
||||||
context.querySelector("#chkTrailer").addEventListener("change", function () {
|
const chkTrailer = context.querySelector('#chkTrailer');
|
||||||
|
chkTrailer.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.HasTrailer = this.checked ? true : null;
|
query.HasTrailer = chkTrailer.checked ? true : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector("#chkThemeSong").addEventListener("change", function () {
|
const chkThemeSong = context.querySelector('#chkThemeSong');
|
||||||
|
chkThemeSong.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.HasThemeSong = this.checked ? true : null;
|
query.HasThemeSong = chkThemeSong.checked ? true : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector("#chkSpecialFeature").addEventListener("change", function () {
|
const chkSpecialFeature = context.querySelector('#chkSpecialFeature');
|
||||||
|
chkSpecialFeature.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.HasSpecialFeature = this.checked ? true : null;
|
query.HasSpecialFeature = chkSpecialFeature.checked ? true : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector("#chkThemeVideo").addEventListener("change", function () {
|
const chkThemeVideo = context.querySelector('#chkThemeVideo');
|
||||||
|
chkThemeVideo.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.HasThemeVideo = this.checked ? true : null;
|
query.HasThemeVideo = chkThemeVideo.checked ? true : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector("#chkMissingEpisode").addEventListener("change", function () {
|
const chkMissingEpisode = context.querySelector('#chkMissingEpisode');
|
||||||
|
chkMissingEpisode.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.IsMissing = this.checked ? true : false;
|
query.IsMissing = !!chkMissingEpisode.checked;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector("#chkSpecialEpisode").addEventListener("change", function () {
|
const chkSpecialEpisode = context.querySelector('#chkSpecialEpisode');
|
||||||
|
chkSpecialEpisode.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.ParentIndexNumber = this.checked ? 0 : null;
|
query.ParentIndexNumber = chkSpecialEpisode.checked ? 0 : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector("#chkFutureEpisode").addEventListener("change", function () {
|
const chkFutureEpisode = context.querySelector('#chkFutureEpisode');
|
||||||
|
chkFutureEpisode.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
if (this.checked) {
|
if (chkFutureEpisode.checked) {
|
||||||
query.IsUnaired = true;
|
query.IsUnaired = true;
|
||||||
query.IsVirtualUnaired = null;
|
query.IsVirtualUnaired = null;
|
||||||
} else {
|
} else {
|
||||||
query.IsUnaired = null;
|
query.IsUnaired = null;
|
||||||
query.IsVirtualUnaired = false;
|
query.IsVirtualUnaired = false;
|
||||||
}
|
}
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.querySelector("#chkSubtitle").addEventListener("change", function () {
|
const chkSubtitle = context.querySelector('#chkSubtitle');
|
||||||
|
chkSubtitle.addEventListener('change', () => {
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.HasSubtitles = this.checked ? true : null;
|
query.HasSubtitles = chkSubtitle.checked ? true : null;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
});
|
});
|
||||||
context.addEventListener("change", function (e) {
|
context.addEventListener('change', (e) => {
|
||||||
var chkGenreFilter = dom.parentWithClass(e.target, "chkGenreFilter");
|
const chkGenreFilter = dom.parentWithClass(e.target, 'chkGenreFilter');
|
||||||
if (chkGenreFilter) {
|
if (chkGenreFilter) {
|
||||||
var filterName = chkGenreFilter.getAttribute("data-filter");
|
const filterName = chkGenreFilter.getAttribute('data-filter');
|
||||||
var filters = query.Genres || "";
|
let filters = query.Genres || '';
|
||||||
var delimiter = "|";
|
const delimiter = '|';
|
||||||
filters = (delimiter + filters).replace(delimiter + filterName, "").substring(1);
|
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
|
||||||
if (chkGenreFilter.checked) {
|
if (chkGenreFilter.checked) {
|
||||||
filters = filters ? (filters + delimiter + filterName) : filterName;
|
filters = filters ? (filters + delimiter + filterName) : filterName;
|
||||||
}
|
}
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.Genres = filters;
|
query.Genres = filters;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var chkTagFilter = dom.parentWithClass(e.target, "chkTagFilter");
|
const chkTagFilter = dom.parentWithClass(e.target, 'chkTagFilter');
|
||||||
if (chkTagFilter) {
|
if (chkTagFilter) {
|
||||||
var filterName = chkTagFilter.getAttribute("data-filter");
|
const filterName = chkTagFilter.getAttribute('data-filter');
|
||||||
var filters = query.Tags || "";
|
let filters = query.Tags || '';
|
||||||
var delimiter = "|";
|
const delimiter = '|';
|
||||||
filters = (delimiter + filters).replace(delimiter + filterName, "").substring(1);
|
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
|
||||||
if (chkTagFilter.checked) {
|
if (chkTagFilter.checked) {
|
||||||
filters = filters ? (filters + delimiter + filterName) : filterName;
|
filters = filters ? (filters + delimiter + filterName) : filterName;
|
||||||
}
|
}
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.Tags = filters;
|
query.Tags = filters;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var chkYearFilter = dom.parentWithClass(e.target, "chkYearFilter");
|
const chkYearFilter = dom.parentWithClass(e.target, 'chkYearFilter');
|
||||||
if (chkYearFilter) {
|
if (chkYearFilter) {
|
||||||
var filterName = chkYearFilter.getAttribute("data-filter");
|
const filterName = chkYearFilter.getAttribute('data-filter');
|
||||||
var filters = query.Years || "";
|
let filters = query.Years || '';
|
||||||
var delimiter = ",";
|
const delimiter = ',';
|
||||||
filters = (delimiter + filters).replace(delimiter + filterName, "").substring(1);
|
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
|
||||||
if (chkYearFilter.checked) {
|
if (chkYearFilter.checked) {
|
||||||
filters = filters ? (filters + delimiter + filterName) : filterName;
|
filters = filters ? (filters + delimiter + filterName) : filterName;
|
||||||
}
|
}
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.Years = filters;
|
query.Years = filters;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var chkOfficialRatingFilter = dom.parentWithClass(e.target, "chkOfficialRatingFilter");
|
const chkOfficialRatingFilter = dom.parentWithClass(e.target, 'chkOfficialRatingFilter');
|
||||||
if (chkOfficialRatingFilter) {
|
if (chkOfficialRatingFilter) {
|
||||||
var filterName = chkOfficialRatingFilter.getAttribute("data-filter");
|
const filterName = chkOfficialRatingFilter.getAttribute('data-filter');
|
||||||
var filters = query.OfficialRatings || "";
|
let filters = query.OfficialRatings || '';
|
||||||
var delimiter = "|";
|
const delimiter = '|';
|
||||||
filters = (delimiter + filters).replace(delimiter + filterName, "").substring(1);
|
filters = (delimiter + filters).replace(delimiter + filterName, '').substring(1);
|
||||||
if (chkOfficialRatingFilter.checked) {
|
if (chkOfficialRatingFilter.checked) {
|
||||||
filters = filters ? (filters + delimiter + filterName) : filterName;
|
filters = filters ? (filters + delimiter + filterName) : filterName;
|
||||||
}
|
}
|
||||||
query.StartIndex = 0;
|
query.StartIndex = 0;
|
||||||
query.OfficialRatings = filters;
|
query.OfficialRatings = filters;
|
||||||
triggerChange(self);
|
triggerChange(this);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
show() {
|
||||||
|
return import('text!./filterdialog.template.html').then(({default: template}) => {
|
||||||
self.show = function () {
|
return new Promise((resolve) => {
|
||||||
return new Promise(function (resolve, reject) {
|
const dlg = dialogHelper.createDialog({
|
||||||
require(["text!./filterdialog.template.html"], function (template) {
|
|
||||||
var dlg = dialogHelper.createDialog({
|
|
||||||
removeOnClose: true,
|
removeOnClose: true,
|
||||||
modal: false
|
modal: false
|
||||||
});
|
});
|
||||||
dlg.classList.add("ui-body-a");
|
dlg.classList.add('ui-body-a');
|
||||||
dlg.classList.add("background-theme-a");
|
dlg.classList.add('background-theme-a');
|
||||||
dlg.classList.add("formDialog");
|
dlg.classList.add('formDialog');
|
||||||
dlg.classList.add("filterDialog");
|
dlg.classList.add('filterDialog');
|
||||||
dlg.innerHTML = globalize.translateDocument(template);
|
dlg.innerHTML = globalize.translateDocument(template);
|
||||||
setVisibility(dlg, options);
|
setVisibility(dlg, this.options);
|
||||||
dialogHelper.open(dlg);
|
dialogHelper.open(dlg);
|
||||||
dlg.addEventListener("close", resolve);
|
dlg.addEventListener('close', resolve);
|
||||||
updateFilterControls(dlg, options);
|
updateFilterControls(dlg, this.options);
|
||||||
bindEvents(dlg);
|
this.bindEvents(dlg);
|
||||||
if (enableDynamicFilters(options.mode)) {
|
if (enableDynamicFilters(this.options.mode)) {
|
||||||
dlg.classList.add("dynamicFilterDialog");
|
dlg.classList.add('dynamicFilterDialog');
|
||||||
var apiClient = connectionManager.getApiClient(options.serverId);
|
const apiClient = connectionManager.getApiClient(this.options.serverId);
|
||||||
loadDynamicFilters(dlg, apiClient, apiClient.getCurrentUserId(), options.query);
|
loadDynamicFilters(dlg, apiClient, apiClient.getCurrentUserId(), this.options.query);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
});
|
|
||||||
|
/* eslint-enable indent */
|
||||||
|
|
||||||
|
export default FilterDialog;
|
||||||
|
|
|
@ -279,7 +279,7 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||||
var html = '';
|
var html = '';
|
||||||
|
|
||||||
html += '<div class="formDialogHeader">';
|
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 += '<h3 class="formDialogHeaderTitle">${Filters}</h3>';
|
||||||
|
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
|
|
@ -117,7 +117,7 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elem.getAttribute('tabindex') === "-1") {
|
if (elem.getAttribute('tabindex') === '-1') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.formDialogHeaderTitle:first-child {
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
.formDialogContent:not(.no-grow) {
|
.formDialogContent:not(.no-grow) {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
@ -46,10 +50,16 @@
|
||||||
right: 0;
|
right: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
padding: 1.25em 1em;
|
padding: 1em 1em;
|
||||||
|
|
||||||
/* Without this emby-checkbox is able to appear on top */
|
/* Without this emby-checkbox is able to appear on top */
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
align-items: flex-end;
|
||||||
|
justify-content: flex-end;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-tv .formDialogFooter {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
@ -69,8 +79,12 @@
|
||||||
|
|
||||||
.formDialogFooterItem {
|
.formDialogFooterItem {
|
||||||
margin: 0.5em !important;
|
margin: 0.5em !important;
|
||||||
flex-grow: 1;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
flex-basis: 12em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-tv .formDialogFooterItem {
|
||||||
|
flex-grow: 1;
|
||||||
flex-basis: 0;
|
flex-basis: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
});
|
|
|
@ -1,28 +1,28 @@
|
||||||
define(["dom", "appRouter", "connectionManager"], function (dom, appRouter, connectionManager) {
|
define(['dom', 'appRouter', 'connectionManager'], function (dom, appRouter, connectionManager) {
|
||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
function onGroupedCardClick(e, card) {
|
function onGroupedCardClick(e, card) {
|
||||||
var itemId = card.getAttribute("data-id");
|
var itemId = card.getAttribute('data-id');
|
||||||
var serverId = card.getAttribute("data-serverid");
|
var serverId = card.getAttribute('data-serverid');
|
||||||
var apiClient = connectionManager.getApiClient(serverId);
|
var apiClient = connectionManager.getApiClient(serverId);
|
||||||
var userId = apiClient.getCurrentUserId();
|
var userId = apiClient.getCurrentUserId();
|
||||||
var playedIndicator = card.querySelector(".playedIndicator");
|
var playedIndicator = card.querySelector('.playedIndicator');
|
||||||
var playedIndicatorHtml = playedIndicator ? playedIndicator.innerHTML : null;
|
var playedIndicatorHtml = playedIndicator ? playedIndicator.innerHTML : null;
|
||||||
var options = {
|
var options = {
|
||||||
Limit: parseInt(playedIndicatorHtml || "10"),
|
Limit: parseInt(playedIndicatorHtml || '10'),
|
||||||
Fields: "PrimaryImageAspectRatio,DateCreated",
|
Fields: 'PrimaryImageAspectRatio,DateCreated',
|
||||||
ParentId: itemId,
|
ParentId: itemId,
|
||||||
GroupItems: false
|
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")) {
|
if (!actionableParent || actionableParent.classList.contains('cardContent')) {
|
||||||
apiClient.getJSON(apiClient.getUrl("Users/" + userId + "/Items/Latest", options)).then(function (items) {
|
apiClient.getJSON(apiClient.getUrl('Users/' + userId + '/Items/Latest', options)).then(function (items) {
|
||||||
if (1 === items.length) {
|
if (1 === items.length) {
|
||||||
return void appRouter.showItem(items[0]);
|
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);
|
Dashboard.navigate(url);
|
||||||
});
|
});
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
@ -32,7 +32,7 @@ define(["dom", "appRouter", "connectionManager"], function (dom, appRouter, conn
|
||||||
}
|
}
|
||||||
|
|
||||||
function onItemsContainerClick(e) {
|
function onItemsContainerClick(e) {
|
||||||
var groupedCard = dom.parentWithClass(e.target, "groupedCard");
|
var groupedCard = dom.parentWithClass(e.target, 'groupedCard');
|
||||||
|
|
||||||
if (groupedCard) {
|
if (groupedCard) {
|
||||||
onGroupedCardClick(e, groupedCard);
|
onGroupedCardClick(e, groupedCard);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
<div class="formDialogHeader">
|
<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" title="${LabelPrevious}" tabindex="-1">
|
||||||
|
<span class="material-icons arrow_back" aria-hidden="true"></span>
|
||||||
|
</button>
|
||||||
<h3 class="formDialogHeaderTitle">
|
<h3 class="formDialogHeaderTitle">
|
||||||
${Settings}
|
${Settings}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
|
@ -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';
|
'use strict';
|
||||||
|
|
||||||
function showViewSettings(instance) {
|
function showViewSettings(instance) {
|
||||||
|
@ -227,7 +227,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||||
channelQuery.Limit = channelLimit;
|
channelQuery.Limit = channelLimit;
|
||||||
channelQuery.AddCurrentProgram = false;
|
channelQuery.AddCurrentProgram = false;
|
||||||
channelQuery.EnableUserData = false;
|
channelQuery.EnableUserData = false;
|
||||||
channelQuery.EnableImageTypes = "Primary";
|
channelQuery.EnableImageTypes = 'Primary';
|
||||||
|
|
||||||
var categories = self.categoryOptions.categories || [];
|
var categories = self.categoryOptions.categories || [];
|
||||||
var displayMovieContent = !categories.length || categories.indexOf('movies') !== -1;
|
var displayMovieContent = !categories.length || categories.indexOf('movies') !== -1;
|
||||||
|
@ -261,8 +261,8 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userSettings.get('livetv-channelorder') === 'DatePlayed') {
|
if (userSettings.get('livetv-channelorder') === 'DatePlayed') {
|
||||||
channelQuery.SortBy = "DatePlayed";
|
channelQuery.SortBy = 'DatePlayed';
|
||||||
channelQuery.SortOrder = "Descending";
|
channelQuery.SortOrder = 'Descending';
|
||||||
} else {
|
} else {
|
||||||
channelQuery.SortBy = null;
|
channelQuery.SortBy = null;
|
||||||
channelQuery.SortOrder = null;
|
channelQuery.SortOrder = null;
|
||||||
|
@ -329,7 +329,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||||
ImageTypeLimit: 1,
|
ImageTypeLimit: 1,
|
||||||
EnableImages: false,
|
EnableImages: false,
|
||||||
//EnableImageTypes: layoutManager.tv ? "Primary,Backdrop" : "Primary",
|
//EnableImageTypes: layoutManager.tv ? "Primary,Backdrop" : "Primary",
|
||||||
SortBy: "StartDate",
|
SortBy: 'StartDate',
|
||||||
EnableTotalRecordCount: false,
|
EnableTotalRecordCount: false,
|
||||||
EnableUserData: false
|
EnableUserData: false
|
||||||
};
|
};
|
||||||
|
@ -415,7 +415,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||||
var status;
|
var status;
|
||||||
|
|
||||||
if (item.Type === 'SeriesTimer') {
|
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) {
|
} else if (item.TimerId || item.SeriesTimerId) {
|
||||||
|
|
||||||
status = item.Status || 'Cancelled';
|
status = item.Status || 'Cancelled';
|
||||||
|
@ -429,13 +429,13 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||||
if (item.SeriesTimerId) {
|
if (item.SeriesTimerId) {
|
||||||
|
|
||||||
if (status !== 'Cancelled') {
|
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) {
|
function getChannelProgramsHtml(context, date, channel, programs, options, listInfo) {
|
||||||
|
@ -502,7 +502,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||||
var endPercent = (renderEndMs - renderStartMs) / msPerDay;
|
var endPercent = (renderEndMs - renderStartMs) / msPerDay;
|
||||||
endPercent *= 100;
|
endPercent *= 100;
|
||||||
|
|
||||||
var cssClass = "programCell itemAction";
|
var cssClass = 'programCell itemAction';
|
||||||
var accentCssClass = null;
|
var accentCssClass = null;
|
||||||
var displayInnerContent = true;
|
var displayInnerContent = true;
|
||||||
|
|
||||||
|
@ -525,11 +525,11 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||||
}
|
}
|
||||||
|
|
||||||
if (displayInnerContent && enableColorCodedBackgrounds && accentCssClass) {
|
if (displayInnerContent && enableColorCodedBackgrounds && accentCssClass) {
|
||||||
cssClass += " programCell-" + accentCssClass;
|
cssClass += ' programCell-' + accentCssClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (now >= startDateLocalMs && now < endDateLocalMs) {
|
if (now >= startDateLocalMs && now < endDateLocalMs) {
|
||||||
cssClass += " programCell-active";
|
cssClass += ' programCell-active';
|
||||||
}
|
}
|
||||||
|
|
||||||
var timerAttributes = '';
|
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 + '%;">';
|
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) {
|
if (displayInnerContent) {
|
||||||
var guideProgramNameClass = "guideProgramName";
|
var guideProgramNameClass = 'guideProgramName';
|
||||||
|
|
||||||
html += '<div class="' + guideProgramNameClass + '">';
|
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;
|
html += '<div class="guideProgramNameText">' + program.Name;
|
||||||
|
|
||||||
|
@ -577,7 +577,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
|
||||||
if (program.IsHD && options.showHdIcon) {
|
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) {
|
if (layoutManager.tv) {
|
||||||
html += '<div class="programIcon guide-programTextIcon guide-programTextIcon-tv">HD</div>';
|
html += '<div class="programIcon guide-programTextIcon guide-programTextIcon-tv">HD</div>';
|
||||||
} else {
|
} else {
|
||||||
|
@ -630,7 +630,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||||
var url = apiClient.getScaledImageUrl(channel.Id, {
|
var url = apiClient.getScaledImageUrl(channel.Id, {
|
||||||
maxHeight: 220,
|
maxHeight: 220,
|
||||||
tag: channel.ImageTags.Primary,
|
tag: channel.ImageTags.Primary,
|
||||||
type: "Primary"
|
type: 'Primary'
|
||||||
});
|
});
|
||||||
|
|
||||||
html += '<div class="guideChannelImage lazy" data-src="' + url + '"></div>';
|
html += '<div class="guideChannelImage lazy" data-src="' + url + '"></div>';
|
||||||
|
@ -1105,7 +1105,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||||
|
|
||||||
var icon = cell.querySelector('.timerIcon');
|
var icon = cell.querySelector('.timerIcon');
|
||||||
if (!icon) {
|
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) {
|
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;
|
return Guide;
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
|
|
||||||
<div class="guide-headerTimeslots">
|
<div class="guide-headerTimeslots">
|
||||||
<div class="guide-channelTimeslotHeader">
|
<div class="guide-channelTimeslotHeader">
|
||||||
<button is="paper-icon-button-light" type="button" class="btnGuideViewSettings">
|
<button is="paper-icon-button-light" type="button" class="btnGuideViewSettings" title="${ButtonMore}">
|
||||||
<i class="material-icons btnGuideViewSettingsIcon more_horiz"></i>
|
<span class="material-icons btnGuideViewSettingsIcon more_vert" aria-hidden="true"></span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="timeslotHeaders scrollX guideScroller"></div>
|
<div class="timeslotHeaders scrollX guideScroller"></div>
|
||||||
|
@ -29,10 +29,10 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="guideOptions hide">
|
<div class="guideOptions hide">
|
||||||
<button is="paper-icon-button-light" type="button" class="btnPreviousPage">
|
<button is="paper-icon-button-light" type="button" class="btnPreviousPage" title="${LabelPrevious}">
|
||||||
<i class="material-icons arrow_back"></i>
|
<span class="material-icons arrow_back" aria-hidden="true"></span>
|
||||||
</button>
|
</button>
|
||||||
<button is="paper-icon-button-light" type="button" class="btnNextPage">
|
<button is="paper-icon-button-light" type="button" class="btnNextPage" title="${LabelNext}">
|
||||||
<i class="material-icons arrow_forward"></i>
|
<span class="material-icons arrow_forward" aria-hidden="true"></span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
.headroom {
|
|
||||||
transition: transform 140ms linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
.headroom--pinned {
|
|
||||||
transform: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.headroom--unpinned:not(.headroomDisabled) {
|
|
||||||
transform: translateY(-100%);
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
});
|
|
|
@ -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) {
|
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;
|
var numConfigurableSections = 7;
|
||||||
|
|
||||||
|
@ -37,18 +37,19 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||||
var list = [];
|
var list = [];
|
||||||
|
|
||||||
if (type === 'movies') {
|
if (type === 'movies') {
|
||||||
|
|
||||||
list.push({
|
list.push({
|
||||||
name: globalize.translate('Movies'),
|
name: globalize.translate('Movies'),
|
||||||
value: 'movies',
|
value: 'movies',
|
||||||
isDefault: true
|
isDefault: true
|
||||||
});
|
});
|
||||||
|
|
||||||
list.push({
|
list.push({
|
||||||
name: globalize.translate('Suggestions'),
|
name: globalize.translate('Suggestions'),
|
||||||
value: 'suggestions'
|
value: 'suggestions'
|
||||||
});
|
});
|
||||||
|
list.push({
|
||||||
|
name: globalize.translate('Genres'),
|
||||||
|
value: 'genres'
|
||||||
|
});
|
||||||
list.push({
|
list.push({
|
||||||
name: globalize.translate('Favorites'),
|
name: globalize.translate('Favorites'),
|
||||||
value: 'favorites'
|
value: 'favorites'
|
||||||
|
@ -58,7 +59,6 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||||
value: 'collections'
|
value: 'collections'
|
||||||
});
|
});
|
||||||
} else if (type === 'tvshows') {
|
} else if (type === 'tvshows') {
|
||||||
|
|
||||||
list.push({
|
list.push({
|
||||||
name: globalize.translate('Shows'),
|
name: globalize.translate('Shows'),
|
||||||
value: 'shows',
|
value: 'shows',
|
||||||
|
@ -68,49 +68,45 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||||
name: globalize.translate('Suggestions'),
|
name: globalize.translate('Suggestions'),
|
||||||
value: 'suggestions'
|
value: 'suggestions'
|
||||||
});
|
});
|
||||||
|
|
||||||
list.push({
|
list.push({
|
||||||
name: globalize.translate('Latest'),
|
name: globalize.translate('Latest'),
|
||||||
value: 'latest'
|
value: 'latest'
|
||||||
});
|
});
|
||||||
|
list.push({
|
||||||
|
name: globalize.translate('Genres'),
|
||||||
|
value: 'genres'
|
||||||
|
});
|
||||||
list.push({
|
list.push({
|
||||||
name: globalize.translate('Favorites'),
|
name: globalize.translate('Favorites'),
|
||||||
value: 'favorites'
|
value: 'favorites'
|
||||||
});
|
});
|
||||||
} else if (type === 'music') {
|
} else if (type === 'music') {
|
||||||
|
|
||||||
list.push({
|
list.push({
|
||||||
name: globalize.translate('Suggestions'),
|
name: globalize.translate('Suggestions'),
|
||||||
value: 'suggestions',
|
value: 'suggestions',
|
||||||
isDefault: true
|
isDefault: true
|
||||||
});
|
});
|
||||||
|
|
||||||
list.push({
|
list.push({
|
||||||
name: globalize.translate('Albums'),
|
name: globalize.translate('Albums'),
|
||||||
value: 'albums'
|
value: 'albums'
|
||||||
});
|
});
|
||||||
|
|
||||||
list.push({
|
list.push({
|
||||||
name: globalize.translate('HeaderAlbumArtists'),
|
name: globalize.translate('HeaderAlbumArtists'),
|
||||||
value: 'albumartists'
|
value: 'albumartists'
|
||||||
});
|
});
|
||||||
|
|
||||||
list.push({
|
list.push({
|
||||||
name: globalize.translate('Artists'),
|
name: globalize.translate('Artists'),
|
||||||
value: 'artists'
|
value: 'artists'
|
||||||
});
|
});
|
||||||
|
|
||||||
list.push({
|
list.push({
|
||||||
name: globalize.translate('Playlists'),
|
name: globalize.translate('Playlists'),
|
||||||
value: 'playlists'
|
value: 'playlists'
|
||||||
});
|
});
|
||||||
|
|
||||||
list.push({
|
list.push({
|
||||||
name: globalize.translate('Genres'),
|
name: globalize.translate('Genres'),
|
||||||
value: 'genres'
|
value: 'genres'
|
||||||
});
|
});
|
||||||
} else if (type === 'livetv') {
|
} else if (type === 'livetv') {
|
||||||
|
|
||||||
list.push({
|
list.push({
|
||||||
name: globalize.translate('Suggestions'),
|
name: globalize.translate('Suggestions'),
|
||||||
value: 'suggestions',
|
value: 'suggestions',
|
||||||
|
@ -149,7 +145,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||||
|
|
||||||
currentHtml += '<div class="listItem viewItem" data-viewid="' + view.Id + '">';
|
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">';
|
currentHtml += '<div class="listItemBody">';
|
||||||
|
|
||||||
|
@ -159,8 +155,8 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||||
|
|
||||||
currentHtml += '</div>';
|
currentHtml += '</div>';
|
||||||
|
|
||||||
currentHtml += '<button type="button" is="paper-icon-button-light" class="btnViewItemUp btnViewItemMove autoSize" title="' + globalize.translate('Up') + '"><i class="material-icons keyboard_arrow_up"></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') + '"><i class="material-icons keyboard_arrow_down"></i></button>';
|
currentHtml += '<button type="button" is="paper-icon-button-light" class="btnViewItemDown btnViewItemMove autoSize" title="' + globalize.translate('Down') + '"><span class="material-icons keyboard_arrow_down"></span></button>';
|
||||||
|
|
||||||
currentHtml += '</div>';
|
currentHtml += '</div>';
|
||||||
|
|
||||||
|
@ -276,7 +272,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||||
updateHomeSectionValues(context, userSettings);
|
updateHomeSectionValues(context, userSettings);
|
||||||
|
|
||||||
var promise1 = apiClient.getUserViews({ IncludeHidden: true }, user.Id);
|
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) {
|
Promise.all([promise1, promise2]).then(function (responses) {
|
||||||
|
|
||||||
|
@ -363,17 +359,17 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||||
|
|
||||||
user.Configuration.HidePlayedInLatest = context.querySelector('.chkHidePlayedFromLatest').checked;
|
user.Configuration.HidePlayedInLatest = context.querySelector('.chkHidePlayedFromLatest').checked;
|
||||||
|
|
||||||
user.Configuration.LatestItemsExcludes = getCheckboxItems(".chkIncludeInLatest", context, false).map(function (i) {
|
user.Configuration.LatestItemsExcludes = getCheckboxItems('.chkIncludeInLatest', context, false).map(function (i) {
|
||||||
|
|
||||||
return i.getAttribute('data-folderid');
|
return i.getAttribute('data-folderid');
|
||||||
});
|
});
|
||||||
|
|
||||||
user.Configuration.MyMediaExcludes = getCheckboxItems(".chkIncludeInMyMedia", context, false).map(function (i) {
|
user.Configuration.MyMediaExcludes = getCheckboxItems('.chkIncludeInMyMedia', context, false).map(function (i) {
|
||||||
|
|
||||||
return i.getAttribute('data-folderid');
|
return i.getAttribute('data-folderid');
|
||||||
});
|
});
|
||||||
|
|
||||||
user.Configuration.GroupedFolders = getCheckboxItems(".chkGroupFolder", context, true).map(function (i) {
|
user.Configuration.GroupedFolders = getCheckboxItems('.chkGroupFolder', context, true).map(function (i) {
|
||||||
|
|
||||||
return i.getAttribute('data-folderid');
|
return i.getAttribute('data-folderid');
|
||||||
});
|
});
|
||||||
|
@ -470,7 +466,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||||
|
|
||||||
function embed(options, self) {
|
function embed(options, self) {
|
||||||
|
|
||||||
require(['text!./homescreensettings.template.html'], function (template) {
|
require(['text!./homeScreenSettings.template.html'], function (template) {
|
||||||
|
|
||||||
for (var i = 1; i <= numConfigurableSections; i++) {
|
for (var i = 1; i <= numConfigurableSections; i++) {
|
||||||
template = template.replace('{section' + i + 'label}', globalize.translate('LabelHomeScreenSectionValue', i));
|
template = template.replace('{section' + i + 'label}', globalize.translate('LabelHomeScreenSectionValue', i));
|
|
@ -10,6 +10,13 @@
|
||||||
<div class="fieldDescription">${LabelPleaseRestart}</div>
|
<div class="fieldDescription">${LabelPleaseRestart}</div>
|
||||||
</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">
|
<div class="selectContainer">
|
||||||
<select is="emby-select" id="selectHomeSection1" label="{section1label}">
|
<select is="emby-select" id="selectHomeSection1" label="{section1label}">
|
||||||
<option value="smalllibrarytiles">${HeaderMyMedia}</option>
|
<option value="smalllibrarytiles">${HeaderMyMedia}</option>
|
||||||
|
@ -110,13 +117,6 @@
|
||||||
|
|
||||||
<div class="perLibrarySettings"></div>
|
<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">
|
<div class="verticalSection verticalSection-extrabottompadding">
|
||||||
<h2 class="sectionTitle">${HeaderLibraryFolders}</h2>
|
<h2 class="sectionTitle">${HeaderLibraryFolders}</h2>
|
||||||
<div>
|
<div>
|
|
@ -64,21 +64,21 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||||
} else {
|
} else {
|
||||||
var noLibDescription;
|
var noLibDescription;
|
||||||
if (user['Policy'] && user['Policy']['IsAdministrator']) {
|
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 {
|
} else {
|
||||||
noLibDescription = Globalize.translate("AskAdminToCreateLibrary");
|
noLibDescription = globalize.translate('AskAdminToCreateLibrary');
|
||||||
}
|
}
|
||||||
|
|
||||||
html += '<div class="centerMessage padded-left padded-right">';
|
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 += '<p>' + noLibDescription + '</p>';
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
elem.innerHTML = html;
|
elem.innerHTML = html;
|
||||||
|
|
||||||
var createNowLink = elem.querySelector("#button-createLibrary");
|
var createNowLink = elem.querySelector('#button-createLibrary');
|
||||||
if (createNowLink) {
|
if (createNowLink) {
|
||||||
createNowLink.addEventListener("click", function () {
|
createNowLink.addEventListener('click', function () {
|
||||||
Dashboard.navigate("library.html");
|
Dashboard.navigate('library.html');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||||
} else if (section === 'librarytiles' || section === 'smalllibrarytiles' || section === 'smalllibrarytiles-automobile' || section === 'librarytiles-automobile') {
|
} else if (section === 'librarytiles' || section === 'smalllibrarytiles' || section === 'smalllibrarytiles-automobile' || section === 'librarytiles-automobile') {
|
||||||
loadLibraryTiles(elem, apiClient, user, userSettings, 'smallBackdrop', userViews, allSections);
|
loadLibraryTiles(elem, apiClient, user, userSettings, 'smallBackdrop', userViews, allSections);
|
||||||
} else if (section === 'librarybuttons') {
|
} else if (section === 'librarybuttons') {
|
||||||
loadlibraryButtons(elem, apiClient, user, userSettings, userViews, allSections);
|
loadlibraryButtons(elem, apiClient, user, userSettings, userViews);
|
||||||
} else if (section === 'resume') {
|
} else if (section === 'resume') {
|
||||||
loadResumeVideo(elem, apiClient, userId);
|
loadResumeVideo(elem, apiClient, userId);
|
||||||
} else if (section === 'resumeaudio') {
|
} else if (section === 'resumeaudio') {
|
||||||
|
@ -172,7 +172,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLibraryButtonsHtml(items) {
|
function getLibraryButtonsHtml(items) {
|
||||||
var html = "";
|
var html = '';
|
||||||
|
|
||||||
html += '<div class="verticalSection verticalSection-extrabottompadding">';
|
html += '<div class="verticalSection verticalSection-extrabottompadding">';
|
||||||
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderMyMedia') + '</h2>';
|
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderMyMedia') + '</h2>';
|
||||||
|
@ -183,7 +183,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||||
for (var i = 0, length = items.length; i < length; i++) {
|
for (var i = 0, length = items.length; i < length; i++) {
|
||||||
var item = items[i];
|
var item = items[i];
|
||||||
var icon = imageHelper.getLibraryIcon(item.CollectionType);
|
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>';
|
html += '</div>';
|
||||||
|
@ -229,9 +229,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||||
|
|
||||||
var options = {
|
var options = {
|
||||||
Limit: limit,
|
Limit: limit,
|
||||||
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
|
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo,Path',
|
||||||
ImageTypeLimit: 1,
|
ImageTypeLimit: 1,
|
||||||
EnableImageTypes: "Primary,Backdrop,Thumb",
|
EnableImageTypes: 'Primary,Backdrop,Thumb',
|
||||||
ParentId: parentId
|
ParentId: parentId
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -243,9 +243,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||||
return function (items) {
|
return function (items) {
|
||||||
var cardLayout = false;
|
var cardLayout = false;
|
||||||
var shape;
|
var shape;
|
||||||
if (itemType === 'Channel' || viewType === 'movies' || viewType === 'books') {
|
if (itemType === 'Channel' || viewType === 'movies' || viewType === 'books' || viewType === 'tvshows') {
|
||||||
shape = getPortraitShape();
|
shape = getPortraitShape();
|
||||||
} else if (viewType === 'music') {
|
} else if (viewType === 'music' || viewType === 'homevideos') {
|
||||||
shape = getSquareShape();
|
shape = getSquareShape();
|
||||||
} else {
|
} else {
|
||||||
shape = getThumbShape();
|
shape = getThumbShape();
|
||||||
|
@ -282,7 +282,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||||
html += '<h2 class="sectionTitle sectionTitle-cards">';
|
html += '<h2 class="sectionTitle sectionTitle-cards">';
|
||||||
html += globalize.translate('LatestFromLibrary', parent.Name);
|
html += globalize.translate('LatestFromLibrary', parent.Name);
|
||||||
html += '</h2>';
|
html += '</h2>';
|
||||||
html += '<i class="material-icons chevron_right"></i>';
|
html += '<span class="material-icons chevron_right"></span>';
|
||||||
html += '</a>';
|
html += '</a>';
|
||||||
} else {
|
} else {
|
||||||
html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate('LatestFromLibrary', parent.Name) + '</h2>';
|
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 = {
|
var options = {
|
||||||
Limit: limit,
|
Limit: limit,
|
||||||
Recursive: true,
|
Recursive: true,
|
||||||
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
|
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
|
||||||
ImageTypeLimit: 1,
|
ImageTypeLimit: 1,
|
||||||
EnableImageTypes: "Primary,Backdrop,Thumb",
|
EnableImageTypes: 'Primary,Backdrop,Thumb',
|
||||||
EnableTotalRecordCount: false,
|
EnableTotalRecordCount: false,
|
||||||
MediaTypes: 'Video'
|
MediaTypes: 'Video'
|
||||||
};
|
};
|
||||||
|
@ -459,9 +459,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||||
var options = {
|
var options = {
|
||||||
Limit: limit,
|
Limit: limit,
|
||||||
Recursive: true,
|
Recursive: true,
|
||||||
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
|
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
|
||||||
ImageTypeLimit: 1,
|
ImageTypeLimit: 1,
|
||||||
EnableImageTypes: "Primary,Backdrop,Thumb",
|
EnableImageTypes: 'Primary,Backdrop,Thumb',
|
||||||
EnableTotalRecordCount: false,
|
EnableTotalRecordCount: false,
|
||||||
MediaTypes: 'Audio'
|
MediaTypes: 'Audio'
|
||||||
};
|
};
|
||||||
|
@ -524,9 +524,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||||
IsAiring: true,
|
IsAiring: true,
|
||||||
limit: 24,
|
limit: 24,
|
||||||
ImageTypeLimit: 1,
|
ImageTypeLimit: 1,
|
||||||
EnableImageTypes: "Primary,Thumb,Backdrop",
|
EnableImageTypes: 'Primary,Thumb,Backdrop',
|
||||||
EnableTotalRecordCount: false,
|
EnableTotalRecordCount: false,
|
||||||
Fields: "ChannelInfo,PrimaryImageAspectRatio"
|
Fields: 'ChannelInfo,PrimaryImageAspectRatio'
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -565,9 +565,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||||
IsAiring: true,
|
IsAiring: true,
|
||||||
limit: 1,
|
limit: 1,
|
||||||
ImageTypeLimit: 1,
|
ImageTypeLimit: 1,
|
||||||
EnableImageTypes: "Primary,Thumb,Backdrop",
|
EnableImageTypes: 'Primary,Thumb,Backdrop',
|
||||||
EnableTotalRecordCount: false,
|
EnableTotalRecordCount: false,
|
||||||
Fields: "ChannelInfo,PrimaryImageAspectRatio"
|
Fields: 'ChannelInfo,PrimaryImageAspectRatio'
|
||||||
}).then(function (result) {
|
}).then(function (result) {
|
||||||
var html = '';
|
var html = '';
|
||||||
if (result.Items.length) {
|
if (result.Items.length) {
|
||||||
|
@ -630,7 +630,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||||
html += '<h2 class="sectionTitle sectionTitle-cards">';
|
html += '<h2 class="sectionTitle sectionTitle-cards">';
|
||||||
html += globalize.translate('HeaderOnNow');
|
html += globalize.translate('HeaderOnNow');
|
||||||
html += '</h2>';
|
html += '</h2>';
|
||||||
html += '<i class="material-icons chevron_right"></i>';
|
html += '<span class="material-icons chevron_right"></span>';
|
||||||
html += '</a>';
|
html += '</a>';
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -667,10 +667,10 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||||
var apiClient = connectionManager.getApiClient(serverId);
|
var apiClient = connectionManager.getApiClient(serverId);
|
||||||
return apiClient.getNextUpEpisodes({
|
return apiClient.getNextUpEpisodes({
|
||||||
Limit: enableScrollX() ? 24 : 15,
|
Limit: enableScrollX() ? 24 : 15,
|
||||||
Fields: "PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo",
|
Fields: 'PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo,Path',
|
||||||
UserId: apiClient.getCurrentUserId(),
|
UserId: apiClient.getCurrentUserId(),
|
||||||
ImageTypeLimit: 1,
|
ImageTypeLimit: 1,
|
||||||
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
|
EnableImageTypes: 'Primary,Backdrop,Banner,Thumb',
|
||||||
EnableTotalRecordCount: false
|
EnableTotalRecordCount: false
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -705,7 +705,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||||
html += '<h2 class="sectionTitle sectionTitle-cards">';
|
html += '<h2 class="sectionTitle sectionTitle-cards">';
|
||||||
html += globalize.translate('HeaderNextUp');
|
html += globalize.translate('HeaderNextUp');
|
||||||
html += '</h2>';
|
html += '</h2>';
|
||||||
html += '<i class="material-icons chevron_right"></i>';
|
html += '<span class="material-icons chevron_right"></span>';
|
||||||
html += '</a>';
|
html += '</a>';
|
||||||
} else {
|
} else {
|
||||||
html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate('HeaderNextUp') + '</h2>';
|
html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate('HeaderNextUp') + '</h2>';
|
||||||
|
@ -739,7 +739,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||||
return apiClient.getLiveTvRecordings({
|
return apiClient.getLiveTvRecordings({
|
||||||
userId: apiClient.getCurrentUserId(),
|
userId: apiClient.getCurrentUserId(),
|
||||||
Limit: enableScrollX() ? 12 : 5,
|
Limit: enableScrollX() ? 12 : 5,
|
||||||
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
|
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
|
||||||
EnableTotalRecordCount: false,
|
EnableTotalRecordCount: false,
|
||||||
IsLibraryItem: activeRecordingsOnly ? null : false,
|
IsLibraryItem: activeRecordingsOnly ? null : false,
|
||||||
IsInProgress: activeRecordingsOnly ? true : null
|
IsInProgress: activeRecordingsOnly ? true : null
|
||||||
|
|
|
@ -2,12 +2,12 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function getSavedVolume() {
|
function getSavedVolume() {
|
||||||
return appSettings.get("volume") || 1;
|
return appSettings.get('volume') || 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveVolume(value) {
|
function saveVolume(value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
appSettings.set("volume", value);
|
appSettings.set('volume', value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||||
}
|
}
|
||||||
|
|
||||||
function enableHlsShakaPlayer(item, mediaSource, mediaType) {
|
function enableHlsShakaPlayer(item, mediaSource, mediaType) {
|
||||||
|
/* eslint-disable-next-line compat/compat */
|
||||||
if (!!window.MediaSource && !!MediaSource.isTypeSupported) {
|
if (!!window.MediaSource && !!MediaSource.isTypeSupported) {
|
||||||
|
|
||||||
if (canPlayNativeHls()) {
|
if (canPlayNativeHls()) {
|
||||||
|
@ -109,7 +109,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||||
var now = Date.now();
|
var now = Date.now();
|
||||||
|
|
||||||
if (window.performance && window.performance.now) {
|
if (window.performance && window.performance.now) {
|
||||||
now = performance.now();
|
now = performance.now(); // eslint-disable-line compat/compat
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!recoverDecodingErrorDate || (now - recoverDecodingErrorDate) > 3000) {
|
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;
|
var seconds = (ticks || 0) / 10000000;
|
||||||
|
|
||||||
|
@ -175,9 +175,10 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||||
if (element.duration >= seconds) {
|
if (element.duration >= seconds) {
|
||||||
// media is ready, seek immediately
|
// media is ready, seek immediately
|
||||||
setCurrentTimeIfNeeded(element, seconds);
|
setCurrentTimeIfNeeded(element, seconds);
|
||||||
|
if (onMediaReady) onMediaReady();
|
||||||
} else {
|
} else {
|
||||||
// update video player position when media is ready to be sought
|
// 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) {
|
var onMediaChange = function(e) {
|
||||||
if (element.currentTime === 0 && element.duration >= seconds) {
|
if (element.currentTime === 0 && element.duration >= seconds) {
|
||||||
// seek only when video position is exactly zero,
|
// seek only when video position is exactly zero,
|
||||||
|
@ -189,10 +190,11 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||||
events.map(function(name) {
|
events.map(function(name) {
|
||||||
element.removeEventListener(name, onMediaChange);
|
element.removeEventListener(name, onMediaChange);
|
||||||
});
|
});
|
||||||
|
if (onMediaReady) onMediaReady();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
events.map(function (name) {
|
events.map(function (name) {
|
||||||
element.addEventListener(name, onMediaChange);
|
return element.addEventListener(name, onMediaChange);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -371,13 +373,13 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||||
onErrorInternal(instance, 'network');
|
onErrorInternal(instance, 'network');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.debug("fatal network error encountered, try to recover");
|
console.debug('fatal network error encountered, try to recover');
|
||||||
hls.startLoad();
|
hls.startLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case Hls.ErrorTypes.MEDIA_ERROR:
|
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;
|
var currentReject = reject;
|
||||||
reject = null;
|
reject = null;
|
||||||
handleHlsJsMediaError(instance, currentReject);
|
handleHlsJsMediaError(instance, currentReject);
|
||||||
|
@ -407,7 +409,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||||
|
|
||||||
elem.src = '';
|
elem.src = '';
|
||||||
elem.innerHTML = '';
|
elem.innerHTML = '';
|
||||||
elem.removeAttribute("src");
|
elem.removeAttribute('src');
|
||||||
|
|
||||||
destroyHlsPlayer(instance);
|
destroyHlsPlayer(instance);
|
||||||
destroyFlvPlayer(instance);
|
destroyFlvPlayer(instance);
|
||||||
|
|
|
@ -109,15 +109,15 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||||
html += '<span style="margin-right: 10px;">';
|
html += '<span style="margin-right: 10px;">';
|
||||||
|
|
||||||
var startAtDisplay = totalRecordCount ? startIndex + 1 : 0;
|
var startAtDisplay = totalRecordCount ? startIndex + 1 : 0;
|
||||||
html += globalize.translate("ListPaging", startAtDisplay, recordsEnd, totalRecordCount);
|
html += globalize.translate('ListPaging', startAtDisplay, recordsEnd, totalRecordCount);
|
||||||
|
|
||||||
html += '</span>';
|
html += '</span>';
|
||||||
|
|
||||||
if (showControls) {
|
if (showControls) {
|
||||||
html += '<div data-role="controlgroup" data-type="horizontal" style="display:inline-block;">';
|
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('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' : '') + '><i class="material-icons arrow_forward"></i></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>';
|
html += '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDisplayUrl(url, apiClient) {
|
function getDisplayUrl(url, apiClient) {
|
||||||
return apiClient.getUrl("Images/Remote", { imageUrl: url });
|
return apiClient.getUrl('Images/Remote', { imageUrl: url });
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRemoteImageHtml(image, imageType, apiClient) {
|
function getRemoteImageHtml(image, imageType, apiClient) {
|
||||||
|
@ -155,21 +155,21 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||||
|
|
||||||
var html = '';
|
var html = '';
|
||||||
|
|
||||||
var cssClass = "card scalableCard imageEditorCard";
|
var cssClass = 'card scalableCard imageEditorCard';
|
||||||
var cardBoxCssClass = 'cardBox visualCardBox';
|
var cardBoxCssClass = 'cardBox visualCardBox';
|
||||||
|
|
||||||
var shape = 'backdrop';
|
var shape = 'backdrop';
|
||||||
if (imageType === "Backdrop" || imageType === "Art" || imageType === "Thumb" || imageType === "Logo") {
|
if (imageType === 'Backdrop' || imageType === 'Art' || imageType === 'Thumb' || imageType === 'Logo') {
|
||||||
shape = 'backdrop';
|
shape = 'backdrop';
|
||||||
} else if (imageType === "Banner") {
|
} else if (imageType === 'Banner') {
|
||||||
shape = 'banner';
|
shape = 'banner';
|
||||||
} else if (imageType === "Disc") {
|
} else if (imageType === 'Disc') {
|
||||||
shape = 'square';
|
shape = 'square';
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (currentItemType === "Episode") {
|
if (currentItemType === 'Episode') {
|
||||||
shape = 'backdrop';
|
shape = 'backdrop';
|
||||||
} else if (currentItemType === "MusicAlbum" || currentItemType === "MusicArtist") {
|
} else if (currentItemType === 'MusicAlbum' || currentItemType === 'MusicArtist') {
|
||||||
shape = 'square';
|
shape = 'square';
|
||||||
} else {
|
} else {
|
||||||
shape = 'portrait';
|
shape = 'portrait';
|
||||||
|
@ -203,9 +203,9 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||||
html += '<div class="cardContent">';
|
html += '<div class="cardContent">';
|
||||||
|
|
||||||
if (layoutManager.tv || !appHost.supports('externallinks')) {
|
if (layoutManager.tv || !appHost.supports('externallinks')) {
|
||||||
html += '<div class="cardImageContainer lazy" data-src="' + getDisplayUrl(image.Url, apiClient) + '" style="background-position:center bottom;"></div>';
|
html += '<div class="cardImageContainer lazy" data-src="' + getDisplayUrl(image.Url, apiClient) + '" style="background-position:center center;background-size:contain;"></div>';
|
||||||
} else {
|
} else {
|
||||||
html += '<a is="emby-linkbutton" target="_blank" href="' + getDisplayUrl(image.Url, apiClient) + '" class="button-link cardImageContainer lazy" data-src="' + getDisplayUrl(image.Url, apiClient) + '" style="background-position:center bottom;"></a>';
|
html += '<a is="emby-linkbutton" target="_blank" href="' + getDisplayUrl(image.Url, apiClient) + '" class="button-link cardImageContainer lazy" data-src="' + getDisplayUrl(image.Url, apiClient) + '" style="background-position:center center;background-size:contain"></a>';
|
||||||
}
|
}
|
||||||
|
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
@ -241,18 +241,18 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||||
|
|
||||||
html += '<div class="cardText cardText-secondary cardTextCentered">';
|
html += '<div class="cardText cardText-secondary cardTextCentered">';
|
||||||
|
|
||||||
if (image.RatingType === "Likes") {
|
if (image.RatingType === 'Likes') {
|
||||||
html += image.CommunityRating + (image.CommunityRating === 1 ? " like" : " likes");
|
html += image.CommunityRating + (image.CommunityRating === 1 ? ' like' : ' likes');
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (image.CommunityRating) {
|
if (image.CommunityRating) {
|
||||||
html += image.CommunityRating.toFixed(1);
|
html += image.CommunityRating.toFixed(1);
|
||||||
|
|
||||||
if (image.VoteCount) {
|
if (image.VoteCount) {
|
||||||
html += ' • ' + image.VoteCount + (image.VoteCount === 1 ? " vote" : " votes");
|
html += ' • ' + image.VoteCount + (image.VoteCount === 1 ? ' vote' : ' votes');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
html += "Unrated";
|
html += 'Unrated';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +262,7 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||||
if (enableFooterButtons) {
|
if (enableFooterButtons) {
|
||||||
html += '<div class="cardText cardTextCentered">';
|
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>';
|
html += '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,7 +320,7 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||||
function showEditor(itemId, serverId, itemType) {
|
function showEditor(itemId, serverId, itemType) {
|
||||||
loading.show();
|
loading.show();
|
||||||
|
|
||||||
require(['text!./imagedownloader.template.html'], function (template) {
|
require(['text!./imageDownloader.template.html'], function (template) {
|
||||||
|
|
||||||
var apiClient = connectionManager.getApiClient(serverId);
|
var apiClient = connectionManager.getApiClient(serverId);
|
||||||
|
|
||||||
|
@ -334,7 +334,7 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||||
if (layoutManager.tv) {
|
if (layoutManager.tv) {
|
||||||
dialogOptions.size = 'fullscreen';
|
dialogOptions.size = 'fullscreen';
|
||||||
} else {
|
} else {
|
||||||
dialogOptions.size = 'fullscreen-border';
|
dialogOptions.size = 'small';
|
||||||
}
|
}
|
||||||
|
|
||||||
var dlg = dialogHelper.createDialog(dialogOptions);
|
var dlg = dialogHelper.createDialog(dialogOptions);
|
|
@ -1,11 +1,11 @@
|
||||||
<div class="formDialogHeader">
|
<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">
|
<h3 class="formDialogHeaderTitle">
|
||||||
${Search}
|
${Search}
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="formDialogContent">
|
<div class="formDialogContent smoothScrollY">
|
||||||
<div class="dialogContentInner">
|
<div class="dialogContentInner">
|
||||||
<div class="flex align-items-center justify-content-center flex-wrap-wrap" style="margin: 2em 0;">
|
<div class="flex align-items-center justify-content-center flex-wrap-wrap" style="margin: 2em 0;">
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
define(["globalize", "dom", "dialogHelper", "emby-checkbox", "emby-select", "emby-input"], function (globalize, dom, dialogHelper) {
|
define(['globalize', 'dom', 'dialogHelper', 'emby-checkbox', 'emby-select', 'emby-input'], function (globalize, dom, dialogHelper) {
|
||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
function getDefaultImageConfig(itemType, type) {
|
function getDefaultImageConfig(itemType, type) {
|
||||||
return {
|
return {
|
||||||
Type: type,
|
Type: type,
|
||||||
MinWidth: 0,
|
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) {
|
function setVisibilityOfBackdrops(elem, visible) {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
elem.classList.remove("hide");
|
elem.classList.remove('hide');
|
||||||
elem.querySelector("input").setAttribute("required", "required");
|
elem.querySelector('input').setAttribute('required', 'required');
|
||||||
} else {
|
} else {
|
||||||
elem.classList.add("hide");
|
elem.classList.add('hide');
|
||||||
elem.querySelector("input").setAttribute("required", "");
|
elem.querySelector('input').setAttribute('required', '');
|
||||||
elem.querySelector("input").removeAttribute("required");
|
elem.querySelector('input').removeAttribute('required');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadValues(context, itemType, options, availableOptions) {
|
function loadValues(context, itemType, options, availableOptions) {
|
||||||
var supportedImageTypes = availableOptions.SupportedImageTypes || [];
|
var supportedImageTypes = availableOptions.SupportedImageTypes || [];
|
||||||
setVisibilityOfBackdrops(context.querySelector(".backdropFields"), -1 != supportedImageTypes.indexOf("Backdrop"));
|
setVisibilityOfBackdrops(context.querySelector('.backdropFields'), -1 != supportedImageTypes.indexOf('Backdrop'));
|
||||||
setVisibilityOfBackdrops(context.querySelector(".screenshotFields"), -1 != supportedImageTypes.indexOf("Screenshot"));
|
setVisibilityOfBackdrops(context.querySelector('.screenshotFields'), -1 != supportedImageTypes.indexOf('Screenshot'));
|
||||||
Array.prototype.forEach.call(context.querySelectorAll(".imageType"), function (i) {
|
Array.prototype.forEach.call(context.querySelectorAll('.imageType'), function (i) {
|
||||||
var imageType = i.getAttribute("data-imagetype");
|
var imageType = i.getAttribute('data-imagetype');
|
||||||
var container = dom.parentWithTag(i, "LABEL");
|
var container = dom.parentWithTag(i, 'LABEL');
|
||||||
|
|
||||||
if (-1 == supportedImageTypes.indexOf(imageType)) {
|
if (-1 == supportedImageTypes.indexOf(imageType)) {
|
||||||
container.classList.add("hide");
|
container.classList.add('hide');
|
||||||
} else {
|
} else {
|
||||||
container.classList.remove("hide");
|
container.classList.remove('hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getImageConfig(options, availableOptions, imageType, itemType).Limit) {
|
if (getImageConfig(options, availableOptions, imageType, itemType).Limit) {
|
||||||
|
@ -50,31 +50,31 @@ define(["globalize", "dom", "dialogHelper", "emby-checkbox", "emby-select", "emb
|
||||||
i.checked = false;
|
i.checked = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var backdropConfig = getImageConfig(options, availableOptions, "Backdrop", itemType);
|
var backdropConfig = getImageConfig(options, availableOptions, 'Backdrop', itemType);
|
||||||
context.querySelector("#txtMaxBackdrops").value = backdropConfig.Limit;
|
context.querySelector('#txtMaxBackdrops').value = backdropConfig.Limit;
|
||||||
context.querySelector("#txtMinBackdropDownloadWidth").value = backdropConfig.MinWidth;
|
context.querySelector('#txtMinBackdropDownloadWidth').value = backdropConfig.MinWidth;
|
||||||
var screenshotConfig = getImageConfig(options, availableOptions, "Screenshot", itemType);
|
var screenshotConfig = getImageConfig(options, availableOptions, 'Screenshot', itemType);
|
||||||
context.querySelector("#txtMaxScreenshots").value = screenshotConfig.Limit;
|
context.querySelector('#txtMaxScreenshots').value = screenshotConfig.Limit;
|
||||||
context.querySelector("#txtMinScreenshotDownloadWidth").value = screenshotConfig.MinWidth;
|
context.querySelector('#txtMinScreenshotDownloadWidth').value = screenshotConfig.MinWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveValues(context, options) {
|
function saveValues(context, options) {
|
||||||
options.ImageOptions = Array.prototype.map.call(context.querySelectorAll(".imageType:not(.hide)"), function (c) {
|
options.ImageOptions = Array.prototype.map.call(context.querySelectorAll('.imageType:not(.hide)'), function (c) {
|
||||||
return {
|
return {
|
||||||
Type: c.getAttribute("data-imagetype"),
|
Type: c.getAttribute('data-imagetype'),
|
||||||
Limit: c.checked ? 1 : 0,
|
Limit: c.checked ? 1 : 0,
|
||||||
MinWidth: 0
|
MinWidth: 0
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
options.ImageOptions.push({
|
options.ImageOptions.push({
|
||||||
Type: "Backdrop",
|
Type: 'Backdrop',
|
||||||
Limit: context.querySelector("#txtMaxBackdrops").value,
|
Limit: context.querySelector('#txtMaxBackdrops').value,
|
||||||
MinWidth: context.querySelector("#txtMinBackdropDownloadWidth").value
|
MinWidth: context.querySelector('#txtMinBackdropDownloadWidth').value
|
||||||
});
|
});
|
||||||
options.ImageOptions.push({
|
options.ImageOptions.push({
|
||||||
Type: "Screenshot",
|
Type: 'Screenshot',
|
||||||
Limit: context.querySelector("#txtMaxScreenshots").value,
|
Limit: context.querySelector('#txtMaxScreenshots').value,
|
||||||
MinWidth: context.querySelector("#txtMinScreenshotDownloadWidth").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) {
|
this.show = function (itemType, options, availableOptions) {
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
var xhr = new XMLHttpRequest();
|
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) {
|
xhr.onload = function (e) {
|
||||||
var template = this.response;
|
var template = this.response;
|
||||||
var dlg = dialogHelper.createDialog({
|
var dlg = dialogHelper.createDialog({
|
||||||
size: "medium-tall",
|
size: 'small',
|
||||||
removeOnClose: true,
|
removeOnClose: true,
|
||||||
scrollY: false
|
scrollY: false
|
||||||
});
|
});
|
||||||
dlg.classList.add("formDialog");
|
dlg.classList.add('formDialog');
|
||||||
dlg.innerHTML = globalize.translateDocument(template);
|
dlg.innerHTML = globalize.translateDocument(template);
|
||||||
dlg.addEventListener("close", function () {
|
dlg.addEventListener('close', function () {
|
||||||
saveValues(dlg, options);
|
saveValues(dlg, options);
|
||||||
});
|
});
|
||||||
loadValues(dlg, itemType, options, availableOptions);
|
loadValues(dlg, itemType, options, availableOptions);
|
||||||
dialogHelper.open(dlg).then(resolve, resolve);
|
dialogHelper.open(dlg).then(resolve, resolve);
|
||||||
dlg.querySelector(".btnCancel").addEventListener("click", function () {
|
dlg.querySelector('.btnCancel').addEventListener('click', function () {
|
||||||
dialogHelper.close(dlg);
|
dialogHelper.close(dlg);
|
||||||
});
|
});
|
||||||
};
|
};
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue