Merge branch 'master' into master
|
@ -2,48 +2,80 @@ trigger:
|
||||||
batch: true
|
batch: true
|
||||||
branches:
|
branches:
|
||||||
include:
|
include:
|
||||||
- master
|
- '*'
|
||||||
- release-*
|
|
||||||
tags:
|
tags:
|
||||||
include:
|
include:
|
||||||
- '*'
|
- '*'
|
||||||
|
pr:
|
||||||
|
branches:
|
||||||
|
include:
|
||||||
|
- '*'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
- job: main_build
|
- job: Build
|
||||||
displayName: 'Main Build'
|
displayName: 'Build'
|
||||||
|
|
||||||
dependsOn: lint
|
strategy:
|
||||||
condition: succeeded()
|
matrix:
|
||||||
|
Development:
|
||||||
|
BuildConfiguration: development
|
||||||
|
Production:
|
||||||
|
BuildConfiguration: production
|
||||||
|
Standalone:
|
||||||
|
BuildConfiguration: standalone
|
||||||
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'ubuntu-latest'
|
vmImage: 'ubuntu-latest'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- task: NodeTool@0
|
- task: NodeTool@0
|
||||||
displayName: 'Install Node.js'
|
displayName: 'Install Node'
|
||||||
inputs:
|
inputs:
|
||||||
versionSpec: '10.x'
|
versionSpec: '12.x'
|
||||||
|
|
||||||
- script: |
|
- task: Cache@2
|
||||||
yarn install
|
displayName: 'Check Cache'
|
||||||
displayName: 'Install dependencies'
|
inputs:
|
||||||
|
key: 'yarn | yarn.lock'
|
||||||
|
path: 'node_modules'
|
||||||
|
cacheHitVar: CACHE_RESTORED
|
||||||
|
|
||||||
- script: |
|
- script: 'yarn install --frozen-lockfile'
|
||||||
test -d dist
|
displayName: 'Install Dependencies'
|
||||||
displayName: 'Check dist directory'
|
condition: ne(variables.CACHE_RESTORED, 'true')
|
||||||
|
|
||||||
- script: |
|
- script: 'yarn build:development'
|
||||||
yarn pack --filename jellyfin-web.tgz
|
displayName: 'Build Development'
|
||||||
displayName: 'Build package'
|
condition: eq(variables['BuildConfiguration'], 'development')
|
||||||
|
|
||||||
|
- script: 'yarn build:production'
|
||||||
|
displayName: 'Build Bundle'
|
||||||
|
condition: eq(variables['BuildConfiguration'], 'production')
|
||||||
|
|
||||||
|
- script: 'yarn build:standalone'
|
||||||
|
displayName: 'Build Standalone'
|
||||||
|
condition: eq(variables['BuildConfiguration'], 'standalone')
|
||||||
|
|
||||||
|
- script: 'test -d dist'
|
||||||
|
displayName: 'Check Build'
|
||||||
|
|
||||||
|
- script: 'mv dist jellyfin-web'
|
||||||
|
displayName: 'Rename Directory'
|
||||||
|
|
||||||
|
- task: ArchiveFiles@2
|
||||||
|
displayName: 'Archive Directory'
|
||||||
|
inputs:
|
||||||
|
rootFolderOrFile: 'jellyfin-web'
|
||||||
|
includeRootFolder: true
|
||||||
|
archiveFile: 'jellyfin-web-$(BuildConfiguration)'
|
||||||
|
|
||||||
- task: PublishPipelineArtifact@1
|
- task: PublishPipelineArtifact@1
|
||||||
displayName: 'Publish package'
|
displayName: 'Publish Release'
|
||||||
condition: succeeded()
|
|
||||||
inputs:
|
inputs:
|
||||||
targetPath: '$(Build.SourcesDirectory)/jellyfin-web.tgz'
|
targetPath: '$(Build.SourcesDirectory)/jellyfin-web-$(BuildConfiguration).zip'
|
||||||
artifactName: 'jellyfin-web'
|
artifactName: 'jellyfin-web-$(BuildConfiguration)'
|
||||||
|
|
||||||
- job: lint
|
- job: Lint
|
||||||
displayName: 'Lint'
|
displayName: 'Lint'
|
||||||
|
|
||||||
pool:
|
pool:
|
||||||
|
@ -51,14 +83,23 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- task: NodeTool@0
|
- task: NodeTool@0
|
||||||
displayName: 'Install Node.js'
|
displayName: 'Install Node'
|
||||||
inputs:
|
inputs:
|
||||||
versionSpec: '10.x'
|
versionSpec: '12.x'
|
||||||
|
|
||||||
- script: |
|
- task: Cache@2
|
||||||
yarn install
|
displayName: 'Check Cache'
|
||||||
displayName: 'Install dependencies'
|
inputs:
|
||||||
|
key: 'yarn | yarn.lock'
|
||||||
|
path: 'node_modules'
|
||||||
|
cacheHitVar: CACHE_RESTORED
|
||||||
|
|
||||||
- script: |
|
- script: 'yarn install --frozen-lockfile'
|
||||||
yarn run lint
|
displayName: 'Install Dependencies'
|
||||||
|
condition: ne(variables.CACHE_RESTORED, 'true')
|
||||||
|
|
||||||
|
- script: 'yarn run lint --quiet'
|
||||||
displayName: 'Run ESLint'
|
displayName: 'Run ESLint'
|
||||||
|
|
||||||
|
- script: 'yarn run stylelint'
|
||||||
|
displayName: 'Run Stylelint'
|
||||||
|
|
1
.copr/Makefile
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../fedora/Makefile
|
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
|
||||||
|
|
193
.eslintrc.js
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
plugins: [
|
||||||
|
'promise',
|
||||||
|
'import',
|
||||||
|
'eslint-comments'
|
||||||
|
],
|
||||||
|
env: {
|
||||||
|
node: true,
|
||||||
|
es6: true,
|
||||||
|
es2017: true,
|
||||||
|
es2020: true
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 2020,
|
||||||
|
sourceType: 'module',
|
||||||
|
ecmaFeatures: {
|
||||||
|
impliedStrict: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
'eslint:recommended',
|
||||||
|
// 'plugin:promise/recommended',
|
||||||
|
'plugin:import/errors',
|
||||||
|
'plugin:import/warnings',
|
||||||
|
'plugin:eslint-comments/recommended',
|
||||||
|
'plugin:compat/recommended'
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
'block-spacing': ["error"],
|
||||||
|
'brace-style': ["error"],
|
||||||
|
'comma-dangle': ["error", "never"],
|
||||||
|
'comma-spacing': ["error"],
|
||||||
|
'eol-last': ["error"],
|
||||||
|
'indent': ["error", 4, { "SwitchCase": 1 }],
|
||||||
|
'keyword-spacing': ["error"],
|
||||||
|
'max-statements-per-line': ["error"],
|
||||||
|
'no-floating-decimal': ["error"],
|
||||||
|
'no-multi-spaces': ["error"],
|
||||||
|
'no-multiple-empty-lines': ["error", { "max": 1 }],
|
||||||
|
'no-trailing-spaces': ["error"],
|
||||||
|
'one-var': ["error", "never"],
|
||||||
|
'quotes': ["error", "single", { "avoidEscape": true, "allowTemplateLiterals": false }],
|
||||||
|
'semi': ["error"],
|
||||||
|
'space-before-blocks': ["error"]
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: [
|
||||||
|
'./src/**/*.js'
|
||||||
|
],
|
||||||
|
env: {
|
||||||
|
node: false,
|
||||||
|
amd: true,
|
||||||
|
browser: true,
|
||||||
|
es6: true,
|
||||||
|
es2017: true,
|
||||||
|
es2020: true
|
||||||
|
},
|
||||||
|
globals: {
|
||||||
|
// Browser globals
|
||||||
|
'MediaMetadata': 'readonly',
|
||||||
|
// Tizen globals
|
||||||
|
'tizen': 'readonly',
|
||||||
|
'webapis': 'readonly',
|
||||||
|
// WebOS globals
|
||||||
|
'webOS': 'readonly',
|
||||||
|
// Dependency globals
|
||||||
|
'$': 'readonly',
|
||||||
|
'jQuery': 'readonly',
|
||||||
|
'requirejs': 'readonly',
|
||||||
|
// Jellyfin globals
|
||||||
|
'ApiClient': 'writable',
|
||||||
|
'AppInfo': 'writable',
|
||||||
|
'chrome': 'writable',
|
||||||
|
'ConnectionManager': 'writable',
|
||||||
|
'DlnaProfilePage': 'writable',
|
||||||
|
'Dashboard': 'writable',
|
||||||
|
'DashboardPage': 'writable',
|
||||||
|
'Emby': 'readonly',
|
||||||
|
'Events': 'writable',
|
||||||
|
'getParameterByName': 'writable',
|
||||||
|
'getWindowLocationSearch': 'writable',
|
||||||
|
'Globalize': 'writable',
|
||||||
|
'Hls': 'writable',
|
||||||
|
'dfnshelper': 'writable',
|
||||||
|
'LibraryMenu': 'writable',
|
||||||
|
'LinkParser': 'writable',
|
||||||
|
'LiveTvHelpers': 'writable',
|
||||||
|
'MetadataEditor': 'writable',
|
||||||
|
'pageClassOn': 'writable',
|
||||||
|
'pageIdOn': 'writable',
|
||||||
|
'PlaylistViewer': 'writable',
|
||||||
|
'UserParentalControlPage': 'writable',
|
||||||
|
'Windows': 'readonly'
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
// TODO: Fix warnings and remove these rules
|
||||||
|
'no-redeclare': ["warn"],
|
||||||
|
'no-unused-vars': ["warn"],
|
||||||
|
'no-useless-escape': ["warn"],
|
||||||
|
// TODO: Remove after ES6 migration is complete
|
||||||
|
'import/no-unresolved': ["off"]
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
polyfills: [
|
||||||
|
// Native Promises Only
|
||||||
|
'Promise',
|
||||||
|
// whatwg-fetch
|
||||||
|
'fetch',
|
||||||
|
// document-register-element
|
||||||
|
'document.registerElement',
|
||||||
|
// resize-observer-polyfill
|
||||||
|
'ResizeObserver',
|
||||||
|
// fast-text-encoding
|
||||||
|
'TextEncoder',
|
||||||
|
// intersection-observer
|
||||||
|
'IntersectionObserver',
|
||||||
|
// Core-js
|
||||||
|
'Object.assign',
|
||||||
|
'Object.is',
|
||||||
|
'Object.setPrototypeOf',
|
||||||
|
'Object.toString',
|
||||||
|
'Object.freeze',
|
||||||
|
'Object.seal',
|
||||||
|
'Object.preventExtensions',
|
||||||
|
'Object.isFrozen',
|
||||||
|
'Object.isSealed',
|
||||||
|
'Object.isExtensible',
|
||||||
|
'Object.getOwnPropertyDescriptor',
|
||||||
|
'Object.getPrototypeOf',
|
||||||
|
'Object.keys',
|
||||||
|
'Object.getOwnPropertyNames',
|
||||||
|
'Function.name',
|
||||||
|
'Function.hasInstance',
|
||||||
|
'Array.from',
|
||||||
|
'Array.arrayOf',
|
||||||
|
'Array.copyWithin',
|
||||||
|
'Array.fill',
|
||||||
|
'Array.find',
|
||||||
|
'Array.findIndex',
|
||||||
|
'Array.iterator',
|
||||||
|
'String.fromCodePoint',
|
||||||
|
'String.raw',
|
||||||
|
'String.iterator',
|
||||||
|
'String.codePointAt',
|
||||||
|
'String.endsWith',
|
||||||
|
'String.includes',
|
||||||
|
'String.repeat',
|
||||||
|
'String.startsWith',
|
||||||
|
'String.trim',
|
||||||
|
'String.anchor',
|
||||||
|
'String.big',
|
||||||
|
'String.blink',
|
||||||
|
'String.bold',
|
||||||
|
'String.fixed',
|
||||||
|
'String.fontcolor',
|
||||||
|
'String.fontsize',
|
||||||
|
'String.italics',
|
||||||
|
'String.link',
|
||||||
|
'String.small',
|
||||||
|
'String.strike',
|
||||||
|
'String.sub',
|
||||||
|
'String.sup',
|
||||||
|
'RegExp',
|
||||||
|
'Number',
|
||||||
|
'Math',
|
||||||
|
'Date',
|
||||||
|
'async',
|
||||||
|
'Symbol',
|
||||||
|
'Map',
|
||||||
|
'Set',
|
||||||
|
'WeakMap',
|
||||||
|
'WeakSet',
|
||||||
|
'ArrayBuffer',
|
||||||
|
'DataView',
|
||||||
|
'Int8Array',
|
||||||
|
'Uint8Array',
|
||||||
|
'Uint8ClampedArray',
|
||||||
|
'Int16Array',
|
||||||
|
'Uint16Array',
|
||||||
|
'Int32Array',
|
||||||
|
'Uint32Array',
|
||||||
|
'Float32Array',
|
||||||
|
'Float64Array',
|
||||||
|
'Reflect',
|
||||||
|
// Temporary while eslint-compat-plugin is buggy
|
||||||
|
'document.querySelector'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,27 +0,0 @@
|
||||||
env:
|
|
||||||
es6: true
|
|
||||||
browser: true
|
|
||||||
amd: true
|
|
||||||
|
|
||||||
rules:
|
|
||||||
block-spacing: ["error"]
|
|
||||||
brace-style: ["error"]
|
|
||||||
comma-dangle: ["error", "never"]
|
|
||||||
comma-spacing: ["error"]
|
|
||||||
eol-last: ["off"]
|
|
||||||
indent: ["error", 4, { "SwitchCase": 1 }]
|
|
||||||
keyword-spacing: ["error"]
|
|
||||||
line-comment-position: ["off"]
|
|
||||||
max-statements-per-line: ["error"]
|
|
||||||
no-empty: ["error"]
|
|
||||||
no-extra-semi: ["error"]
|
|
||||||
no-floating-decimal: ["error"]
|
|
||||||
no-multi-spaces: ["error"]
|
|
||||||
no-multiple-empty-lines: ["error", { "max": 1 }]
|
|
||||||
no-trailing-spaces: ["error"]
|
|
||||||
no-void: ["off"]
|
|
||||||
one-var: ["error", "never"]
|
|
||||||
padding-line-between-statements: ["off"]
|
|
||||||
semi: ["off"]
|
|
||||||
space-before-blocks: ["error"]
|
|
||||||
yoda: ["off"]
|
|
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
|
@ -0,0 +1,4 @@
|
||||||
|
.ci @dkanada @EraYaN
|
||||||
|
.github @jellyfin/core
|
||||||
|
build.sh @joshuaboniface
|
||||||
|
deployment @joshuaboniface
|
585
.gitignore
vendored
|
@ -1,578 +1,11 @@
|
||||||
|
# config
|
||||||
|
config.json
|
||||||
|
|
||||||
# Created by https://www.gitignore.io/api/node,rider,macos,linux,windows,visualstudio,visualstudiocode
|
# npm
|
||||||
# Edit at https://www.gitignore.io/?templates=node,rider,macos,linux,windows,visualstudio,visualstudiocode
|
|
||||||
|
|
||||||
### Linux ###
|
|
||||||
*~
|
|
||||||
|
|
||||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
|
||||||
.fuse_hidden*
|
|
||||||
|
|
||||||
# KDE directory preferences
|
|
||||||
.directory
|
|
||||||
|
|
||||||
# Linux trash folder which might appear on any partition or disk
|
|
||||||
.Trash-*
|
|
||||||
|
|
||||||
# .nfs files are created when an open file is removed but is still being accessed
|
|
||||||
.nfs*
|
|
||||||
|
|
||||||
### macOS ###
|
|
||||||
# General
|
|
||||||
.DS_Store
|
|
||||||
.AppleDouble
|
|
||||||
.LSOverride
|
|
||||||
|
|
||||||
# Icon must end with two \r
|
|
||||||
Icon
|
|
||||||
|
|
||||||
# Thumbnails
|
|
||||||
._*
|
|
||||||
|
|
||||||
# Files that might appear in the root of a volume
|
|
||||||
.DocumentRevisions-V100
|
|
||||||
.fseventsd
|
|
||||||
.Spotlight-V100
|
|
||||||
.TemporaryItems
|
|
||||||
.Trashes
|
|
||||||
.VolumeIcon.icns
|
|
||||||
.com.apple.timemachine.donotpresent
|
|
||||||
|
|
||||||
# Directories potentially created on remote AFP share
|
|
||||||
.AppleDB
|
|
||||||
.AppleDesktop
|
|
||||||
Network Trash Folder
|
|
||||||
Temporary Items
|
|
||||||
.apdisk
|
|
||||||
|
|
||||||
### Node ###
|
|
||||||
# Logs
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
|
|
||||||
# Runtime data
|
|
||||||
pids
|
|
||||||
*.pid
|
|
||||||
*.seed
|
|
||||||
*.pid.lock
|
|
||||||
|
|
||||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
||||||
lib-cov
|
|
||||||
|
|
||||||
# Coverage directory used by tools like istanbul
|
|
||||||
coverage
|
|
||||||
|
|
||||||
# nyc test coverage
|
|
||||||
.nyc_output
|
|
||||||
|
|
||||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
|
||||||
.grunt
|
|
||||||
|
|
||||||
# node-waf configuration
|
|
||||||
.lock-wscript
|
|
||||||
|
|
||||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
|
||||||
build/Release
|
|
||||||
|
|
||||||
# Dependency directories
|
|
||||||
node_modules/
|
|
||||||
jspm_packages/
|
|
||||||
|
|
||||||
# Dependency lockfile
|
|
||||||
package-lock.json
|
|
||||||
|
|
||||||
# TypeScript v1 declaration files
|
|
||||||
typings/
|
|
||||||
|
|
||||||
# Optional npm cache directory
|
|
||||||
.npm
|
|
||||||
|
|
||||||
# Optional eslint cache
|
|
||||||
.eslintcache
|
|
||||||
|
|
||||||
# Optional REPL history
|
|
||||||
.node_repl_history
|
|
||||||
|
|
||||||
# Output of 'npm pack'
|
|
||||||
*.tgz
|
|
||||||
|
|
||||||
# Yarn Integrity file
|
|
||||||
.yarn-integrity
|
|
||||||
|
|
||||||
# dotenv environment variables file
|
|
||||||
.env
|
|
||||||
.env.test
|
|
||||||
|
|
||||||
# parcel-bundler cache (https://parceljs.org/)
|
|
||||||
.cache
|
|
||||||
|
|
||||||
# next.js build output
|
|
||||||
.next
|
|
||||||
|
|
||||||
# nuxt.js build output
|
|
||||||
.nuxt
|
|
||||||
|
|
||||||
# vuepress build output
|
|
||||||
.vuepress/dist
|
|
||||||
|
|
||||||
# Serverless directories
|
|
||||||
.serverless/
|
|
||||||
|
|
||||||
# FuseBox cache
|
|
||||||
.fusebox/
|
|
||||||
|
|
||||||
# DynamoDB Local files
|
|
||||||
.dynamodb/
|
|
||||||
|
|
||||||
### Rider ###
|
|
||||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
|
|
||||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
|
||||||
|
|
||||||
# User-specific stuff
|
|
||||||
.idea/**/workspace.xml
|
|
||||||
.idea/**/tasks.xml
|
|
||||||
.idea/**/usage.statistics.xml
|
|
||||||
.idea/**/dictionaries
|
|
||||||
.idea/**/shelf
|
|
||||||
|
|
||||||
# Generated files
|
|
||||||
.idea/**/contentModel.xml
|
|
||||||
|
|
||||||
# Sensitive or high-churn files
|
|
||||||
.idea/**/dataSources/
|
|
||||||
.idea/**/dataSources.ids
|
|
||||||
.idea/**/dataSources.local.xml
|
|
||||||
.idea/**/sqlDataSources.xml
|
|
||||||
.idea/**/dynamic.xml
|
|
||||||
.idea/**/uiDesigner.xml
|
|
||||||
.idea/**/dbnavigator.xml
|
|
||||||
|
|
||||||
# Gradle
|
|
||||||
.idea/**/gradle.xml
|
|
||||||
.idea/**/libraries
|
|
||||||
|
|
||||||
# Gradle and Maven with auto-import
|
|
||||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
|
||||||
# since they will be recreated, and may cause churn. Uncomment if using
|
|
||||||
# auto-import.
|
|
||||||
# .idea/modules.xml
|
|
||||||
# .idea/*.iml
|
|
||||||
# .idea/modules
|
|
||||||
|
|
||||||
# CMake
|
|
||||||
cmake-build-*/
|
|
||||||
|
|
||||||
# Mongo Explorer plugin
|
|
||||||
.idea/**/mongoSettings.xml
|
|
||||||
|
|
||||||
# File-based project format
|
|
||||||
*.iws
|
|
||||||
|
|
||||||
# IntelliJ
|
|
||||||
out/
|
|
||||||
|
|
||||||
# mpeltonen/sbt-idea plugin
|
|
||||||
.idea_modules/
|
|
||||||
|
|
||||||
# JIRA plugin
|
|
||||||
atlassian-ide-plugin.xml
|
|
||||||
|
|
||||||
# Cursive Clojure plugin
|
|
||||||
.idea/replstate.xml
|
|
||||||
|
|
||||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
|
||||||
com_crashlytics_export_strings.xml
|
|
||||||
crashlytics.properties
|
|
||||||
crashlytics-build.properties
|
|
||||||
fabric.properties
|
|
||||||
|
|
||||||
# Editor-based Rest Client
|
|
||||||
.idea/httpRequests
|
|
||||||
|
|
||||||
# Android studio 3.1+ serialized cache file
|
|
||||||
.idea/caches/build_file_checksums.ser
|
|
||||||
|
|
||||||
### VisualStudioCode ###
|
|
||||||
.vscode/*
|
|
||||||
!.vscode/settings.json
|
|
||||||
!.vscode/tasks.json
|
|
||||||
!.vscode/launch.json
|
|
||||||
!.vscode/extensions.json
|
|
||||||
|
|
||||||
### VisualStudioCode Patch ###
|
|
||||||
# Ignore all local history of files
|
|
||||||
.history
|
|
||||||
|
|
||||||
### Windows ###
|
|
||||||
# Windows thumbnail cache files
|
|
||||||
Thumbs.db
|
|
||||||
ehthumbs.db
|
|
||||||
ehthumbs_vista.db
|
|
||||||
|
|
||||||
# Dump file
|
|
||||||
*.stackdump
|
|
||||||
|
|
||||||
# Folder config file
|
|
||||||
[Dd]esktop.ini
|
|
||||||
|
|
||||||
# Recycle Bin used on file shares
|
|
||||||
$RECYCLE.BIN/
|
|
||||||
|
|
||||||
# Windows Installer files
|
|
||||||
*.cab
|
|
||||||
*.msi
|
|
||||||
*.msix
|
|
||||||
*.msm
|
|
||||||
*.msp
|
|
||||||
|
|
||||||
# Windows shortcuts
|
|
||||||
*.lnk
|
|
||||||
|
|
||||||
### VisualStudio ###
|
|
||||||
## Ignore Visual Studio temporary files, build results, and
|
|
||||||
## files generated by popular Visual Studio add-ons.
|
|
||||||
##
|
|
||||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
|
||||||
|
|
||||||
# User-specific files
|
|
||||||
*.rsuser
|
|
||||||
*.suo
|
|
||||||
*.user
|
|
||||||
*.userosscache
|
|
||||||
*.sln.docstates
|
|
||||||
|
|
||||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
|
||||||
*.userprefs
|
|
||||||
|
|
||||||
# Build results
|
|
||||||
[Dd]ebug/
|
|
||||||
[Dd]ebugPublic/
|
|
||||||
[Rr]elease/
|
|
||||||
[Rr]eleases/
|
|
||||||
x64/
|
|
||||||
x86/
|
|
||||||
[Aa][Rr][Mm]/
|
|
||||||
[Aa][Rr][Mm]64/
|
|
||||||
bld/
|
|
||||||
[Bb]in/
|
|
||||||
[Oo]bj/
|
|
||||||
[Ll]og/
|
|
||||||
|
|
||||||
# Visual Studio 2015/2017 cache/options directory
|
|
||||||
.vs/
|
|
||||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
|
||||||
#wwwroot/
|
|
||||||
|
|
||||||
# Visual Studio 2017 auto generated files
|
|
||||||
Generated\ Files/
|
|
||||||
|
|
||||||
# MSTest test Results
|
|
||||||
[Tt]est[Rr]esult*/
|
|
||||||
[Bb]uild[Ll]og.*
|
|
||||||
|
|
||||||
# NUNIT
|
|
||||||
*.VisualState.xml
|
|
||||||
TestResult.xml
|
|
||||||
|
|
||||||
# Build Results of an ATL Project
|
|
||||||
[Dd]ebugPS/
|
|
||||||
[Rr]eleasePS/
|
|
||||||
dlldata.c
|
|
||||||
|
|
||||||
# Benchmark Results
|
|
||||||
BenchmarkDotNet.Artifacts/
|
|
||||||
|
|
||||||
# .NET Core
|
|
||||||
project.lock.json
|
|
||||||
project.fragment.lock.json
|
|
||||||
artifacts/
|
|
||||||
|
|
||||||
# StyleCop
|
|
||||||
StyleCopReport.xml
|
|
||||||
|
|
||||||
# Files built by Visual Studio
|
|
||||||
*_i.c
|
|
||||||
*_p.c
|
|
||||||
*_h.h
|
|
||||||
*.ilk
|
|
||||||
*.meta
|
|
||||||
*.obj
|
|
||||||
*.iobj
|
|
||||||
*.pch
|
|
||||||
*.pdb
|
|
||||||
*.ipdb
|
|
||||||
*.pgc
|
|
||||||
*.pgd
|
|
||||||
*.rsp
|
|
||||||
*.sbr
|
|
||||||
*.tlb
|
|
||||||
*.tli
|
|
||||||
*.tlh
|
|
||||||
*.tmp
|
|
||||||
*.tmp_proj
|
|
||||||
*_wpftmp.csproj
|
|
||||||
*.vspscc
|
|
||||||
*.vssscc
|
|
||||||
.builds
|
|
||||||
*.pidb
|
|
||||||
*.svclog
|
|
||||||
*.scc
|
|
||||||
|
|
||||||
# Chutzpah Test files
|
|
||||||
_Chutzpah*
|
|
||||||
|
|
||||||
# Visual C++ cache files
|
|
||||||
ipch/
|
|
||||||
*.aps
|
|
||||||
*.ncb
|
|
||||||
*.opendb
|
|
||||||
*.opensdf
|
|
||||||
*.sdf
|
|
||||||
*.cachefile
|
|
||||||
*.VC.db
|
|
||||||
*.VC.VC.opendb
|
|
||||||
|
|
||||||
# Visual Studio profiler
|
|
||||||
*.psess
|
|
||||||
*.vsp
|
|
||||||
*.vspx
|
|
||||||
*.sap
|
|
||||||
|
|
||||||
# Visual Studio Trace Files
|
|
||||||
*.e2e
|
|
||||||
|
|
||||||
# TFS 2012 Local Workspace
|
|
||||||
$tf/
|
|
||||||
|
|
||||||
# Guidance Automation Toolkit
|
|
||||||
*.gpState
|
|
||||||
|
|
||||||
# ReSharper is a .NET coding add-in
|
|
||||||
_ReSharper*/
|
|
||||||
*.[Rr]e[Ss]harper
|
|
||||||
*.DotSettings.user
|
|
||||||
|
|
||||||
# JustCode is a .NET coding add-in
|
|
||||||
.JustCode
|
|
||||||
|
|
||||||
# TeamCity is a build add-in
|
|
||||||
_TeamCity*
|
|
||||||
|
|
||||||
# DotCover is a Code Coverage Tool
|
|
||||||
*.dotCover
|
|
||||||
|
|
||||||
# AxoCover is a Code Coverage Tool
|
|
||||||
.axoCover/*
|
|
||||||
!.axoCover/settings.json
|
|
||||||
|
|
||||||
# Visual Studio code coverage results
|
|
||||||
*.coverage
|
|
||||||
*.coveragexml
|
|
||||||
|
|
||||||
# NCrunch
|
|
||||||
_NCrunch_*
|
|
||||||
.*crunch*.local.xml
|
|
||||||
nCrunchTemp_*
|
|
||||||
|
|
||||||
# MightyMoose
|
|
||||||
*.mm.*
|
|
||||||
AutoTest.Net/
|
|
||||||
|
|
||||||
# Web workbench (sass)
|
|
||||||
.sass-cache/
|
|
||||||
|
|
||||||
# Installshield output folder
|
|
||||||
[Ee]xpress/
|
|
||||||
|
|
||||||
# DocProject is a documentation generator add-in
|
|
||||||
DocProject/buildhelp/
|
|
||||||
DocProject/Help/*.HxT
|
|
||||||
DocProject/Help/*.HxC
|
|
||||||
DocProject/Help/*.hhc
|
|
||||||
DocProject/Help/*.hhk
|
|
||||||
DocProject/Help/*.hhp
|
|
||||||
DocProject/Help/Html2
|
|
||||||
DocProject/Help/html
|
|
||||||
|
|
||||||
# Click-Once directory
|
|
||||||
publish/
|
|
||||||
|
|
||||||
# Publish Web Output
|
|
||||||
*.[Pp]ublish.xml
|
|
||||||
*.azurePubxml
|
|
||||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
|
||||||
# but database connection strings (with potential passwords) will be unencrypted
|
|
||||||
*.pubxml
|
|
||||||
*.publishproj
|
|
||||||
|
|
||||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
|
||||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
|
||||||
# in these scripts will be unencrypted
|
|
||||||
PublishScripts/
|
|
||||||
|
|
||||||
# NuGet Packages
|
|
||||||
*.nupkg
|
|
||||||
# The packages folder can be ignored because of Package Restore
|
|
||||||
**/[Pp]ackages/*
|
|
||||||
# except build/, which is used as an MSBuild target.
|
|
||||||
!**/[Pp]ackages/build/
|
|
||||||
# Uncomment if necessary however generally it will be regenerated when needed
|
|
||||||
#!**/[Pp]ackages/repositories.config
|
|
||||||
# NuGet v3's project.json files produces more ignorable files
|
|
||||||
*.nuget.props
|
|
||||||
*.nuget.targets
|
|
||||||
|
|
||||||
# Microsoft Azure Build Output
|
|
||||||
csx/
|
|
||||||
*.build.csdef
|
|
||||||
|
|
||||||
# Microsoft Azure Emulator
|
|
||||||
ecf/
|
|
||||||
rcf/
|
|
||||||
|
|
||||||
# Windows Store app package directories and files
|
|
||||||
AppPackages/
|
|
||||||
BundleArtifacts/
|
|
||||||
Package.StoreAssociation.xml
|
|
||||||
_pkginfo.txt
|
|
||||||
*.appx
|
|
||||||
|
|
||||||
# Visual Studio cache files
|
|
||||||
# files ending in .cache can be ignored
|
|
||||||
*.[Cc]ache
|
|
||||||
# but keep track of directories ending in .cache
|
|
||||||
!?*.[Cc]ache/
|
|
||||||
|
|
||||||
# Others
|
|
||||||
ClientBin/
|
|
||||||
~$*
|
|
||||||
*.dbmdl
|
|
||||||
*.dbproj.schemaview
|
|
||||||
*.jfm
|
|
||||||
*.pfx
|
|
||||||
*.publishsettings
|
|
||||||
orleans.codegen.cs
|
|
||||||
|
|
||||||
# Including strong name files can present a security risk
|
|
||||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
|
||||||
#*.snk
|
|
||||||
|
|
||||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
|
||||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
|
||||||
#bower_components/
|
|
||||||
# ASP.NET Core default setup: bower directory is configured as wwwroot/lib/ and bower restore is true
|
|
||||||
**/wwwroot/lib/
|
|
||||||
|
|
||||||
# RIA/Silverlight projects
|
|
||||||
Generated_Code/
|
|
||||||
|
|
||||||
# Backup & report files from converting an old project file
|
|
||||||
# to a newer Visual Studio version. Backup files are not needed,
|
|
||||||
# because we have git ;-)
|
|
||||||
_UpgradeReport_Files/
|
|
||||||
Backup*/
|
|
||||||
UpgradeLog*.XML
|
|
||||||
UpgradeLog*.htm
|
|
||||||
ServiceFabricBackup/
|
|
||||||
*.rptproj.bak
|
|
||||||
|
|
||||||
# SQL Server files
|
|
||||||
*.mdf
|
|
||||||
*.ldf
|
|
||||||
*.ndf
|
|
||||||
|
|
||||||
# Business Intelligence projects
|
|
||||||
*.rdl.data
|
|
||||||
*.bim.layout
|
|
||||||
*.bim_*.settings
|
|
||||||
*.rptproj.rsuser
|
|
||||||
*- Backup*.rdl
|
|
||||||
|
|
||||||
# Microsoft Fakes
|
|
||||||
FakesAssemblies/
|
|
||||||
|
|
||||||
# GhostDoc plugin setting file
|
|
||||||
*.GhostDoc.xml
|
|
||||||
|
|
||||||
# Node.js Tools for Visual Studio
|
|
||||||
.ntvs_analysis.dat
|
|
||||||
|
|
||||||
# Visual Studio 6 build log
|
|
||||||
*.plg
|
|
||||||
|
|
||||||
# Visual Studio 6 workspace options file
|
|
||||||
*.opt
|
|
||||||
|
|
||||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
|
||||||
*.vbw
|
|
||||||
|
|
||||||
# Visual Studio LightSwitch build output
|
|
||||||
**/*.HTMLClient/GeneratedArtifacts
|
|
||||||
**/*.DesktopClient/GeneratedArtifacts
|
|
||||||
**/*.DesktopClient/ModelManifest.xml
|
|
||||||
**/*.Server/GeneratedArtifacts
|
|
||||||
**/*.Server/ModelManifest.xml
|
|
||||||
_Pvt_Extensions
|
|
||||||
|
|
||||||
# Paket dependency manager
|
|
||||||
.paket/paket.exe
|
|
||||||
paket-files/
|
|
||||||
|
|
||||||
# FAKE - F# Make
|
|
||||||
.fake/
|
|
||||||
|
|
||||||
# JetBrains Rider
|
|
||||||
.idea/
|
|
||||||
*.sln.iml
|
|
||||||
|
|
||||||
# CodeRush personal settings
|
|
||||||
.cr/personal
|
|
||||||
|
|
||||||
# Python Tools for Visual Studio (PTVS)
|
|
||||||
__pycache__/
|
|
||||||
*.pyc
|
|
||||||
|
|
||||||
# Cake - Uncomment if you are using it
|
|
||||||
# tools/**
|
|
||||||
# !tools/packages.config
|
|
||||||
|
|
||||||
# Tabs Studio
|
|
||||||
*.tss
|
|
||||||
|
|
||||||
# Telerik's JustMock configuration file
|
|
||||||
*.jmconfig
|
|
||||||
|
|
||||||
# BizTalk build output
|
|
||||||
*.btp.cs
|
|
||||||
*.btm.cs
|
|
||||||
*.odx.cs
|
|
||||||
*.xsd.cs
|
|
||||||
|
|
||||||
# OpenCover UI analysis results
|
|
||||||
OpenCover/
|
|
||||||
|
|
||||||
# Azure Stream Analytics local run output
|
|
||||||
ASALocalRun/
|
|
||||||
|
|
||||||
# MSBuild Binary and Structured Log
|
|
||||||
*.binlog
|
|
||||||
|
|
||||||
# NVidia Nsight GPU debugger configuration file
|
|
||||||
*.nvuser
|
|
||||||
|
|
||||||
# MFractors (Xamarin productivity tool) working folder
|
|
||||||
.mfractor/
|
|
||||||
|
|
||||||
# Local History for Visual Studio
|
|
||||||
.localhistory/
|
|
||||||
|
|
||||||
# BeatPulse healthcheck temp database
|
|
||||||
healthchecksdb
|
|
||||||
|
|
||||||
# End of https://www.gitignore.io/api/node,rider,macos,linux,windows,visualstudio,visualstudiocode
|
|
||||||
|
|
||||||
# dist for webpack output
|
|
||||||
dist
|
dist
|
||||||
|
web
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
# ide
|
||||||
|
.idea
|
||||||
|
.vscode
|
143
.stylelintrc
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
"stylelint-no-browser-hacks/lib",
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"at-rule-empty-line-before": [ "always", {
|
||||||
|
except: [
|
||||||
|
"blockless-after-same-name-blockless",
|
||||||
|
"first-nested",
|
||||||
|
],
|
||||||
|
ignore: ["after-comment"],
|
||||||
|
} ],
|
||||||
|
"at-rule-name-case": "lower",
|
||||||
|
"at-rule-name-space-after": "always-single-line",
|
||||||
|
"at-rule-no-unknown": true,
|
||||||
|
"at-rule-semicolon-newline-after": "always",
|
||||||
|
"block-closing-brace-empty-line-before": "never",
|
||||||
|
"block-closing-brace-newline-after": "always",
|
||||||
|
"block-closing-brace-newline-before": "always-multi-line",
|
||||||
|
"block-closing-brace-space-before": "always-single-line",
|
||||||
|
"block-no-empty": true,
|
||||||
|
"block-opening-brace-newline-after": "always-multi-line",
|
||||||
|
"block-opening-brace-space-after": "always-single-line",
|
||||||
|
"block-opening-brace-space-before": "always",
|
||||||
|
"color-hex-case": "lower",
|
||||||
|
"color-hex-length": "short",
|
||||||
|
"color-no-invalid-hex": true,
|
||||||
|
"comment-empty-line-before": [ "always", {
|
||||||
|
except: ["first-nested"],
|
||||||
|
ignore: ["stylelint-commands"],
|
||||||
|
} ],
|
||||||
|
"comment-no-empty": true,
|
||||||
|
"comment-whitespace-inside": "always",
|
||||||
|
"custom-property-empty-line-before": [ "always", {
|
||||||
|
except: [
|
||||||
|
"after-custom-property",
|
||||||
|
"first-nested",
|
||||||
|
],
|
||||||
|
ignore: [
|
||||||
|
"after-comment",
|
||||||
|
"inside-single-line-block",
|
||||||
|
],
|
||||||
|
} ],
|
||||||
|
"declaration-bang-space-after": "never",
|
||||||
|
"declaration-bang-space-before": "always",
|
||||||
|
"declaration-block-no-duplicate-properties": [
|
||||||
|
true,
|
||||||
|
{
|
||||||
|
ignore: ["consecutive-duplicates-with-different-values"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"declaration-block-no-shorthand-property-overrides": true,
|
||||||
|
"declaration-block-semicolon-newline-after": "always-multi-line",
|
||||||
|
"declaration-block-semicolon-space-after": "always-single-line",
|
||||||
|
"declaration-block-semicolon-space-before": "never",
|
||||||
|
"declaration-block-single-line-max-declarations": 1,
|
||||||
|
"declaration-block-trailing-semicolon": "always",
|
||||||
|
"declaration-colon-newline-after": "always-multi-line",
|
||||||
|
"declaration-colon-space-after": "always-single-line",
|
||||||
|
"declaration-colon-space-before": "never",
|
||||||
|
"font-family-no-duplicate-names": true,
|
||||||
|
"function-calc-no-invalid": true,
|
||||||
|
"function-calc-no-unspaced-operator": true,
|
||||||
|
"function-comma-newline-after": "always-multi-line",
|
||||||
|
"function-comma-space-after": "always-single-line",
|
||||||
|
"function-comma-space-before": "never",
|
||||||
|
"function-linear-gradient-no-nonstandard-direction": true,
|
||||||
|
"function-max-empty-lines": 0,
|
||||||
|
"function-name-case": "lower",
|
||||||
|
"function-parentheses-newline-inside": "always-multi-line",
|
||||||
|
"function-parentheses-space-inside": "never-single-line",
|
||||||
|
"function-whitespace-after": "always",
|
||||||
|
"indentation": 4,
|
||||||
|
"keyframe-declaration-no-important": true,
|
||||||
|
"length-zero-no-unit": true,
|
||||||
|
"max-empty-lines": 1,
|
||||||
|
"media-feature-colon-space-after": "always",
|
||||||
|
"media-feature-colon-space-before": "never",
|
||||||
|
"media-feature-name-case": "lower",
|
||||||
|
"media-feature-name-no-unknown": true,
|
||||||
|
"media-feature-parentheses-space-inside": "never",
|
||||||
|
"media-feature-range-operator-space-after": "always",
|
||||||
|
"media-feature-range-operator-space-before": "always",
|
||||||
|
"media-query-list-comma-newline-after": "always-multi-line",
|
||||||
|
"media-query-list-comma-space-after": "always-single-line",
|
||||||
|
"media-query-list-comma-space-before": "never",
|
||||||
|
"no-descending-specificity": true,
|
||||||
|
"no-duplicate-at-import-rules": true,
|
||||||
|
"no-duplicate-selectors": true,
|
||||||
|
"no-empty-source": true,
|
||||||
|
"no-eol-whitespace": true,
|
||||||
|
"no-extra-semicolons": true,
|
||||||
|
"no-invalid-double-slash-comments": true,
|
||||||
|
"no-missing-end-of-source-newline": true,
|
||||||
|
"number-leading-zero": "always",
|
||||||
|
"number-no-trailing-zeros": true,
|
||||||
|
"plugin/no-browser-hacks": true,
|
||||||
|
"property-case": "lower",
|
||||||
|
"property-no-unknown": [
|
||||||
|
true,
|
||||||
|
{
|
||||||
|
"ignoreProperties": [
|
||||||
|
"user-drag"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"rule-empty-line-before": [ "always-multi-line", {
|
||||||
|
except: ["first-nested"],
|
||||||
|
ignore: ["after-comment"],
|
||||||
|
} ],
|
||||||
|
"selector-attribute-brackets-space-inside": "never",
|
||||||
|
"selector-attribute-operator-space-after": "never",
|
||||||
|
"selector-attribute-operator-space-before": "never",
|
||||||
|
"selector-combinator-space-after": "always",
|
||||||
|
"selector-combinator-space-before": "always",
|
||||||
|
"selector-descendant-combinator-no-non-space": true,
|
||||||
|
"selector-list-comma-newline-after": "always",
|
||||||
|
"selector-list-comma-space-before": "never",
|
||||||
|
"selector-max-empty-lines": 0,
|
||||||
|
"selector-pseudo-class-case": "lower",
|
||||||
|
"selector-pseudo-class-no-unknown": true,
|
||||||
|
"selector-pseudo-class-parentheses-space-inside": "never",
|
||||||
|
"selector-pseudo-element-case": "lower",
|
||||||
|
"selector-pseudo-element-colon-notation": "double",
|
||||||
|
"selector-pseudo-element-no-unknown": [
|
||||||
|
true,
|
||||||
|
{
|
||||||
|
"ignorePseudoElements": [
|
||||||
|
"cue"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"selector-type-case": "lower",
|
||||||
|
"selector-type-no-unknown": true,
|
||||||
|
"string-no-newline": true,
|
||||||
|
"unit-case": "lower",
|
||||||
|
"unit-no-unknown": true,
|
||||||
|
"value-list-comma-newline-after": "always-multi-line",
|
||||||
|
"value-list-comma-space-after": "always-single-line",
|
||||||
|
"value-list-comma-space-before": "never",
|
||||||
|
"value-list-max-empty-lines": 0,
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,6 +32,9 @@
|
||||||
- [bilde2910](https://github.com/bilde2910)
|
- [bilde2910](https://github.com/bilde2910)
|
||||||
- [Daniel Hartung](https://github.com/dhartung)
|
- [Daniel Hartung](https://github.com/dhartung)
|
||||||
- [Ryan Hartzell](https://github.com/ryan-hartzell)
|
- [Ryan Hartzell](https://github.com/ryan-hartzell)
|
||||||
|
- [Thibault Nocchi](https://github.com/ThibaultNocchi)
|
||||||
|
- [MrTimscampi](https://github.com/MrTimscampi)
|
||||||
|
- [Sarab Singh](https://github.com/sarab97)
|
||||||
|
|
||||||
# Emby Contributors
|
# Emby Contributors
|
||||||
|
|
||||||
|
|
17
README.md
|
@ -45,20 +45,37 @@ Jellyfin Web is the frontend used for most of the clients available for end user
|
||||||
### Dependencies
|
### Dependencies
|
||||||
|
|
||||||
- Yarn
|
- Yarn
|
||||||
|
- Gulp-cli
|
||||||
|
|
||||||
### Getting Started
|
### Getting Started
|
||||||
|
|
||||||
1. Clone or download this repository.
|
1. Clone or download this repository.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git clone https://github.com/jellyfin/jellyfin-web.git
|
git clone https://github.com/jellyfin/jellyfin-web.git
|
||||||
cd jellyfin-web
|
cd jellyfin-web
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Install build dependencies in the project directory.
|
2. Install build dependencies in the project directory.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
yarn install
|
yarn install
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Run the web client with webpack for local development.
|
3. Run the web client with webpack for local development.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
yarn serve
|
yarn serve
|
||||||
```
|
```
|
||||||
|
|
||||||
|
4. Build the client with sourcemaps.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yarn build:development
|
||||||
|
```
|
||||||
|
|
||||||
|
You can build a nginx compatible version as well.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yarn build:standalone
|
||||||
|
```
|
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
|
@ -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
|
@ -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
|
@ -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
|
@ -0,0 +1 @@
|
||||||
|
8
|
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
|
@ -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
|
@ -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
|
@ -0,0 +1 @@
|
||||||
|
web usr/share/jellyfin/
|
1
debian/po/POTFILES.in
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
[type: gettext/rfc822deb] templates
|
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
|
@ -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
|
@ -0,0 +1 @@
|
||||||
|
1.0
|
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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
205
gulpfile.js
Normal file
|
@ -0,0 +1,205 @@
|
||||||
|
const { src, dest, series, parallel, watch } = require('gulp');
|
||||||
|
const browserSync = require('browser-sync').create();
|
||||||
|
const del = require('del');
|
||||||
|
const babel = require('gulp-babel');
|
||||||
|
const concat = require('gulp-concat');
|
||||||
|
const terser = require('gulp-terser');
|
||||||
|
const htmlmin = require('gulp-htmlmin');
|
||||||
|
const imagemin = require('gulp-imagemin');
|
||||||
|
const sourcemaps = require('gulp-sourcemaps');
|
||||||
|
const mode = require('gulp-mode')({
|
||||||
|
modes: ['development', 'production'],
|
||||||
|
default: 'development',
|
||||||
|
verbose: false
|
||||||
|
});
|
||||||
|
const stream = require('webpack-stream');
|
||||||
|
const inject = require('gulp-inject');
|
||||||
|
const postcss = require('gulp-postcss');
|
||||||
|
const sass = require('gulp-sass');
|
||||||
|
const gulpif = require('gulp-if');
|
||||||
|
const lazypipe = require('lazypipe');
|
||||||
|
|
||||||
|
sass.compiler = require('node-sass');
|
||||||
|
|
||||||
|
let config;
|
||||||
|
if (mode.production()) {
|
||||||
|
config = require('./webpack.prod.js');
|
||||||
|
} else {
|
||||||
|
config = require('./webpack.dev.js');
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
javascript: {
|
||||||
|
query: ['src/**/*.js', '!src/bundle.js', '!src/standalone.js', '!src/scripts/apploader.js']
|
||||||
|
},
|
||||||
|
apploader: {
|
||||||
|
query: ['src/standalone.js', 'src/scripts/apploader.js']
|
||||||
|
},
|
||||||
|
css: {
|
||||||
|
query: ['src/**/*.css', 'src/**/*.scss']
|
||||||
|
},
|
||||||
|
html: {
|
||||||
|
query: ['src/**/*.html', '!src/index.html']
|
||||||
|
},
|
||||||
|
images: {
|
||||||
|
query: ['src/**/*.png', 'src/**/*.jpg', 'src/**/*.gif', 'src/**/*.svg']
|
||||||
|
},
|
||||||
|
copy: {
|
||||||
|
query: ['src/**/*.json', 'src/**/*.ico']
|
||||||
|
},
|
||||||
|
injectBundle: {
|
||||||
|
query: 'src/index.html'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function serve() {
|
||||||
|
browserSync.init({
|
||||||
|
server: {
|
||||||
|
baseDir: './dist'
|
||||||
|
},
|
||||||
|
port: 8080
|
||||||
|
});
|
||||||
|
|
||||||
|
const events = ['add', 'change'];
|
||||||
|
|
||||||
|
watch(options.javascript.query).on('all', function (event, path) {
|
||||||
|
if (events.includes(event)) {
|
||||||
|
javascript(path);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(options.apploader.query, apploader(true));
|
||||||
|
|
||||||
|
watch('src/bundle.js', webpack);
|
||||||
|
|
||||||
|
watch(options.css.query).on('all', function (event, path) {
|
||||||
|
if (events.includes(event)) {
|
||||||
|
css(path);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(options.html.query).on('all', function (event, path) {
|
||||||
|
if (events.includes(event)) {
|
||||||
|
html(path);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(options.images.query).on('all', function (event, path) {
|
||||||
|
if (events.includes(event)) {
|
||||||
|
images(path);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(options.copy.query).on('all', function (event, path) {
|
||||||
|
if (events.includes(event)) {
|
||||||
|
copy(path);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(options.injectBundle.query, injectBundle);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clean() {
|
||||||
|
return del(['dist/']);
|
||||||
|
}
|
||||||
|
|
||||||
|
const pipelineJavascript = lazypipe()
|
||||||
|
.pipe(function () {
|
||||||
|
return mode.development(sourcemaps.init({ loadMaps: true }));
|
||||||
|
})
|
||||||
|
.pipe(function () {
|
||||||
|
return babel({
|
||||||
|
presets: [
|
||||||
|
['@babel/preset-env']
|
||||||
|
]
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.pipe(function () {
|
||||||
|
return terser({
|
||||||
|
keep_fnames: true,
|
||||||
|
mangle: false
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.pipe(function () {
|
||||||
|
return mode.development(sourcemaps.write('.'));
|
||||||
|
});
|
||||||
|
|
||||||
|
function javascript(query) {
|
||||||
|
return src(typeof query !== 'function' ? query : options.javascript.query, { base: './src/' })
|
||||||
|
.pipe(pipelineJavascript())
|
||||||
|
.pipe(dest('dist/'))
|
||||||
|
.pipe(browserSync.stream());
|
||||||
|
}
|
||||||
|
|
||||||
|
function apploader(standalone) {
|
||||||
|
function task() {
|
||||||
|
return src(options.apploader.query, { base: './src/' })
|
||||||
|
.pipe(gulpif(standalone, concat('scripts/apploader.js')))
|
||||||
|
.pipe(pipelineJavascript())
|
||||||
|
.pipe(dest('dist/'))
|
||||||
|
.pipe(browserSync.stream());
|
||||||
|
}
|
||||||
|
|
||||||
|
task.displayName = 'apploader';
|
||||||
|
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
function webpack() {
|
||||||
|
return stream(config)
|
||||||
|
.pipe(dest('dist/'))
|
||||||
|
.pipe(browserSync.stream());
|
||||||
|
}
|
||||||
|
|
||||||
|
function css(query) {
|
||||||
|
return src(typeof query !== 'function' ? query : options.css.query, { base: './src/' })
|
||||||
|
.pipe(mode.development(sourcemaps.init({ loadMaps: true })))
|
||||||
|
.pipe(sass().on('error', sass.logError))
|
||||||
|
.pipe(postcss())
|
||||||
|
.pipe(mode.development(sourcemaps.write('.')))
|
||||||
|
.pipe(dest('dist/'))
|
||||||
|
.pipe(browserSync.stream());
|
||||||
|
}
|
||||||
|
|
||||||
|
function html(query) {
|
||||||
|
return src(typeof query !== 'function' ? query : options.html.query, { base: './src/' })
|
||||||
|
.pipe(mode.production(htmlmin({ collapseWhitespace: true })))
|
||||||
|
.pipe(dest('dist/'))
|
||||||
|
.pipe(browserSync.stream());
|
||||||
|
}
|
||||||
|
|
||||||
|
function images(query) {
|
||||||
|
return src(typeof query !== 'function' ? query : options.images.query, { base: './src/' })
|
||||||
|
.pipe(mode.production(imagemin()))
|
||||||
|
.pipe(dest('dist/'))
|
||||||
|
.pipe(browserSync.stream());
|
||||||
|
}
|
||||||
|
|
||||||
|
function copy(query) {
|
||||||
|
return src(typeof query !== 'function' ? query : options.copy.query, { base: './src/' })
|
||||||
|
.pipe(dest('dist/'))
|
||||||
|
.pipe(browserSync.stream());
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyIndex() {
|
||||||
|
return src(options.injectBundle.query, { base: './src/' })
|
||||||
|
.pipe(dest('dist/'))
|
||||||
|
.pipe(browserSync.stream());
|
||||||
|
}
|
||||||
|
|
||||||
|
function injectBundle() {
|
||||||
|
return src(options.injectBundle.query, { base: './src/' })
|
||||||
|
.pipe(inject(
|
||||||
|
src(['src/scripts/apploader.js'], { read: false }, { base: './src/' }), { relative: true }
|
||||||
|
))
|
||||||
|
.pipe(dest('dist/'))
|
||||||
|
.pipe(browserSync.stream());
|
||||||
|
}
|
||||||
|
|
||||||
|
function build(standalone) {
|
||||||
|
return series(clean, parallel(javascript, apploader(standalone), webpack, css, html, images, copy));
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.default = series(build(false), copyIndex);
|
||||||
|
exports.standalone = series(build(true), injectBundle);
|
||||||
|
exports.serve = series(exports.standalone, serve);
|
131
package.json
|
@ -5,39 +5,113 @@
|
||||||
"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": {
|
||||||
"autoprefixer": "^9.7.3",
|
"@babel/core": "^7.9.6",
|
||||||
|
"@babel/plugin-transform-modules-amd": "^7.9.6",
|
||||||
|
"@babel/polyfill": "^7.8.7",
|
||||||
|
"@babel/preset-env": "^7.8.6",
|
||||||
|
"autoprefixer": "^9.7.6",
|
||||||
|
"babel-loader": "^8.0.6",
|
||||||
|
"browser-sync": "^2.26.7",
|
||||||
"clean-webpack-plugin": "^3.0.0",
|
"clean-webpack-plugin": "^3.0.0",
|
||||||
"copy-webpack-plugin": "^5.1.1",
|
"copy-webpack-plugin": "^5.1.1",
|
||||||
"css-loader": "^2.1.0",
|
"css-loader": "^3.4.2",
|
||||||
"eslint": "^5.16.0",
|
"cssnano": "^4.1.10",
|
||||||
"file-loader": "^3.0.1",
|
"del": "^5.1.0",
|
||||||
"html-webpack-plugin": "^3.2.0",
|
"eslint": "^6.8.0",
|
||||||
|
"eslint-plugin-compat": "^3.5.1",
|
||||||
|
"eslint-plugin-eslint-comments": "^3.1.2",
|
||||||
|
"eslint-plugin-import": "^2.20.2",
|
||||||
|
"eslint-plugin-promise": "^4.2.1",
|
||||||
|
"file-loader": "^6.0.0",
|
||||||
|
"gulp": "^4.0.2",
|
||||||
|
"gulp-babel": "^8.0.0",
|
||||||
|
"gulp-cli": "^2.2.0",
|
||||||
|
"gulp-concat": "^2.6.1",
|
||||||
|
"gulp-htmlmin": "^5.0.1",
|
||||||
|
"gulp-if": "^3.0.0",
|
||||||
|
"gulp-imagemin": "^7.1.0",
|
||||||
|
"gulp-inject": "^5.0.5",
|
||||||
|
"gulp-mode": "^1.0.2",
|
||||||
|
"gulp-postcss": "^8.0.0",
|
||||||
|
"gulp-sass": "^4.0.2",
|
||||||
|
"gulp-sourcemaps": "^2.6.5",
|
||||||
|
"gulp-terser": "^1.2.0",
|
||||||
|
"html-webpack-plugin": "^4.3.0",
|
||||||
|
"lazypipe": "^1.0.2",
|
||||||
|
"node-sass": "^4.13.1",
|
||||||
"postcss-loader": "^3.0.0",
|
"postcss-loader": "^3.0.0",
|
||||||
"style-loader": "^0.23.1",
|
"postcss-preset-env": "^6.7.0",
|
||||||
"webpack": "^4.41.0",
|
"style-loader": "^1.1.3",
|
||||||
"webpack-cli": "^3.3.9",
|
"stylelint": "^13.3.3",
|
||||||
|
"stylelint-config-rational-order": "^0.1.2",
|
||||||
|
"stylelint-no-browser-hacks": "^1.2.1",
|
||||||
|
"stylelint-order": "^4.0.0",
|
||||||
|
"webpack": "^4.41.5",
|
||||||
|
"webpack-cli": "^3.3.10",
|
||||||
"webpack-concat-plugin": "^3.0.0",
|
"webpack-concat-plugin": "^3.0.0",
|
||||||
"webpack-dev-server": "^3.8.1",
|
"webpack-dev-server": "^3.10.3",
|
||||||
"webpack-merge": "^4.2.2"
|
"webpack-merge": "^4.2.2",
|
||||||
|
"webpack-stream": "^5.2.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"alameda": "^1.3.0",
|
"alameda": "^1.4.0",
|
||||||
"document-register-element": "^0.5.4",
|
"classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz",
|
||||||
|
"core-js": "^3.6.5",
|
||||||
|
"date-fns": "^2.13.0",
|
||||||
|
"document-register-element": "^1.14.3",
|
||||||
|
"fast-text-encoding": "^1.0.1",
|
||||||
"flv.js": "^1.5.0",
|
"flv.js": "^1.5.0",
|
||||||
"hls.js": "^0.12.4",
|
"headroom.js": "^0.11.0",
|
||||||
"howler": "^2.1.2",
|
"hls.js": "^0.13.1",
|
||||||
"jquery": "^3.4.1",
|
"howler": "^2.1.3",
|
||||||
|
"intersection-observer": "^0.10.0",
|
||||||
|
"jellyfin-apiclient": "^1.1.1",
|
||||||
|
"jellyfin-noto": "https://github.com/jellyfin/jellyfin-noto",
|
||||||
|
"jquery": "^3.5.1",
|
||||||
"jstree": "^3.3.7",
|
"jstree": "^3.3.7",
|
||||||
"libjass": "^0.11.0",
|
"libass-wasm": "https://github.com/jellyfin/JavascriptSubtitlesOctopus#4.0.0-jf-smarttv",
|
||||||
|
"material-design-icons-iconfont": "^5.0.1",
|
||||||
"native-promise-only": "^0.8.0-a",
|
"native-promise-only": "^0.8.0-a",
|
||||||
"requirejs": "^2.3.5",
|
"page": "^1.11.6",
|
||||||
|
"query-string": "^6.11.1",
|
||||||
"resize-observer-polyfill": "^1.5.1",
|
"resize-observer-polyfill": "^1.5.1",
|
||||||
"shaka-player": "^2.5.5",
|
"screenfull": "^5.0.2",
|
||||||
"sortablejs": "^1.9.0",
|
"shaka-player": "^2.5.11",
|
||||||
"swiper": "^3.4.2",
|
"sortablejs": "^1.10.2",
|
||||||
"libass-wasm": "^2.1.1",
|
"swiper": "^5.3.7",
|
||||||
"webcomponents.js": "^0.7.24",
|
"webcomponents.js": "^0.7.24",
|
||||||
"whatwg-fetch": "^1.1.1"
|
"whatwg-fetch": "^3.0.0"
|
||||||
|
},
|
||||||
|
"babel": {
|
||||||
|
"presets": [
|
||||||
|
"@babel/preset-env"
|
||||||
|
],
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"test": [
|
||||||
|
"src/components/autoFocuser.js",
|
||||||
|
"src/components/cardbuilder/cardBuilder.js",
|
||||||
|
"src/components/filedownloader.js",
|
||||||
|
"src/components/images/imageLoader.js",
|
||||||
|
"src/components/lazyloader/lazyloader-intersectionobserver.js",
|
||||||
|
"src/components/playback/mediasession.js",
|
||||||
|
"src/components/sanatizefilename.js",
|
||||||
|
"src/components/scrollManager.js",
|
||||||
|
"src/scripts/dfnshelper.js",
|
||||||
|
"src/scripts/dom.js",
|
||||||
|
"src/scripts/filesystem.js",
|
||||||
|
"src/scripts/imagehelper.js",
|
||||||
|
"src/scripts/inputManager.js",
|
||||||
|
"src/scripts/keyboardnavigation.js",
|
||||||
|
"src/scripts/settings/appSettings.js",
|
||||||
|
"src/scripts/settings/userSettings.js",
|
||||||
|
"src/scripts/settings/webSettings.js"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
"@babel/plugin-transform-modules-amd"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"last 2 Firefox versions",
|
"last 2 Firefox versions",
|
||||||
|
@ -46,18 +120,21 @@
|
||||||
"last 2 Safari versions",
|
"last 2 Safari versions",
|
||||||
"last 2 iOS versions",
|
"last 2 iOS versions",
|
||||||
"last 2 Edge versions",
|
"last 2 Edge versions",
|
||||||
|
"Chrome 27",
|
||||||
"Chrome 38",
|
"Chrome 38",
|
||||||
"Chrome 47",
|
"Chrome 47",
|
||||||
"Chrome 53",
|
"Chrome 53",
|
||||||
"Chrome 56",
|
"Chrome 56",
|
||||||
"Chrome 63",
|
"Chrome 63",
|
||||||
"Explorer 11",
|
|
||||||
"Firefox ESR"
|
"Firefox ESR"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "webpack-dev-server --config webpack.dev.js --open",
|
"serve": "gulp serve --development",
|
||||||
"build": "webpack --config webpack.prod.js",
|
"prepare": "gulp --production",
|
||||||
"lint": "eslint \"src\"",
|
"build:development": "gulp --development",
|
||||||
"prepare": "webpack --config webpack.prod.js"
|
"build:production": "gulp --production",
|
||||||
|
"build:standalone": "gulp standalone --development",
|
||||||
|
"lint": "eslint \".\"",
|
||||||
|
"stylelint": "stylelint \"src/**/*.css\""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,16 @@
|
||||||
module.exports = {
|
const packageConfig = require('./package.json');
|
||||||
|
const postcssPresetEnv = require('postcss-preset-env');
|
||||||
|
const autoprefixer = require('autoprefixer');
|
||||||
|
const cssnano = require('cssnano');
|
||||||
|
|
||||||
|
const config = () => ({
|
||||||
plugins: [
|
plugins: [
|
||||||
require('autoprefixer')
|
// 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()
|
||||||
]
|
]
|
||||||
}
|
});
|
||||||
|
|
||||||
|
module.exports = config;
|
||||||
|
|
41
scripts/scdup.py
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
|
# load every key in the source language
|
||||||
|
# check the keys in all translations
|
||||||
|
# remove keys that only exist in translations
|
||||||
|
|
||||||
|
cwd = os.getcwd()
|
||||||
|
langdir = cwd + '/../src/strings'
|
||||||
|
langlst = os.listdir(langdir)
|
||||||
|
|
||||||
|
langlst.remove('en-us.json')
|
||||||
|
print(langlst)
|
||||||
|
input('press enter to continue')
|
||||||
|
|
||||||
|
keysus = []
|
||||||
|
with open(langdir + '/' + 'en-us.json') as en:
|
||||||
|
langus = json.load(en)
|
||||||
|
for key in langus:
|
||||||
|
keysus.append(key)
|
||||||
|
|
||||||
|
for lang in langlst:
|
||||||
|
with open(langdir + '/' + lang, 'r') as f:
|
||||||
|
inde = 2
|
||||||
|
if '\n \"' in f.read():
|
||||||
|
inde = 4
|
||||||
|
f.close()
|
||||||
|
with open(langdir + '/' + lang, 'r+') as f:
|
||||||
|
langjson = json.load(f)
|
||||||
|
langjnew = {}
|
||||||
|
for key in langjson:
|
||||||
|
if key in keysus:
|
||||||
|
langjnew[key] = langjson[key]
|
||||||
|
f.seek(0)
|
||||||
|
f.write(json.dumps(langjnew, indent=inde, sort_keys=False, ensure_ascii=False))
|
||||||
|
f.write('\n')
|
||||||
|
f.truncate()
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
print('DONE')
|
40
scripts/scgen.py
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import json
|
||||||
|
|
||||||
|
# load all keys in the source language
|
||||||
|
# check entire codebase for usages
|
||||||
|
# print unused keys to a text file
|
||||||
|
# TODO: dynamic string usages cause false positives
|
||||||
|
|
||||||
|
cwd = os.getcwd()
|
||||||
|
langdir = cwd + '/../src/strings'
|
||||||
|
langlst = []
|
||||||
|
langlst.append('en-us.json')
|
||||||
|
|
||||||
|
# unused keys
|
||||||
|
dep = []
|
||||||
|
|
||||||
|
def grep(key):
|
||||||
|
command = 'grep -r -E "(\(\\\"|\(\'|\{)%s(\\\"|\'|\})" --include=\*.{js,html} --exclude-dir=../src/strings ../src' % key
|
||||||
|
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
|
output = p.stdout.readlines()
|
||||||
|
if output:
|
||||||
|
print('DONE: ' + key)
|
||||||
|
return True
|
||||||
|
print('UNUSED: ' + key)
|
||||||
|
dep.append(key)
|
||||||
|
return False
|
||||||
|
|
||||||
|
for lang in langlst:
|
||||||
|
with open(langdir + '/' + lang) as f:
|
||||||
|
langjson = json.load(f)
|
||||||
|
for key in langjson:
|
||||||
|
grep(key)
|
||||||
|
|
||||||
|
print(dep)
|
||||||
|
print('LENGTH: ' + str(len(dep)))
|
||||||
|
with open('scout.txt', 'w') as out:
|
||||||
|
for item in dep:
|
||||||
|
out.write(item + '\n')
|
||||||
|
out.close()
|
34
scripts/scrm.py
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
|
# load text file containing unused keys
|
||||||
|
# remove the keys from all string files
|
||||||
|
|
||||||
|
cwd = os.getcwd()
|
||||||
|
langdir = cwd + '/../src/strings'
|
||||||
|
langlst = os.listdir(langdir)
|
||||||
|
|
||||||
|
keys = []
|
||||||
|
|
||||||
|
with open('scout.txt', 'r') as f:
|
||||||
|
for line in f:
|
||||||
|
keys.append(line.strip('\n'))
|
||||||
|
|
||||||
|
for lang in langlst:
|
||||||
|
with open(langdir + '/' + lang, 'r') as f:
|
||||||
|
inde = 2
|
||||||
|
if '\n \"' in f.read():
|
||||||
|
inde = 4
|
||||||
|
f.close()
|
||||||
|
with open(langdir + '/' + lang, 'r+') as f:
|
||||||
|
langjson = json.load(f)
|
||||||
|
for key in keys:
|
||||||
|
langjson.pop(key, None)
|
||||||
|
f.seek(0)
|
||||||
|
f.write(json.dumps(langjson, indent=inde, sort_keys=False, ensure_ascii=False))
|
||||||
|
f.write('\n')
|
||||||
|
f.truncate()
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
print('DONE')
|
|
@ -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="md-icon">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>
|
||||||
|
|
|
@ -1,239 +1,295 @@
|
||||||
.dashboardColumn,
|
.dashboardColumn,
|
||||||
.dashboardSections {
|
.dashboardSections {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-box-direction: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboardFooter {
|
.dashboardFooter {
|
||||||
margin-top: 3.5em;
|
margin-top: 3.5em;
|
||||||
text-align: center
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboardFooter a {
|
.dashboardFooter a {
|
||||||
margin: 0 .7em
|
margin: 0 0.7em;
|
||||||
}
|
}
|
||||||
|
|
||||||
progress {
|
progress {
|
||||||
appearance: none;
|
appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background: #ccc !important
|
background: #ccc !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
progress[role]:after {
|
progress[role]::after {
|
||||||
background-image: none
|
background-image: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
progress::-webkit-progress-bar {
|
progress::-webkit-progress-bar {
|
||||||
background: #ccc
|
background: #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
progress::-moz-progress-bar {
|
progress::-moz-progress-bar {
|
||||||
background-color: #00a4dc
|
background-color: #00a4dc;
|
||||||
}
|
}
|
||||||
|
|
||||||
progress::-webkit-progress-value {
|
progress::-webkit-progress-value {
|
||||||
background-color: #00a4dc
|
background-color: #00a4dc;
|
||||||
}
|
}
|
||||||
|
|
||||||
progress[aria-valuenow]:before {
|
progress[aria-valuenow]::before {
|
||||||
border-radius: .4em;
|
border-radius: 0.4em;
|
||||||
background-color: #00a4dc
|
background-color: #00a4dc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.localnav {
|
.localnav {
|
||||||
margin-bottom: 2.2em !important
|
margin-bottom: 2.2em !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (min-width: 50em) {
|
@media all and (min-width: 50em) {
|
||||||
|
.type-interior > div[data-role=content],
|
||||||
.type-interior>.ui-panel-content-wrap>div[data-role=content],
|
.type-interior > .ui-panel-content-wrap > div[data-role=content] {
|
||||||
.type-interior>div[data-role=content] {
|
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
overflow: hidden
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboardDocument .dashboardEntryHeaderButton,
|
.dashboardDocument .dashboardEntryHeaderButton,
|
||||||
.dashboardDocument .lnkManageServer {
|
.dashboardDocument .lnkManageServer {
|
||||||
display: none !important
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.adminDrawerLogo {
|
.adminDrawerLogo {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-mobile .adminDrawerLogo {
|
||||||
padding: 1.5em 1em 1.2em;
|
padding: 1.5em 1em 1.2em;
|
||||||
border-bottom: 1px solid #e0e0e0;
|
border-bottom: 1px solid #e0e0e0;
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
display: block
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.adminDrawerLogo img {
|
.adminDrawerLogo img {
|
||||||
height: 4em
|
height: 4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
a[data-role=button] {
|
||||||
|
background: #292929 !important;
|
||||||
|
background-clip: padding-box;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-webkit-background-clip: padding-box;
|
||||||
|
cursor: pointer !important;
|
||||||
|
font-family: inherit !important;
|
||||||
|
font-weight: 500 !important;
|
||||||
|
margin: 0 0.25em !important;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.8em 1em;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
div[data-role=controlgroup] a[data-role=button] {
|
div[data-role=controlgroup] a[data-role=button] {
|
||||||
display: inline-block !important;
|
display: inline-block !important;
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
|
-webkit-box-shadow: none !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
border-radius: 0
|
-webkit-border-radius: 0;
|
||||||
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
div[data-role=controlgroup] a[data-role=button]:first-child {
|
div[data-role=controlgroup] a[data-role=button]:first-child {
|
||||||
border-bottom-left-radius: .3125em;
|
-webkit-border-bottom-left-radius: 0.3125em;
|
||||||
border-top-left-radius: .3125em
|
border-bottom-left-radius: 0.3125em;
|
||||||
|
-webkit-border-top-left-radius: 0.3125em;
|
||||||
|
border-top-left-radius: 0.3125em;
|
||||||
}
|
}
|
||||||
|
|
||||||
div[data-role=controlgroup] a[data-role=button]:last-child {
|
div[data-role=controlgroup] a[data-role=button]:last-child {
|
||||||
border-bottom-right-radius: .3125em;
|
-webkit-border-bottom-right-radius: 0.3125em;
|
||||||
border-top-right-radius: .3125em
|
border-bottom-right-radius: 0.3125em;
|
||||||
|
-webkit-border-top-right-radius: 0.3125em;
|
||||||
|
border-top-right-radius: 0.3125em;
|
||||||
}
|
}
|
||||||
|
|
||||||
div[data-role=controlgroup] a[data-role=button] + a[data-role=button] {
|
div[data-role=controlgroup] a[data-role=button] + a[data-role=button] {
|
||||||
border-left-width: 0 !important;
|
border-left-width: 0 !important;
|
||||||
margin: 0 0 0 -.4em !important
|
margin: 0 0 0 -0.4em !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
div[data-role=controlgroup] a.ui-btn-active {
|
div[data-role=controlgroup] a.ui-btn-active {
|
||||||
background: #00a4dc !important;
|
background: #00a4dc !important;
|
||||||
color: #292929 !important
|
color: #292929 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header .imageLink {
|
.sessionAppInfo img {
|
||||||
display: inline-block
|
max-width: 40px;
|
||||||
|
max-height: 40px;
|
||||||
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header .imageLink img {
|
.appLinks img {
|
||||||
height: 2.1em;
|
height: 36px;
|
||||||
vertical-align: middle
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-primary {
|
|
||||||
padding-top: 6em;
|
|
||||||
padding-right: 1em;
|
|
||||||
padding-left: 1em
|
|
||||||
}
|
|
||||||
|
|
||||||
.withTabs .content-primary {
|
|
||||||
padding-top: 9em !important
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (min-width:40em) {
|
|
||||||
.content-primary {
|
|
||||||
padding-top: 7em
|
|
||||||
}
|
|
||||||
|
|
||||||
.withTabs .content-primary {
|
|
||||||
padding-top: 10em !important
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (min-width:84em) {
|
|
||||||
.withTabs .content-primary {
|
|
||||||
padding-top: 7em !important
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-primary ul:first-child {
|
|
||||||
margin-top: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboardSections {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboardColumn {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-grow: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
.activeSession:not(.playingSession) .sessionNowPlayingContent {
|
|
||||||
display: none
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboardSection {
|
|
||||||
flex-shrink: 0;
|
|
||||||
margin: 0 0 2em
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboardSection h3 {
|
|
||||||
margin-top: .5em;
|
|
||||||
margin-bottom: .5em
|
|
||||||
}
|
|
||||||
|
|
||||||
.activeRecordingItems>.card {
|
|
||||||
width: 50%
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (min-width:70em) {
|
|
||||||
.dashboardSections {
|
|
||||||
flex-wrap: wrap;
|
|
||||||
flex-direction: row
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboardColumn-2-60 {
|
|
||||||
width: 46%
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboardColumn-2-40 {
|
|
||||||
width: 27%
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboardSection {
|
|
||||||
padding: 0 1.5em
|
|
||||||
}
|
|
||||||
|
|
||||||
.activeRecordingItems>.card {
|
|
||||||
width: 25%
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.premiumBanner img {
|
|
||||||
position: absolute;
|
|
||||||
text-align: right;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
width: 4.4em;
|
|
||||||
height: 4.4em
|
|
||||||
}
|
|
||||||
|
|
||||||
.wizardContent {
|
|
||||||
max-width: 62em;
|
|
||||||
padding: .5em 2em 1em;
|
|
||||||
margin: 0 auto;
|
|
||||||
background: #fff
|
|
||||||
}
|
|
||||||
|
|
||||||
.wizardNavigation {
|
|
||||||
text-align: right
|
|
||||||
}
|
|
||||||
|
|
||||||
.wizardContent form {
|
|
||||||
max-width: 100%
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.wizardContent h2 img {
|
.wizardContent h2 img {
|
||||||
height: 2.5em;
|
height: 2.5em;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
margin-right: .5em;
|
margin-right: 0.5em;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -.3em
|
top: -0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header .imageLink {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header .imageLink img {
|
||||||
|
height: 2.1em;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-primary {
|
||||||
|
padding-top: 6em;
|
||||||
|
padding-right: 1em;
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.withTabs .content-primary {
|
||||||
|
padding-top: 9em !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 40em) {
|
||||||
|
.content-primary {
|
||||||
|
padding-top: 4.6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.withTabs .content-primary {
|
||||||
|
padding-top: 10em !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 84em) {
|
||||||
|
.withTabs .content-primary {
|
||||||
|
padding-top: 7em !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-primary ul:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboardSections {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -webkit-flex;
|
||||||
|
display: flex;
|
||||||
|
-webkit-flex-direction: column;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboardColumn {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -webkit-flex;
|
||||||
|
display: flex;
|
||||||
|
-webkit-flex-direction: column;
|
||||||
|
flex-direction: column;
|
||||||
|
-webkit-flex-shrink: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
-webkit-box-flex: 1;
|
||||||
|
-webkit-flex-grow: 1;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sessionNowPlayingContent {
|
||||||
|
-webkit-background-size: cover;
|
||||||
|
background-size: cover;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center center;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activeSession:not(.playingSession) .sessionNowPlayingContent {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboardSection {
|
||||||
|
-webkit-flex-shrink: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin: 0 0 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboardSection h3 {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activeRecordingItems > .card {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 70em) {
|
||||||
|
.dashboardSections {
|
||||||
|
-webkit-flex-wrap: wrap;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
-webkit-box-orient: horizontal;
|
||||||
|
-webkit-box-direction: normal;
|
||||||
|
-webkit-flex-direction: row;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboardColumn-2-60 {
|
||||||
|
width: 46%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboardColumn-2-40 {
|
||||||
|
width: 27%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboardSection {
|
||||||
|
padding: 0 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activeRecordingItems > .card {
|
||||||
|
width: 25%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizardContent {
|
||||||
|
max-width: 62em;
|
||||||
|
padding: 0.5em 2em 1em;
|
||||||
|
margin: 0 auto;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizardNavigation {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizardContent form {
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scheduledTaskPaperIconItem {
|
.scheduledTaskPaperIconItem {
|
||||||
outline: 0 !important
|
outline: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.activeSession {
|
.activeSession {
|
||||||
width: 100% !important
|
width: 100% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.activitylogUserPhoto {
|
.activitylogUserPhoto {
|
||||||
height: 1.71em;
|
height: 1.71em;
|
||||||
width: 1.71em;
|
width: 1.71em;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
margin-right:.5em;
|
margin-right: 0.5em;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
|
@ -241,22 +297,22 @@ div[data-role=controlgroup] a.ui-btn-active {
|
||||||
|
|
||||||
@media all and (min-width: 40em) {
|
@media all and (min-width: 40em) {
|
||||||
.activeSession {
|
.activeSession {
|
||||||
width: 100% !important
|
width: 100% !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (min-width: 50em) {
|
@media all and (min-width: 50em) {
|
||||||
.activeSession {
|
.activeSession {
|
||||||
width: 50% !important
|
width: 50% !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sessionCardFooter {
|
.sessionCardFooter {
|
||||||
padding-top: .5em !important;
|
padding-top: 0.5em !important;
|
||||||
padding-bottom: 1em !important;
|
padding-bottom: 1em !important;
|
||||||
border-top: 1px solid #eee;
|
border-top: 1px solid #eee;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
position: relative
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sessionAppInfo {
|
.sessionAppInfo {
|
||||||
|
@ -265,22 +321,11 @@ div[data-role=controlgroup] a.ui-btn-active {
|
||||||
}
|
}
|
||||||
|
|
||||||
.sessionCardButtons {
|
.sessionCardButtons {
|
||||||
min-height: 2.7em
|
min-height: 2.7em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sessionCardButton {
|
.sessionCardButton {
|
||||||
margin: 0
|
margin: 0;
|
||||||
}
|
|
||||||
|
|
||||||
.sessionNowPlayingContent {
|
|
||||||
background-size: cover;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: center center;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sessionNowPlayingInnerContent {
|
.sessionNowPlayingInnerContent {
|
||||||
|
@ -289,23 +334,23 @@ div[data-role=controlgroup] a.ui-btn-active {
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
font-weight: 400
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sessionNowPlayingContent-withbackground + .sessionNowPlayingInnerContent {
|
.sessionNowPlayingContent-withbackground + .sessionNowPlayingInnerContent {
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
background: rgba(0, 0, 0, .7)
|
background: rgba(0, 0, 0, 0.7);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sessionAppName {
|
.sessionAppName {
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
max-width: 200px
|
max-width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sessionNowPlayingDetails {
|
.sessionNowPlayingDetails {
|
||||||
display: flex;
|
display: flex;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0px;
|
bottom: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,12 +360,6 @@ div[data-role=controlgroup] a.ui-btn-active {
|
||||||
padding: 0.8em 0.5em;
|
padding: 0.8em 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sessionAppInfo img {
|
|
||||||
max-width: 40px;
|
|
||||||
max-height: 40px;
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sessionNowPlayingTime {
|
.sessionNowPlayingTime {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
align-self: flex-end;
|
align-self: flex-end;
|
||||||
|
@ -332,6 +371,13 @@ div[data-role=controlgroup] a.ui-btn-active {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.playbackProgress,
|
||||||
|
.transcodingProgress {
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
background: transparent !important;
|
||||||
|
}
|
||||||
|
|
||||||
.activeSession .playbackProgress,
|
.activeSession .playbackProgress,
|
||||||
.activeSession .transcodingProgress {
|
.activeSession .transcodingProgress {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -342,13 +388,6 @@ div[data-role=controlgroup] a.ui-btn-active {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.playbackProgress,
|
|
||||||
.transcodingProgress {
|
|
||||||
margin: 0px;
|
|
||||||
width: 100%;
|
|
||||||
background: transparent !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.playbackProgress > div {
|
.playbackProgress > div {
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
background-color: #00a4dc;
|
background-color: #00a4dc;
|
||||||
|
@ -360,65 +399,65 @@ div[data-role=controlgroup] a.ui-btn-active {
|
||||||
|
|
||||||
@media all and (max-width: 34.375em) {
|
@media all and (max-width: 34.375em) {
|
||||||
.sessionAppName {
|
.sessionAppName {
|
||||||
max-width: 160px
|
max-width: 160px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 31.25em) {
|
@media all and (max-width: 31.25em) {
|
||||||
.sessionAppName {
|
.sessionAppName {
|
||||||
max-width: 150px
|
max-width: 150px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.disabledUser {
|
.disabledUser {
|
||||||
filter: grayscale(100%)
|
-webkit-filter: grayscale(100%);
|
||||||
|
filter: grayscale(100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.disabledUserBanner {
|
.disabledUserBanner {
|
||||||
margin: 0 0 2em
|
margin: 0 0 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.appLinks a {
|
.appLinks a {
|
||||||
text-decoration: none !important
|
text-decoration: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.appLinks a + a {
|
.appLinks a + a {
|
||||||
margin-left: 5px
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.appLinks img {
|
@-webkit-keyframes rotating {
|
||||||
height: 36px
|
from {
|
||||||
|
-webkit-transform: rotate(0);
|
||||||
|
transform: rotate(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
a[data-role=button] {
|
to {
|
||||||
background-clip: padding-box;
|
-webkit-transform: rotate(360deg);
|
||||||
cursor: pointer !important;
|
transform: rotate(360deg);
|
||||||
font-family: inherit !important;
|
}
|
||||||
font-weight: 500 !important;
|
|
||||||
margin: 0 .25em !important;
|
|
||||||
display: inline-block;
|
|
||||||
padding: .8em 1em;
|
|
||||||
text-align: center;
|
|
||||||
text-decoration: none !important;
|
|
||||||
background: #292929 !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes rotating {
|
@keyframes rotating {
|
||||||
from {
|
from {
|
||||||
transform: rotate(0)
|
-webkit-transform: rotate(0);
|
||||||
|
transform: rotate(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
to {
|
to {
|
||||||
transform: rotate(360deg)
|
-webkit-transform: rotate(360deg);
|
||||||
|
transform: rotate(360deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.rotatingCircle {
|
.rotatingCircle {
|
||||||
animation: rotating 2s linear infinite
|
-webkit-animation: rotating 2s linear infinite;
|
||||||
|
animation: rotating 2s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pluginPreviewImg {
|
.pluginPreviewImg {
|
||||||
box-shadow: 0 .0725em .29em 0 rgba(0, 0, 0, .37)
|
-webkit-box-shadow: 0 0.0725em 0.29em 0 rgba(0, 0, 0, 0.37);
|
||||||
|
box-shadow: 0 0.0725em 0.29em 0 rgba(0, 0, 0, 0.37);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-bar-a {
|
.ui-bar-a {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
.detailTableBodyCell,
|
.detailTableBodyCell,
|
||||||
.detailTableHeaderCell {
|
.detailTableHeaderCell {
|
||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
padding: .4em
|
padding: 0.4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detailTable {
|
.detailTable {
|
||||||
|
@ -9,11 +9,11 @@
|
||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0 auto
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detailTableHeaderCell {
|
.detailTableHeaderCell {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
vertical-align: top
|
vertical-align: top;
|
||||||
}
|
}
|
|
@ -1,34 +1,35 @@
|
||||||
html {
|
html {
|
||||||
font-family: -apple-system, "Helvetica", system-ui, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen-Sans", "Ubuntu", "Cantarell", "Helvetica Neue", 'Open Sans', sans-serif;
|
font-family: "Noto Sans", sans-serif;
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
|
||||||
font-size: 93%;
|
font-size: 93%;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
text-size-adjust: 100%;
|
text-size-adjust: 100%;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1, h2, h3 {
|
h1,
|
||||||
/* For better bolding, since Helvetica does not support 500 weight, and 600 is too thick */
|
h2,
|
||||||
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen-Sans", "Ubuntu", "Cantarell", "Helvetica Neue", 'Open Sans', sans-serif;
|
h3 {
|
||||||
|
font-family: "Noto Sans", sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-weight: 500;
|
font-weight: 400;
|
||||||
font-size: 1.8em;
|
font-size: 1.8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
font-weight: 500;
|
font-weight: 400;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
font-weight: 500;
|
font-weight: 400;
|
||||||
font-size: 1.17em;
|
font-size: 1.17em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout-tv {
|
.layout-tv {
|
||||||
font-size: 2.5vh;
|
font-size: 130%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout-mobile {
|
.layout-mobile {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
h1 {
|
h1 {
|
||||||
font-weight: 500;
|
font-weight: 400;
|
||||||
font-size: 1.8em;
|
font-size: 1.8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,12 +8,12 @@ h1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
font-weight: 500;
|
font-weight: 400;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
font-weight: 500;
|
font-weight: 400;
|
||||||
font-size: 1.17em;
|
font-size: 1.17em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
html {
|
html {
|
||||||
font-size: 82% !important
|
font-size: 82% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.formDialogFooter {
|
.formDialogFooter {
|
||||||
position: static !important;
|
position: static !important;
|
||||||
margin: 0 -1em !important
|
margin: 0 -1em !important;
|
||||||
}
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
.guideVerticalScroller {
|
.guideVerticalScroller {
|
||||||
padding-bottom: 15em
|
padding-bottom: 15em;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (min-width: 62.5em) {
|
@media all and (min-width: 62.5em) {
|
||||||
#guideTab {
|
#guideTab {
|
||||||
padding-left: .5em
|
padding-left: 0.5em;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,25 +0,0 @@
|
||||||
@font-face {
|
|
||||||
font-family: 'Material Icons';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
src: local('Material Icons'), local('MaterialIcons-Regular'), url(flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2) format('woff2'), url(flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff) format('woff');
|
|
||||||
}
|
|
||||||
|
|
||||||
.md-icon {
|
|
||||||
font-family: 'Material Icons';
|
|
||||||
font-weight: normal;
|
|
||||||
font-style: normal;
|
|
||||||
letter-spacing: normal;
|
|
||||||
text-transform: none;
|
|
||||||
display: inline-block;
|
|
||||||
white-space: nowrap;
|
|
||||||
word-wrap: normal;
|
|
||||||
direction: ltr;
|
|
||||||
-webkit-font-feature-settings: 'liga';
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
font-feature-settings: "liga" 1;
|
|
||||||
line-height: 1;
|
|
||||||
overflow: hidden;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
|
@ -1,50 +1,54 @@
|
||||||
.editPageSidebar {
|
.editPageSidebar {
|
||||||
display: block
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editPageSidebar-withcontent {
|
.editPageSidebar-withcontent {
|
||||||
display: none
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.libraryTree {
|
.libraryTree {
|
||||||
margin-left: .25em
|
margin-left: 0.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.offlineEditorNode {
|
.offlineEditorNode {
|
||||||
color: #c33
|
color: #c33;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editorNode img {
|
.editorNode img {
|
||||||
height: 18px;
|
height: 18px;
|
||||||
margin: 0 .35em;
|
margin: 0 0.35em;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -2px
|
top: -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jstree-anchor {
|
.jstree-anchor {
|
||||||
font-weight: 400 !important
|
font-weight: 400 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jstree-wholerow-hovered {
|
.jstree-wholerow-hovered {
|
||||||
background: #38c !important;
|
background: #38c !important;
|
||||||
|
-webkit-border-radius: 0 !important;
|
||||||
border-radius: 0 !important;
|
border-radius: 0 !important;
|
||||||
box-shadow: none !important
|
-webkit-box-shadow: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jstree-default .jstree-hovered {
|
.jstree-default .jstree-hovered {
|
||||||
background: 0 0 !important;
|
background: 0 0 !important;
|
||||||
|
-webkit-border-radius: 0 !important;
|
||||||
border-radius: 0 !important;
|
border-radius: 0 !important;
|
||||||
|
-webkit-box-shadow: none !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
color: #fff !important
|
color: #fff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jstree-default .jstree-wholerow-clicked {
|
.jstree-default .jstree-wholerow-clicked {
|
||||||
background: #00a4dc !important
|
background: #00a4dc !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.metadataSidebarIcon {
|
.metadataSidebarIcon {
|
||||||
margin-right: .4em
|
margin-right: 0.4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (min-width: 50em) {
|
@media all and (min-width: 50em) {
|
||||||
|
@ -55,21 +59,21 @@
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 30%;
|
width: 30%;
|
||||||
border-right: 1px solid #555;
|
border-right: 1px solid #555;
|
||||||
display: block
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editPageInnerContent {
|
.editPageInnerContent {
|
||||||
float: right;
|
float: right;
|
||||||
width: 68.5%
|
width: 68.5%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (min-width: 112.5em) {
|
@media all and (min-width: 112.5em) {
|
||||||
.editPageSidebar {
|
.editPageSidebar {
|
||||||
width: 25%
|
width: 25%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editPageInnerContent {
|
.editPageInnerContent {
|
||||||
width: 73.5%
|
width: 73.5%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
.scrollX {
|
.scrollX {
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
@ -8,39 +9,50 @@
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hiddenScrollX, .layout-tv .scrollX {
|
.hiddenScrollX,
|
||||||
scrollbar-width: none;
|
.layout-tv .scrollX {
|
||||||
|
-ms-overflow-style: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hiddenScrollX-forced {
|
.hiddenScrollX-forced {
|
||||||
scrollbar-width: none;
|
overflow: -moz-scrollbars-none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hiddenScrollX::-webkit-scrollbar, .layout-tv .scrollX::-webkit-scrollbar {
|
.hiddenScrollX::-webkit-scrollbar,
|
||||||
|
.layout-tv .scrollX::-webkit-scrollbar {
|
||||||
height: 0 !important;
|
height: 0 !important;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrollY {
|
.scrollY {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.smoothScrollY {
|
.smoothScrollY {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hiddenScrollY, .layout-tv .smoothScrollY {
|
.hiddenScrollY,
|
||||||
scrollbar-width: none;
|
.layout-tv .smoothScrollY {
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
|
||||||
|
/* Can't do this because it not only hides the scrollbar, but also prevents scrolling */
|
||||||
|
|
||||||
|
/* overflow: -moz-scrollbars-none; */
|
||||||
}
|
}
|
||||||
|
|
||||||
.hiddenScrollY-forced {
|
.hiddenScrollY-forced {
|
||||||
scrollbar-width: none;
|
overflow: -moz-scrollbars-none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hiddenScrollY::-webkit-scrollbar, .layout-tv .smoothScrollY::-webkit-scrollbar, .layout-tv .scrollY::-webkit-scrollbar {
|
.hiddenScrollY::-webkit-scrollbar,
|
||||||
|
.layout-tv .smoothScrollY::-webkit-scrollbar,
|
||||||
|
.layout-tv .scrollY::-webkit-scrollbar {
|
||||||
width: 0 !important;
|
width: 0 !important;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,23 @@ body,
|
||||||
html {
|
html {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
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 {
|
||||||
|
/* Fix font ligatures on older WebOS versions */
|
||||||
|
-webkit-font-feature-settings: "liga";
|
||||||
}
|
}
|
||||||
|
|
||||||
.backgroundContainer {
|
.backgroundContainer {
|
||||||
|
@ -11,52 +27,58 @@ html {
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
contain: strict
|
contain: strict;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
line-height: 1.35
|
line-height: 1.35;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout-mobile,
|
.layout-mobile,
|
||||||
.layout-tv {
|
.layout-tv {
|
||||||
user-select: none
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mainAnimatedPage {
|
.mainAnimatedPage {
|
||||||
contain: style size !important
|
contain: style size !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pageContainer {
|
.pageContainer {
|
||||||
overflow-x: visible !important
|
overflow-x: visible !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bodyWithPopupOpen {
|
.bodyWithPopupOpen {
|
||||||
overflow-y: hidden !important
|
overflow-y: hidden !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
div[data-role=page] {
|
div[data-role=page] {
|
||||||
outline: 0
|
outline: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pageTitle {
|
.pageTitle {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
font-family: inherit
|
font-family: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fieldDescription {
|
.fieldDescription {
|
||||||
padding-left: .15em;
|
padding-left: 0.15em;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
white-space: normal !important
|
white-space: normal !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fieldDescription + .fieldDescription {
|
.fieldDescription + .fieldDescription {
|
||||||
margin-top: .3em
|
margin-top: 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-primary,
|
.content-primary,
|
||||||
|
@ -70,18 +92,31 @@ div[data-role=page] {
|
||||||
@media all and (min-width: 50em) {
|
@media all and (min-width: 50em) {
|
||||||
.readOnlyContent,
|
.readOnlyContent,
|
||||||
form {
|
form {
|
||||||
max-width: 54em
|
max-width: 54em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.headerHelpButton {
|
.headerHelpButton {
|
||||||
margin-left: 1.25em !important;
|
margin-left: 1.25em !important;
|
||||||
padding-bottom: .4em !important;
|
padding-bottom: 0.4em !important;
|
||||||
padding-top: .4em !important
|
padding-top: 0.4em !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mediaInfoContent {
|
.mediaInfoContent {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
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%);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
.chapterThumbTextContainer,
|
.chapterThumbTextContainer,
|
||||||
.videoOsdBottom {
|
.videoOsdBottom {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.osdPoster img,
|
.osdPoster img,
|
||||||
|
@ -8,52 +11,59 @@
|
||||||
.videoOsdBottom {
|
.videoOsdBottom {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.osdHeader {
|
.osdHeader {
|
||||||
transition: opacity .3s ease-out;
|
-webkit-transition: opacity 0.3s ease-out;
|
||||||
|
-o-transition: opacity 0.3s ease-out;
|
||||||
|
transition: opacity 0.3s ease-out;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
background: rgba(0, 0, 0, 0.7) !important;
|
background: rgba(0, 0, 0, 0.7) !important;
|
||||||
|
-webkit-backdrop-filter: none !important;
|
||||||
backdrop-filter: none !important;
|
backdrop-filter: none !important;
|
||||||
color: #eee !important;
|
color: #eee !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.osdHeader-hidden {
|
.osdHeader-hidden {
|
||||||
opacity: 0
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.osdHeader .headerButton:not(.headerBackButton):not(.headerCastButton) {
|
.osdHeader .headerButton:not(.headerBackButton):not(.headerCastButton) {
|
||||||
display: none
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chapterThumbContainer {
|
.chapterThumbContainer {
|
||||||
|
-webkit-box-shadow: 0 0 1.9vh #000;
|
||||||
box-shadow: 0 0 1.9vh #000;
|
box-shadow: 0 0 1.9vh #000;
|
||||||
|
-webkit-box-flex: 1;
|
||||||
|
-webkit-flex-grow: 1;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
position: relative
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chapterThumb {
|
.chapterThumb {
|
||||||
background-position: center center;
|
background-position: center center;
|
||||||
|
-webkit-background-size: contain;
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
border: 0;
|
border: 0;
|
||||||
height: 20vh;
|
height: 20vh;
|
||||||
min-width: 20vh
|
min-width: 20vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (orientation: portrait) {
|
@media all and (orientation: portrait) {
|
||||||
.chapterThumb {
|
.chapterThumb {
|
||||||
height: 30vw;
|
height: 30vw;
|
||||||
min-width: 30vw
|
min-width: 30vw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-height: 50em) and (orientation: landscape) {
|
@media all and (max-height: 50em) and (orientation: landscape) {
|
||||||
.chapterThumb {
|
.chapterThumb {
|
||||||
height: 30vh;
|
height: 30vh;
|
||||||
min-width: 30vh
|
min-width: 30vh;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,161 +72,218 @@
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
background: rgba(0, 0, 0, .7);
|
background: rgba(0, 0, 0, 0.7);
|
||||||
padding: .25em .5em;
|
padding: 0.25em 0.5em;
|
||||||
user-select: none
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chapterThumbText {
|
.chapterThumbText {
|
||||||
padding: .25em 0;
|
padding: 0.25em 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
opacity: 1
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chapterThumbText-dim {
|
.chapterThumbText-dim {
|
||||||
opacity: .6
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.videoOsdBottom {
|
.videoOsdBottom {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
background-color: rgba(0, 0, 0, 0.7);
|
background-color: rgba(0, 0, 0, 0.7);
|
||||||
padding: 1%;
|
padding: 1%;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -webkit-flex;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
-webkit-box-orient: horizontal;
|
||||||
|
-webkit-box-direction: normal;
|
||||||
|
-webkit-flex-direction: row;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
will-change: opacity;
|
will-change: opacity;
|
||||||
|
-webkit-transition: opacity 0.3s ease-out;
|
||||||
|
-o-transition: opacity 0.3s ease-out;
|
||||||
transition: opacity 0.3s ease-out;
|
transition: opacity 0.3s ease-out;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
user-select: none
|
user-select: none;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.videoOsdBottom-hidden {
|
.videoOsdBottom-hidden {
|
||||||
opacity: 0
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.osdControls {
|
.osdControls {
|
||||||
flex-grow: 1
|
-webkit-box-flex: 1;
|
||||||
|
-webkit-flex-grow: 1;
|
||||||
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.videoOsdBottom .buttons {
|
.videoOsdBottom .buttons {
|
||||||
padding: .25em 0 0;
|
padding: 0.25em 0 0;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -webkit-flex;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
-webkit-flex-wrap: wrap;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
align-items: center
|
-webkit-box-align: center;
|
||||||
|
-webkit-align-items: center;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.osdVolumeSliderContainer {
|
.osdVolumeSliderContainer {
|
||||||
width: 9em;
|
width: 9em;
|
||||||
flex-grow: 1
|
-webkit-box-flex: 1;
|
||||||
|
-webkit-flex-grow: 1;
|
||||||
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.osdMediaInfo,
|
.osdMediaInfo,
|
||||||
.volumeButtons {
|
.volumeButtons {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -webkit-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
-webkit-box-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.volumeButtons {
|
.volumeButtons {
|
||||||
margin: 0 .5em 0 auto;
|
margin: 0 0.5em 0 auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center
|
-webkit-align-items: center;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.osdTimeText {
|
.osdTimeText {
|
||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
user-select: none
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.osdPoster {
|
.osdPoster {
|
||||||
width: 10%;
|
width: 10%;
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-right: .5em
|
margin-right: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.osdPoster img {
|
.osdPoster img {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
height: auto;
|
height: auto;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
-webkit-box-shadow: 0 0 1.9vh #000;
|
||||||
box-shadow: 0 0 1.9vh #000;
|
box-shadow: 0 0 1.9vh #000;
|
||||||
border: .08em solid #222;
|
border: 0.08em solid #222;
|
||||||
user-drag: none;
|
user-drag: none;
|
||||||
user-select: none
|
user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-webkit-user-drag: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.osdTitle,
|
.osdTitle,
|
||||||
.osdTitleSmall {
|
.osdTitleSmall {
|
||||||
margin: 0 1em 0 0
|
margin: 0 1em 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.osdMediaInfo {
|
.osdMediaInfo {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center
|
-webkit-align-items: center;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.osdSecondaryMediaInfo {
|
.osdSecondaryMediaInfo {
|
||||||
padding-left: .6em !important
|
padding-left: 0.6em !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.osdTextContainer {
|
.osdTextContainer {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -webkit-flex;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-webkit-align-items: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
margin-bottom: .7em;
|
margin-bottom: 0.7em;
|
||||||
padding-left: .5em
|
padding-left: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.osdMainTextContainer {
|
.osdMainTextContainer {
|
||||||
align-items: baseline
|
-webkit-box-align: baseline;
|
||||||
|
-webkit-align-items: baseline;
|
||||||
|
align-items: baseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.osdMediaStatus {
|
.osdMediaStatus {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@-moz-keyframes spin {
|
||||||
|
100% {
|
||||||
|
-moz-transform: rotate(360deg);
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes spin {
|
||||||
|
100% {
|
||||||
|
-webkit-transform: rotate(360deg);
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes spin {
|
@keyframes spin {
|
||||||
100% {
|
100% {
|
||||||
|
-webkit-transform: rotate(360deg);
|
||||||
transform: rotate(360deg);
|
transform: rotate(360deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.osdMediaStatus .animate {
|
.osdMediaStatus .animate {
|
||||||
|
-webkit-animation: spin 4s linear infinite;
|
||||||
|
-moz-animation: spin 4s linear infinite;
|
||||||
animation: spin 4s linear infinite;
|
animation: spin 4s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pageContainer {
|
.pageContainer {
|
||||||
top: 0;
|
top: 0;
|
||||||
position: fixed
|
position: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 30em) {
|
@media all and (max-width: 30em) {
|
||||||
|
|
||||||
.btnFastForward,
|
.btnFastForward,
|
||||||
.btnRewind,
|
.btnRewind,
|
||||||
.osdMediaInfo,
|
.osdMediaInfo,
|
||||||
.osdPoster {
|
.osdPoster {
|
||||||
display: none !important
|
display: none !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 33.75em) {
|
@media all and (max-width: 33.75em) {
|
||||||
.videoOsdBottom .paper-icon-button-light {
|
.videoOsdBottom .paper-icon-button-light {
|
||||||
margin: 0
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 43em) {
|
@media all and (max-width: 43em) {
|
||||||
.videoOsdBottom .volumeButtons,
|
.videoOsdBottom .volumeButtons,
|
||||||
.osdMediaStatus span {
|
.osdMediaStatus span {
|
||||||
display: none !important
|
display: none !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 50em) {
|
@media all and (max-width: 50em) {
|
||||||
.videoOsdBottom .btnFastForward, .videoOsdBottom .btnRewind {
|
.videoOsdBottom .btnFastForward,
|
||||||
display: none !important
|
.videoOsdBottom .btnRewind {
|
||||||
|
display: none !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 75em) {
|
@media all and (max-width: 75em) {
|
||||||
.videoOsdBottom .endsAtText {
|
.videoOsdBottom .endsAtText {
|
||||||
display: none !important
|
display: none !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
@ -1,4 +1,4 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M24 19H0a13.6 13.6 0 0 1 2.21-6.07A11.2 11.2 0 0 1 5.87 9.4l.41-.23-2.02-3.41a.51.51 0 0 1 .17-.7.5.5 0 0 1 .69.18l2.08 3.5a12.62 12.62 0 0 1 4.84-.9 12.2 12.2 0 0 1 4.75.9l2.07-3.5a.5.5 0 0 1 .7-.17.51.51 0 0 1 .16.7L17.7 9.19l.5.28a11.38 11.38 0 0 1 3.63 3.62A14.48 14.48 0 0 1 24 19zm-7.5-4.48a1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0-1-1 1 1 0 0 0-1 1zm-11 0a1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0-1-1 1 1 0 0 0-1 1z"/>
|
<path d="M24 19H0a13.6 13.6 0 0 1 2.21-6.07A11.2 11.2 0 0 1 5.87 9.4l.41-.23-2.02-3.41a.51.51 0 0 1 .17-.7.5.5 0 0 1 .69.18l2.08 3.5a12.62 12.62 0 0 1 4.84-.9 12.2 12.2 0 0 1 4.75.9l2.07-3.5a.5.5 0 0 1 .7-.17.51.51 0 0 1 .16.7L17.7 9.19l.5.28a11.38 11.38 0 0 1 3.63 3.62A14.48 14.48 0 0 1 24 19zm-7.5-4.48a1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0-1-1 1 1 0 0 0-1 1zm-11 0a1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0-1-1 1 1 0 0 0-1 1z" fill="#fff"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 551 B After Width: | Height: | Size: 563 B |
20
src/assets/img/fresh.svg
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
<svg id="svg3390" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="141.25" viewBox="0 0 138.75 141.25" width="138.75" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
|
<metadata id="metadata3396">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||||
|
<dc:title/>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g id="layer1" fill="#f93208">
|
||||||
|
<path id="path3412" d="m20.154 40.829c-28.149 27.622-13.657 61.011-5.734 71.931 35.254 41.954 92.792 25.339 111.89-5.9071 4.7608-8.2027 22.554-53.467-23.976-78.009z"/>
|
||||||
|
<path id="path3471" d="m39.613 39.265 4.7778-8.8607 28.406-5.0384 11.119 9.2082z"/>
|
||||||
|
</g>
|
||||||
|
<g id="layer2">
|
||||||
|
<path id="path3437" d="m39.436 8.5696 8.9682-5.2826 6.7569 15.479c3.7925-6.3226 13.79-16.316 24.939-4.6684-4.7281 1.2636-7.5161 3.8553-7.7397 8.4768 15.145-4.1697 31.343 3.2127 33.539 9.0911-10.951-4.314-27.695 10.377-41.771 2.334 0.009 15.045-12.617 16.636-19.902 17.076 2.077-4.996 5.591-9.994 1.474-14.987-7.618 8.171-13.874 10.668-33.17 4.668 4.876-1.679 14.843-11.39 24.448-11.425-6.775-2.467-12.29-2.087-17.814-1.475 2.917-3.961 12.149-15.197 28.625-8.476z" fill="#02902e"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
1
src/assets/img/rotten.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="145" height="140"><path fill="#0fc755" d="M47.4 35.342c-13.607-7.935-12.32-25.203 2.097-31.88 26.124-6.531 29.117 13.78 22.652 30.412-6.542 24.11 18.095 23.662 19.925 10.067 3.605-18.412 19.394-26.695 31.67-16.359 12.598 12.135 7.074 36.581-17.827 34.187-16.03-1.545-19.552 19.585.839 21.183 32.228 1.915 42.49 22.167 31.04 35.865-15.993 15.15-37.691-4.439-45.512-19.505-6.8-9.307-17.321.11-13.423 6.502 12.983 19.465 2.923 31.229-10.906 30.62-13.37-.85-20.96-9.06-13.214-29.15 3.897-12.481-8.595-15.386-16.57-5.45-11.707 19.61-28.865 13.68-33.976 4.19-3.243-7.621-2.921-25.846 24.119-23.696 16.688 4.137 11.776-12.561-.63-13.633-9.245-.443-30.501-7.304-22.86-24.54 7.34-11.056 24.958-11.768 33.348 6.293 3.037 4.232 8.361 11.042 18.037 5.033 3.51-5.197 1.21-13.9-8.809-20.135z"/></svg>
|
After Width: | Height: | Size: 833 B |
168
src/bundle.js
|
@ -5,94 +5,174 @@
|
||||||
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;
|
||||||
|
});
|
||||||
|
|
||||||
|
// query-string
|
||||||
|
var query = require('query-string');
|
||||||
|
_define('queryString', function() {
|
||||||
|
return query;
|
||||||
});
|
});
|
||||||
|
|
||||||
// flvjs
|
// flvjs
|
||||||
var flvjs = require("flv.js").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;
|
||||||
});
|
});
|
||||||
|
|
||||||
// native-promise-only
|
|
||||||
var nativePromise = require("native-promise-only");
|
|
||||||
_define("native-promise-only", function() {
|
|
||||||
return nativePromise;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 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");
|
var swiper = require('swiper/js/swiper');
|
||||||
require("swiper/dist/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;
|
||||||
});
|
|
||||||
|
|
||||||
// libjass
|
|
||||||
var libjass = require("libjass");
|
|
||||||
require("libjass/libjass.css");
|
|
||||||
_define("libjass", function() {
|
|
||||||
return libjass;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 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
|
||||||
|
var materialIcons = require('material-design-icons-iconfont/dist/material-design-icons.css');
|
||||||
|
_define('material-icons', function() {
|
||||||
|
return materialIcons;
|
||||||
|
});
|
||||||
|
|
||||||
|
// noto font
|
||||||
|
var noto = require('jellyfin-noto');
|
||||||
|
_define('jellyfin-noto', function () {
|
||||||
|
return noto;
|
||||||
|
});
|
||||||
|
|
||||||
|
// page.js
|
||||||
|
var page = require('page');
|
||||||
|
_define('page', function() {
|
||||||
|
return page;
|
||||||
|
});
|
||||||
|
|
||||||
|
// core-js
|
||||||
|
var polyfill = require('@babel/polyfill/dist/polyfill');
|
||||||
|
_define('polyfill', function () {
|
||||||
|
return polyfill;
|
||||||
|
});
|
||||||
|
|
||||||
|
// domtokenlist-shim
|
||||||
|
var classlist = require('classlist.js');
|
||||||
|
_define('classlist-polyfill', function () {
|
||||||
|
return classlist;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Date-FNS
|
||||||
|
var dateFns = require('date-fns');
|
||||||
|
_define('date-fns', function () {
|
||||||
|
return dateFns;
|
||||||
|
});
|
||||||
|
|
||||||
|
var dateFnsLocale = require('date-fns/locale');
|
||||||
|
_define('date-fns/locale', function () {
|
||||||
|
return dateFnsLocale;
|
||||||
|
});
|
||||||
|
|
||||||
|
var fast_text_encoding = require('fast-text-encoding');
|
||||||
|
_define('fast-text-encoding', function () {
|
||||||
|
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;
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
define(["dialogHelper", "datetime", "emby-select", "paper-icon-button-light", "formDialogStyle"], function (dialogHelper, datetime) {
|
define(['dialogHelper', 'datetime', 'globalize', 'emby-select', 'paper-icon-button-light', 'formDialogStyle'], function (dialogHelper, datetime, globalize) {
|
||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
function getDisplayTime(hours) {
|
function getDisplayTime(hours) {
|
||||||
var minutes = 0;
|
var minutes = 0;
|
||||||
|
@ -13,32 +13,32 @@ define(["dialogHelper", "datetime", "emby-select", "paper-icon-button-light", "f
|
||||||
}
|
}
|
||||||
|
|
||||||
function populateHours(context) {
|
function populateHours(context) {
|
||||||
var html = "";
|
var html = '';
|
||||||
|
|
||||||
for (var i = 0; i < 24; i++) {
|
for (var i = 0; i < 24; i++) {
|
||||||
html += '<option value="' + i + '">' + getDisplayTime(i) + "</option>";
|
html += '<option value="' + i + '">' + getDisplayTime(i) + '</option>';
|
||||||
}
|
}
|
||||||
|
|
||||||
html += '<option value="24">' + getDisplayTime(0) + "</option>";
|
html += '<option value="24">' + getDisplayTime(0) + '</option>';
|
||||||
context.querySelector("#selectStart").innerHTML = html;
|
context.querySelector('#selectStart').innerHTML = html;
|
||||||
context.querySelector("#selectEnd").innerHTML = html;
|
context.querySelector('#selectEnd').innerHTML = html;
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadSchedule(context, schedule) {
|
function loadSchedule(context, schedule) {
|
||||||
context.querySelector("#selectDay").value = schedule.DayOfWeek || "Sunday";
|
context.querySelector('#selectDay').value = schedule.DayOfWeek || 'Sunday';
|
||||||
context.querySelector("#selectStart").value = schedule.StartHour || 0;
|
context.querySelector('#selectStart').value = schedule.StartHour || 0;
|
||||||
context.querySelector("#selectEnd").value = schedule.EndHour || 0;
|
context.querySelector('#selectEnd').value = schedule.EndHour || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function submitSchedule(context, options) {
|
function submitSchedule(context, options) {
|
||||||
var updatedSchedule = {
|
var updatedSchedule = {
|
||||||
DayOfWeek: context.querySelector("#selectDay").value,
|
DayOfWeek: context.querySelector('#selectDay').value,
|
||||||
StartHour: context.querySelector("#selectStart").value,
|
StartHour: context.querySelector('#selectStart').value,
|
||||||
EndHour: context.querySelector("#selectEnd").value
|
EndHour: context.querySelector('#selectEnd').value
|
||||||
};
|
};
|
||||||
|
|
||||||
if (parseFloat(updatedSchedule.StartHour) >= parseFloat(updatedSchedule.EndHour)) {
|
if (parseFloat(updatedSchedule.StartHour) >= parseFloat(updatedSchedule.EndHour)) {
|
||||||
return void alert(Globalize.translate("ErrorMessageStartHourGreaterThanEnd"));
|
return void alert(globalize.translate('ErrorMessageStartHourGreaterThanEnd'));
|
||||||
}
|
}
|
||||||
|
|
||||||
context.submitted = true;
|
context.submitted = true;
|
||||||
|
@ -50,32 +50,32 @@ define(["dialogHelper", "datetime", "emby-select", "paper-icon-button-light", "f
|
||||||
show: function (options) {
|
show: function (options) {
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
xhr.open("GET", "components/accessschedule/accessschedule.template.html", true);
|
xhr.open('GET', 'components/accessschedule/accessschedule.template.html', true);
|
||||||
|
|
||||||
xhr.onload = function (e) {
|
xhr.onload = function (e) {
|
||||||
var template = this.response;
|
var template = this.response;
|
||||||
var dlg = dialogHelper.createDialog({
|
var dlg = dialogHelper.createDialog({
|
||||||
removeOnClose: true,
|
removeOnClose: true,
|
||||||
size: "small"
|
size: 'small'
|
||||||
});
|
});
|
||||||
dlg.classList.add("formDialog");
|
dlg.classList.add('formDialog');
|
||||||
var html = "";
|
var html = '';
|
||||||
html += Globalize.translateDocument(template);
|
html += globalize.translateDocument(template);
|
||||||
dlg.innerHTML = html;
|
dlg.innerHTML = html;
|
||||||
populateHours(dlg);
|
populateHours(dlg);
|
||||||
loadSchedule(dlg, options.schedule);
|
loadSchedule(dlg, options.schedule);
|
||||||
dialogHelper.open(dlg);
|
dialogHelper.open(dlg);
|
||||||
dlg.addEventListener("close", function () {
|
dlg.addEventListener('close', function () {
|
||||||
if (dlg.submitted) {
|
if (dlg.submitted) {
|
||||||
resolve(options.schedule);
|
resolve(options.schedule);
|
||||||
} else {
|
} else {
|
||||||
reject();
|
reject();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
dlg.querySelector(".btnCancel").addEventListener("click", function (e) {
|
dlg.querySelector('.btnCancel').addEventListener('click', function (e) {
|
||||||
dialogHelper.close(dlg);
|
dialogHelper.close(dlg);
|
||||||
});
|
});
|
||||||
dlg.querySelector("form").addEventListener("submit", function (e) {
|
dlg.querySelector('form').addEventListener('submit', function (e) {
|
||||||
submitSchedule(dlg, options);
|
submitSchedule(dlg, options);
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -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="md-icon">arrow_back</i>
|
<span class="material-icons arrow_back" aria-hidden="true"></span>
|
||||||
</button>
|
</button>
|
||||||
<h3 class="formDialogHeaderTitle">
|
<h3 class="formDialogHeaderTitle">
|
||||||
${HeaderAccessSchedule}
|
${HeaderAccessSchedule}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border: none;
|
border: none;
|
||||||
max-height: 84%;
|
max-height: 84%;
|
||||||
border-radius: .1em !important;
|
border-radius: 0.1em !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.actionsheet-not-fullscreen {
|
.actionsheet-not-fullscreen {
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
.actionSheetContent {
|
.actionSheetContent {
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
padding: .4em 0 !important;
|
padding: 0.4em 0 !important;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -45,7 +45,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.actionsheetListItemBody {
|
.actionsheetListItemBody {
|
||||||
padding: .4em 1em .4em .6em !important;
|
padding: 0.4em 1em 0.4em 0.6em !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.actionSheetItemText {
|
.actionSheetItemText {
|
||||||
|
@ -59,13 +59,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.actionSheetItemAsideText {
|
.actionSheetItemAsideText {
|
||||||
opacity: .7;
|
opacity: 0.7;
|
||||||
font-size: 90%;
|
font-size: 90%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
margin-left: 5em;
|
margin-left: 5em;
|
||||||
margin-right: .5em;
|
margin-right: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.actionSheetScroller {
|
.actionSheetScroller {
|
||||||
|
@ -83,14 +83,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.actionsheetDivider {
|
.actionsheetDivider {
|
||||||
height: .07em;
|
height: 0.07em;
|
||||||
margin: .25em 0;
|
margin: 0.25em 0;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.actionSheetTitle {
|
.actionSheetTitle {
|
||||||
margin: .6em 0 .7em !important;
|
margin: 0.6em 0 0.7em !important;
|
||||||
padding: 0 .9em;
|
padding: 0 0.9em;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.actionsheetMenuItemIcon {
|
.actionsheetMenuItemIcon {
|
||||||
margin: 0 .85em 0 .45em !important;
|
margin: 0 0.85em 0 0.45em !important;
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,6 +110,6 @@
|
||||||
|
|
||||||
.btnCloseActionSheet {
|
.btnCloseActionSheet {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: .75em;
|
top: 0.75em;
|
||||||
left: .5em;
|
left: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,7 +136,7 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'browser', 'dom', 'emby-bu
|
||||||
// Admittedly a hack but right now the scrollbar is being factored into the width which is causing truncation
|
// Admittedly a hack but right now the scrollbar is being factored into the width which is causing truncation
|
||||||
if (options.items.length > 20) {
|
if (options.items.length > 20) {
|
||||||
var minWidth = dom.getWindowSize().innerWidth >= 300 ? 240 : 200;
|
var minWidth = dom.getWindowSize().innerWidth >= 300 ? 240 : 200;
|
||||||
style += "min-width:" + minWidth + "px;";
|
style += 'min-width:' + minWidth + 'px;';
|
||||||
}
|
}
|
||||||
|
|
||||||
var i;
|
var i;
|
||||||
|
@ -158,7 +158,7 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'browser', 'dom', 'emby-bu
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layoutManager.tv) {
|
if (layoutManager.tv) {
|
||||||
html += '<button is="paper-icon-button-light" class="btnCloseActionSheet hide-mouse-idle-tv" tabindex="-1"><i class="md-icon">arrow_back</i></button>';
|
html += '<button is="paper-icon-button-light" class="btnCloseActionSheet hide-mouse-idle-tv" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
|
||||||
}
|
}
|
||||||
|
|
||||||
// If any items have an icon, give them all an icon just to make sure they're all lined up evenly
|
// If any items have an icon, give them all an icon just to make sure they're all lined up evenly
|
||||||
|
@ -226,9 +226,9 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'browser', 'dom', 'emby-bu
|
||||||
|
|
||||||
if (itemIcon) {
|
if (itemIcon) {
|
||||||
|
|
||||||
html += '<i class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent md-icon">' + itemIcon + '</i>';
|
html += '<span class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons ' + itemIcon + '"></span>';
|
||||||
} else if (renderIcon && !center) {
|
} else if (renderIcon && !center) {
|
||||||
html += '<i class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent md-icon" style="visibility:hidden;">check</i>';
|
html += '<span class="actionsheetMenuItemIcon listItemIcon listItemIcon-transparent material-icons check" style="visibility:hidden;"></span>';
|
||||||
}
|
}
|
||||||
|
|
||||||
html += '<div class="listItemBody actionsheetListItemBody">';
|
html += '<div class="listItemBody actionsheetListItemBody">';
|
||||||
|
|
|
@ -1,60 +1,59 @@
|
||||||
define(["events", "globalize", "dom", "datetime", "userSettings", "serverNotifications", "connectionManager", "emby-button", "listViewStyle"], function (events, globalize, dom, datetime, 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 md-icon" 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 md-icon" 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">';
|
||||||
var date = datetime.parseISO8601Date(entry.Date, true);
|
html += datefns.formatRelative(Date.parse(entry.Date), Date.parse(new Date()), { locale: dfnshelper.getLocale() });
|
||||||
html += datetime.toLocaleString(date).toLowerCase();
|
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="md-icon">info</i></button>';
|
html += '<button type="button" is="paper-icon-button-light" class="btnEntryInfo" data-id="' + entry.Id + '" title="' + globalize.translate('Info') + '"><span class="material-icons info"></span></button>';
|
||||||
}
|
}
|
||||||
|
|
||||||
return html += "</div>";
|
return html += '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderList(elem, apiClient, result, startIndex, limit) {
|
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
|
||||||
|
@ -62,22 +61,22 @@ define(["events", "globalize", "dom", "datetime", "userSettings", "serverNotific
|
||||||
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');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,10 +95,10 @@ define(["events", "globalize", "dom", "datetime", "userSettings", "serverNotific
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
@ -115,7 +114,7 @@ define(["events", "globalize", "dom", "datetime", "userSettings", "serverNotific
|
||||||
}
|
}
|
||||||
|
|
||||||
function showItemOverview(item) {
|
function showItemOverview(item) {
|
||||||
require(["alert"], function (alert) {
|
require(['alert'], function (alert) {
|
||||||
alert({
|
alert({
|
||||||
text: item.Overview
|
text: item.Overview
|
||||||
});
|
});
|
||||||
|
@ -125,28 +124,28 @@ define(["events", "globalize", "dom", "datetime", "userSettings", "serverNotific
|
||||||
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="md-icon 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="md-icon 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
|
||||||
|
@ -241,7 +241,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
|
||||||
try {
|
try {
|
||||||
btn = element.querySelector('.alphaPickerButton[data-value=\'' + value + '\']');
|
btn = element.querySelector('.alphaPickerButton[data-value=\'' + value + '\']');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('Error in querySelector: ' + err);
|
console.error('error in querySelector: ' + err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (btn && btn !== selected) {
|
if (btn && btn !== selected) {
|
||||||
|
@ -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
|
||||||
|
|
|
@ -35,16 +35,15 @@
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
min-width: initial;
|
min-width: initial;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: .1em .4em;
|
padding: 0.1em 0.4em;
|
||||||
width: auto;
|
width: auto;
|
||||||
border-radius: .1em;
|
border-radius: 0.1em;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-height: 50em) {
|
@media all and (max-height: 50em) {
|
||||||
|
|
||||||
.alphaPicker-fixed {
|
.alphaPicker-fixed {
|
||||||
bottom: 5em;
|
bottom: 5em;
|
||||||
}
|
}
|
||||||
|
@ -56,14 +55,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-height: 49em) {
|
@media all and (max-height: 49em) {
|
||||||
|
|
||||||
.alphaPicker-vertical {
|
.alphaPicker-vertical {
|
||||||
font-size: 94%;
|
font-size: 94%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-height: 44em) {
|
@media all and (max-height: 44em) {
|
||||||
|
|
||||||
.alphaPicker-vertical {
|
.alphaPicker-vertical {
|
||||||
font-size: 90%;
|
font-size: 90%;
|
||||||
}
|
}
|
||||||
|
@ -75,14 +72,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-height: 37em) {
|
@media all and (max-height: 37em) {
|
||||||
|
|
||||||
.alphaPicker-vertical {
|
.alphaPicker-vertical {
|
||||||
font-size: 82%;
|
font-size: 82%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-height: 32em) {
|
@media all and (max-height: 32em) {
|
||||||
|
|
||||||
.alphaPicker-vertical {
|
.alphaPicker-vertical {
|
||||||
font-size: 74%;
|
font-size: 74%;
|
||||||
}
|
}
|
||||||
|
@ -112,27 +107,17 @@
|
||||||
bottom: 1%;
|
bottom: 1%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.alphaPicker-fixed-left {
|
|
||||||
left: .4em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alphaPicker-fixed-right {
|
.alphaPicker-fixed-right {
|
||||||
right: .4em;
|
right: 0.4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (min-width: 62.5em) {
|
@media all and (min-width: 62.5em) {
|
||||||
|
|
||||||
.alphaPicker-fixed-left {
|
|
||||||
left: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alphaPicker-fixed-right {
|
.alphaPicker-fixed-right {
|
||||||
right: 1em;
|
right: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-height: 31.25em) {
|
@media all and (max-height: 31.25em) {
|
||||||
|
|
||||||
.alphaPicker-fixed {
|
.alphaPicker-fixed {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,9 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
},
|
},
|
||||||
showSettings: function () {
|
showSettings: function () {
|
||||||
show('/settings/settings.html');
|
show('/settings/settings.html');
|
||||||
|
},
|
||||||
|
showNowPlaying: function () {
|
||||||
|
show('/nowplaying.html');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -197,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;
|
||||||
|
|
||||||
|
@ -265,6 +268,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) {
|
||||||
|
@ -276,6 +280,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* eslint-enable compat/compat */
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -367,7 +372,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
}
|
}
|
||||||
|
|
||||||
function enableNativeHistory() {
|
function enableNativeHistory() {
|
||||||
return page.enableNativeHistory();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function authenticate(ctx, route, callback) {
|
function authenticate(ctx, route, callback) {
|
||||||
|
@ -387,13 +392,13 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
var apiClient = connectionManager.currentApiClient();
|
var apiClient = connectionManager.currentApiClient();
|
||||||
var pathname = ctx.pathname.toLowerCase();
|
var pathname = ctx.pathname.toLowerCase();
|
||||||
|
|
||||||
console.log('appRouter - processing path request ' + pathname);
|
console.debug('appRouter - processing path request ' + pathname);
|
||||||
|
|
||||||
var isCurrentRouteStartup = currentRouteInfo ? currentRouteInfo.route.startup : true;
|
var isCurrentRouteStartup = currentRouteInfo ? currentRouteInfo.route.startup : true;
|
||||||
var shouldExitApp = ctx.isBack && route.isDefaultRoute && isCurrentRouteStartup;
|
var shouldExitApp = ctx.isBack && route.isDefaultRoute && isCurrentRouteStartup;
|
||||||
|
|
||||||
if (!shouldExitApp && (!apiClient || !apiClient.isLoggedIn()) && !route.anonymous) {
|
if (!shouldExitApp && (!apiClient || !apiClient.isLoggedIn()) && !route.anonymous) {
|
||||||
console.log('appRouter - route does not allow anonymous access, redirecting to login');
|
console.debug('appRouter - route does not allow anonymous access, redirecting to login');
|
||||||
beginConnectionWizard();
|
beginConnectionWizard();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -408,10 +413,10 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
|
|
||||||
if (apiClient && apiClient.isLoggedIn()) {
|
if (apiClient && apiClient.isLoggedIn()) {
|
||||||
|
|
||||||
console.log('appRouter - user is authenticated');
|
console.debug('appRouter - user is authenticated');
|
||||||
|
|
||||||
if (route.isDefaultRoute) {
|
if (route.isDefaultRoute) {
|
||||||
console.log('appRouter - loading skin home page');
|
console.debug('appRouter - loading skin home page');
|
||||||
loadUserSkinWithOptions(ctx);
|
loadUserSkinWithOptions(ctx);
|
||||||
return;
|
return;
|
||||||
} else if (route.roles) {
|
} else if (route.roles) {
|
||||||
|
@ -425,7 +430,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('appRouter - proceeding to ' + pathname);
|
console.debug('appRouter - proceeding to ' + pathname);
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,9 +513,16 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
return baseRoute;
|
return baseRoute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var popstateOccurred = false;
|
||||||
|
window.addEventListener('popstate', function () {
|
||||||
|
popstateOccurred = true;
|
||||||
|
});
|
||||||
|
|
||||||
function getHandler(route) {
|
function getHandler(route) {
|
||||||
return function (ctx, next) {
|
return function (ctx, next) {
|
||||||
|
ctx.isBack = popstateOccurred;
|
||||||
handleRoute(ctx, next, route);
|
handleRoute(ctx, next, route);
|
||||||
|
popstateOccurred = false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,15 +541,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, ' '));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,22 +557,31 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
page.back();
|
page.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pages of "no return" (when "Go back" should behave differently, probably quitting the application).
|
||||||
|
*/
|
||||||
|
var startPages = ['home', 'login', 'selectserver'];
|
||||||
|
|
||||||
function canGoBack() {
|
function canGoBack() {
|
||||||
var curr = current();
|
var curr = current();
|
||||||
if (!curr) {
|
if (!curr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curr.type === 'home') {
|
if (!document.querySelector('.dialogContainer') && startPages.indexOf(curr.type) !== -1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return page.canGoBack();
|
if (enableHistory()) {
|
||||||
|
return history.length > 1;
|
||||||
|
}
|
||||||
|
return (page.len || 0) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function show(path, options) {
|
function show(path, options) {
|
||||||
|
@ -658,7 +679,8 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
|
|
||||||
function pushState(state, title, url) {
|
function pushState(state, title, url) {
|
||||||
state.navigate = false;
|
state.navigate = false;
|
||||||
page.pushState(state, title, url);
|
history.pushState(state, title, url);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setBaseRoute() {
|
function setBaseRoute() {
|
||||||
|
@ -667,7 +689,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
baseRoute = baseRoute.substring(0, baseRoute.length - 1);
|
baseRoute = baseRoute.substring(0, baseRoute.length - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Setting page base to ' + baseRoute);
|
console.debug('setting page base to ' + baseRoute);
|
||||||
page.base(baseRoute);
|
page.base(baseRoute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,7 +730,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'layoutManager', 'skinM
|
||||||
appRouter.getRoutes = getRoutes;
|
appRouter.getRoutes = getRoutes;
|
||||||
appRouter.pushState = pushState;
|
appRouter.pushState = pushState;
|
||||||
appRouter.enableNativeHistory = enableNativeHistory;
|
appRouter.enableNativeHistory = enableNativeHistory;
|
||||||
appRouter.handleAnchorClick = page.handleAnchorClick;
|
appRouter.handleAnchorClick = page.clickHandler;
|
||||||
appRouter.TransparencyLevel = {
|
appRouter.TransparencyLevel = {
|
||||||
None: 0,
|
None: 0,
|
||||||
Backdrop: 1,
|
Backdrop: 1,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 1;
|
z-index: 10;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
transition: transform 180ms linear;
|
transition: transform 180ms linear;
|
||||||
contain: layout style;
|
contain: layout style;
|
||||||
|
|
|
@ -2,24 +2,18 @@ define(['browser', 'css!./appfooter'], function (browser) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function render(options) {
|
function render(options) {
|
||||||
|
|
||||||
var elem = document.createElement('div');
|
var elem = document.createElement('div');
|
||||||
|
|
||||||
elem.classList.add('appfooter');
|
elem.classList.add('appfooter');
|
||||||
|
|
||||||
elem.classList.add('appfooter-blurred');
|
|
||||||
|
|
||||||
document.body.appendChild(elem);
|
document.body.appendChild(elem);
|
||||||
|
|
||||||
return elem;
|
return elem;
|
||||||
}
|
}
|
||||||
|
|
||||||
function appFooter(options) {
|
function appFooter(options) {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
self.element = render(options);
|
self.element = render(options);
|
||||||
|
|
||||||
self.add = function (elem) {
|
self.add = function (elem) {
|
||||||
self.element.appendChild(elem);
|
self.element.appendChild(elem);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSettings, browser, events, htmlMediaHelper) {
|
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 || browser.msie) {
|
||||||
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"], function (appSet
|
||||||
|
|
||||||
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"], function (appSet
|
||||||
}
|
}
|
||||||
|
|
||||||
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"], function (appSet
|
||||||
}
|
}
|
||||||
|
|
||||||
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"], function (appSet
|
||||||
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"], function (appSet
|
||||||
}
|
}
|
||||||
|
|
||||||
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,16 +93,16 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
|
||||||
|
|
||||||
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" : "Web Browser";
|
deviceName = browser.tizen ? 'Samsung Smart TV' : browser.web0s ? 'LG Smart TV' : browser.operaTv ? 'Opera TV' : browser.xboxOne ? 'Xbox One' : browser.ps4 ? 'Sony PS4' : browser.chrome ? 'Chrome' : browser.edge ? 'Edge' : browser.firefox ? 'Firefox' : browser.msie ? 'Internet Explorer' : browser.opera ? 'Opera' : browser.safari ? 'Safari' : 'Web Browser';
|
||||||
|
|
||||||
if (browser.ipad) {
|
if (browser.ipad) {
|
||||||
deviceName += " iPad";
|
deviceName += ' iPad';
|
||||||
} else {
|
} else {
|
||||||
if (browser.iphone) {
|
if (browser.iphone) {
|
||||||
deviceName += " iPhone";
|
deviceName += ' iPhone';
|
||||||
} else {
|
} else {
|
||||||
if (browser.android) {
|
if (browser.android) {
|
||||||
deviceName += " Android";
|
deviceName += ' Android';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,12 +124,12 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
|
||||||
}
|
}
|
||||||
|
|
||||||
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 +145,7 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDefaultLayout() {
|
function getDefaultLayout() {
|
||||||
return "desktop";
|
return 'desktop';
|
||||||
}
|
}
|
||||||
|
|
||||||
function supportsHtmlMediaAutoplay() {
|
function supportsHtmlMediaAutoplay() {
|
||||||
|
@ -168,23 +157,25 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var savedResult = appSettings.get(htmlMediaAutoplayAppStorageKey);
|
return true;
|
||||||
return "true" === savedResult || "false" !== savedResult && null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function cueSupported() {
|
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.log("Error detecting cue support:" + err);
|
console.error('error detecting cue support: ' + err);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,150 +183,172 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
|
||||||
function onAppVisible() {
|
function onAppVisible() {
|
||||||
if (isHidden) {
|
if (isHidden) {
|
||||||
isHidden = false;
|
isHidden = false;
|
||||||
console.log("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.log("app is hidden");
|
console.debug('app is hidden');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var htmlMediaAutoplayAppStorageKey = "supportshtmlmediaautoplay0";
|
|
||||||
|
|
||||||
var supportedFeatures = function () {
|
var supportedFeatures = function () {
|
||||||
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');
|
||||||
// allows users to connect to more than one server
|
features.push('screensaver');
|
||||||
//features.push("multiserver");
|
|
||||||
features.push("screensaver");
|
|
||||||
|
|
||||||
if (!browser.orsay && !browser.tizen && !browser.msie && (browser.firefox || browser.ps4 || browser.edge || cueSupported())) {
|
webSettings.enableMultiServer().then(enabled => {
|
||||||
features.push("subtitleappearancesettings");
|
if (enabled) features.push('multiserver');
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!browser.orsay && !browser.msie && (browser.firefox || browser.ps4 || browser.edge || supportsCue())) {
|
||||||
|
features.push('subtitleappearancesettings');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!browser.orsay && !browser.tizen) {
|
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;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
if (supportedFeatures.indexOf("htmlvideoautoplay") === -1 && supportsHtmlMediaAutoplay() !== false) {
|
/**
|
||||||
require(["autoPlayDetect"], function (autoPlayDetect) {
|
* Do exit according to platform
|
||||||
autoPlayDetect.supportsHtmlMediaAutoplay().then(function () {
|
*/
|
||||||
appSettings.set(htmlMediaAutoplayAppStorageKey, "true");
|
function doExit() {
|
||||||
supportedFeatures.push("htmlvideoautoplay");
|
try {
|
||||||
supportedFeatures.push("htmlaudioautoplay");
|
if (window.NativeShell) {
|
||||||
}, function () {
|
window.NativeShell.AppHost.exit();
|
||||||
appSettings.set(htmlMediaAutoplayAppStorageKey, "false");
|
} else if (browser.tizen) {
|
||||||
|
tizen.application.getCurrentApplication().exit();
|
||||||
|
} else if (browser.web0s) {
|
||||||
|
webOS.platformBack();
|
||||||
|
} else {
|
||||||
|
window.close();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('error closing application: ' + err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var exitPromise;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ask user for exit
|
||||||
|
*/
|
||||||
|
function askForExit() {
|
||||||
|
if (exitPromise) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
require(['actionsheet'], function (actionsheet) {
|
||||||
|
exitPromise = actionsheet.show({
|
||||||
|
title: globalize.translate('MessageConfirmAppExit'),
|
||||||
|
items: [
|
||||||
|
{id: 'yes', name: globalize.translate('Yes')},
|
||||||
|
{id: 'no', name: globalize.translate('No')}
|
||||||
|
]
|
||||||
|
}).then(function (value) {
|
||||||
|
if (value === 'yes') {
|
||||||
|
doExit();
|
||||||
|
}
|
||||||
|
}).finally(function () {
|
||||||
|
exitPromise = null;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
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.NativeShell) {
|
if (!!window.appMode && browser.tizen) {
|
||||||
window.NativeShell.AppHost.exit();
|
askForExit();
|
||||||
} else if (browser.tizen) {
|
|
||||||
try {
|
|
||||||
tizen.application.getCurrentApplication().exit();
|
|
||||||
} catch (err) {
|
|
||||||
console.log("error closing application: " + err);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
window.close();
|
doExit();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
supports: function (command) {
|
supports: function (command) {
|
||||||
|
@ -346,14 +359,14 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
|
||||||
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 ? "dots-vert" : "dots-horiz",
|
moreIcon: browser.android ? 'more_vert' : 'more_horiz',
|
||||||
getSyncProfile: getSyncProfile,
|
getSyncProfile: getSyncProfile,
|
||||||
getDefaultLayout: function () {
|
getDefaultLayout: function () {
|
||||||
if (window.NativeShell) {
|
if (window.NativeShell) {
|
||||||
return window.NativeShell.AppHost.getDefaultLayout();
|
return window.NativeShell.AppHost.getDefaultLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
return getDefaultLayout()
|
return getDefaultLayout();
|
||||||
},
|
},
|
||||||
getDeviceProfile: getDeviceProfile,
|
getDeviceProfile: getDeviceProfile,
|
||||||
init: function () {
|
init: function () {
|
||||||
|
@ -382,58 +395,44 @@ define(["appSettings", "browser", "events", "htmlMediaHelper"], function (appSet
|
||||||
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;
|
|
||||||
|
|
||||||
if (doc) {
|
|
||||||
if (void 0 !== doc.visibilityState) {
|
|
||||||
visibilityChange = "visibilitychange";
|
|
||||||
visibilityState = "hidden";
|
|
||||||
} else {
|
|
||||||
if (void 0 !== doc.mozHidden) {
|
|
||||||
visibilityChange = "mozvisibilitychange";
|
|
||||||
visibilityState = "mozVisibilityState";
|
|
||||||
} else {
|
|
||||||
if (void 0 !== doc.msHidden) {
|
|
||||||
visibilityChange = "msvisibilitychange";
|
|
||||||
visibilityState = "msVisibilityState";
|
|
||||||
} else {
|
|
||||||
if (void 0 !== doc.webkitHidden) {
|
|
||||||
visibilityChange = "webkitvisibilitychange";
|
|
||||||
visibilityState = "webkitVisibilityState";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var isHidden = false;
|
var isHidden = false;
|
||||||
|
var hidden;
|
||||||
|
var visibilityChange;
|
||||||
|
|
||||||
if (doc) {
|
if (typeof document.hidden !== 'undefined') { /* eslint-disable-line compat/compat */
|
||||||
doc.addEventListener(visibilityChange, function () {
|
hidden = 'hidden';
|
||||||
if (document[visibilityState]) {
|
visibilityChange = 'visibilitychange';
|
||||||
|
} else if (typeof document.webkitHidden !== 'undefined') {
|
||||||
|
hidden = 'webkitHidden';
|
||||||
|
visibilityChange = 'webkitvisibilitychange';
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener(visibilityChange, function () {
|
||||||
|
/* eslint-disable-next-line compat/compat */
|
||||||
|
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;
|
||||||
|
|
|
@ -1,71 +1,73 @@
|
||||||
define(["focusManager", "layoutManager"], function (focusManager, layoutManager) {
|
/* eslint-disable indent */
|
||||||
"use strict";
|
|
||||||
|
/**
|
||||||
|
* Module for performing auto-focus.
|
||||||
|
* @module components/autoFocuser
|
||||||
|
*/
|
||||||
|
|
||||||
|
import focusManager from 'focusManager';
|
||||||
|
import layoutManager from 'layoutManager';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Previously selected element.
|
* Previously selected element.
|
||||||
*/
|
*/
|
||||||
var activeElement;
|
let activeElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if AutoFocuser is enabled.
|
* Returns _true_ if AutoFocuser is enabled.
|
||||||
*/
|
*/
|
||||||
function isEnabled() {
|
export function isEnabled() {
|
||||||
return layoutManager.tv;
|
return layoutManager.tv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start AutoFocuser
|
* Start AutoFocuser.
|
||||||
*/
|
*/
|
||||||
function enable() {
|
export function enable() {
|
||||||
if (!isEnabled()) {
|
if (!isEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("focusin", function (e) {
|
window.addEventListener('focusin', function (e) {
|
||||||
activeElement = e.target;
|
activeElement = e.target;
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("AutoFocuser enabled");
|
console.debug('AutoFocuser enabled');
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an array from some source.
|
|
||||||
*/
|
|
||||||
var arrayFrom = Array.prototype.from || function (src) {
|
|
||||||
return Array.prototype.slice.call(src);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set focus on a suitable element, taking into account the previously selected.
|
* Set focus on a suitable element, taking into account the previously selected.
|
||||||
|
* @param {HTMLElement} [container] - Element to limit scope.
|
||||||
|
* @returns {HTMLElement} Focused element.
|
||||||
*/
|
*/
|
||||||
function autoFocus(container) {
|
export function autoFocus(container) {
|
||||||
if (!isEnabled()) {
|
if (!isEnabled()) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
container = container || document.body;
|
container = container || document.body;
|
||||||
|
|
||||||
var candidates = [];
|
let candidates = [];
|
||||||
|
|
||||||
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(arrayFrom(container.querySelectorAll(".btnResume")));
|
candidates = candidates.concat(Array.from(container.querySelectorAll('.btnResume')));
|
||||||
candidates = candidates.concat(arrayFrom(container.querySelectorAll(".btnPlay")));
|
candidates = candidates.concat(Array.from(container.querySelectorAll('.btnPlay')));
|
||||||
|
|
||||||
var focusedElement;
|
let focusedElement;
|
||||||
|
|
||||||
candidates.every(function (element) {
|
candidates.every(function (element) {
|
||||||
if (focusManager.isCurrentlyFocusable(element)) {
|
if (focusManager.isCurrentlyFocusable(element)) {
|
||||||
|
@ -79,7 +81,7 @@ define(["focusManager", "layoutManager"], function (focusManager, layoutManager)
|
||||||
|
|
||||||
if (!focusedElement) {
|
if (!focusedElement) {
|
||||||
// FIXME: Multiple itemsContainers
|
// FIXME: Multiple itemsContainers
|
||||||
var itemsContainer = container.querySelector(".itemsContainer");
|
const itemsContainer = container.querySelector('.itemsContainer');
|
||||||
|
|
||||||
if (itemsContainer) {
|
if (itemsContainer) {
|
||||||
focusedElement = focusManager.autoFocus(itemsContainer);
|
focusedElement = focusManager.autoFocus(itemsContainer);
|
||||||
|
@ -93,9 +95,10 @@ define(["focusManager", "layoutManager"], function (focusManager, layoutManager)
|
||||||
return focusedElement;
|
return focusedElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
/* eslint-enable indent */
|
||||||
|
|
||||||
|
export default {
|
||||||
isEnabled: isEnabled,
|
isEnabled: isEnabled,
|
||||||
enable: enable,
|
enable: enable,
|
||||||
autoFocus: autoFocus
|
autoFocus: autoFocus
|
||||||
};
|
};
|
||||||
});
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
define(['browser', 'connectionManager', 'playbackManager', 'dom', 'css!./backdrop'], function (browser, connectionManager, playbackManager, dom) {
|
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,8 +180,9 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'css!./backdro
|
||||||
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(),
|
||||||
index: index
|
index: index
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
@ -190,8 +191,9 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'css!./backdro
|
||||||
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(),
|
||||||
index: index
|
index: index
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
@ -236,10 +238,15 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'css!./backdro
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function enabled() {
|
||||||
|
return userSettings.enableBackdrops();
|
||||||
|
}
|
||||||
|
|
||||||
var rotationInterval;
|
var rotationInterval;
|
||||||
var currentRotatingImages = [];
|
var currentRotatingImages = [];
|
||||||
var currentRotationIndex = -1;
|
var currentRotationIndex = -1;
|
||||||
function setBackdrops(items, imageOptions, enableImageRotation) {
|
function setBackdrops(items, imageOptions, enableImageRotation) {
|
||||||
|
if (enabled()) {
|
||||||
var images = getImageUrls(items, imageOptions);
|
var images = getImageUrls(items, imageOptions);
|
||||||
|
|
||||||
if (images.length) {
|
if (images.length) {
|
||||||
|
@ -248,6 +255,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'css!./backdro
|
||||||
clearBackdrop();
|
clearBackdrop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function startRotation(images, enableImageRotation) {
|
function startRotation(images, enableImageRotation) {
|
||||||
if (arraysEqual(images, currentRotatingImages)) {
|
if (arraysEqual(images, currentRotatingImages)) {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
define(["connectionManager"], function (connectionManager) {
|
define(['connectionManager'], function (connectionManager) {
|
||||||
|
|
||||||
return function () {
|
return function () {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
self.name = "Backdrop ScreenSaver";
|
self.name = 'Backdrop ScreenSaver';
|
||||||
self.type = "screensaver";
|
self.type = 'screensaver';
|
||||||
self.id = "backdropscreensaver";
|
self.id = 'backdropscreensaver';
|
||||||
self.supportsAnonymous = false;
|
self.supportsAnonymous = false;
|
||||||
|
|
||||||
var currentSlideshow;
|
var currentSlideshow;
|
||||||
|
@ -14,12 +14,12 @@ define(["connectionManager"], function (connectionManager) {
|
||||||
self.show = function () {
|
self.show = function () {
|
||||||
|
|
||||||
var query = {
|
var query = {
|
||||||
ImageTypes: "Backdrop",
|
ImageTypes: 'Backdrop',
|
||||||
EnableImageTypes: "Backdrop",
|
EnableImageTypes: 'Backdrop',
|
||||||
IncludeItemTypes: "Movie,Series,MusicArtist",
|
IncludeItemTypes: 'Movie,Series,MusicArtist',
|
||||||
SortBy: "Random",
|
SortBy: 'Random',
|
||||||
Recursive: true,
|
Recursive: true,
|
||||||
Fields: "Taglines",
|
Fields: 'Taglines',
|
||||||
ImageTypeLimit: 1,
|
ImageTypeLimit: 1,
|
||||||
StartIndex: 0,
|
StartIndex: 0,
|
||||||
Limit: 200
|
Limit: 200
|
||||||
|
@ -30,7 +30,7 @@ define(["connectionManager"], function (connectionManager) {
|
||||||
|
|
||||||
if (result.Items.length) {
|
if (result.Items.length) {
|
||||||
|
|
||||||
require(["slideshow"], function (slideshow) {
|
require(['slideshow'], function (slideshow) {
|
||||||
|
|
||||||
var newSlideShow = new slideshow({
|
var newSlideShow = new slideshow({
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
|
@ -52,5 +52,5 @@ define(["connectionManager"], function (connectionManager) {
|
||||||
currentSlideshow = null;
|
currentSlideshow = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,23 +1,24 @@
|
||||||
|
button {
|
||||||
|
-webkit-border-fit: border !important;
|
||||||
|
}
|
||||||
|
|
||||||
button::-moz-focus-inner {
|
button::-moz-focus-inner {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
|
||||||
-webkit-border-fit: border !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
border: 0;
|
border: 0;
|
||||||
font-size: inherit !important;
|
font-size: inherit !important;
|
||||||
font-family: inherit !important;
|
font-family: inherit !important;
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
background-color: transparent !important;
|
|
||||||
background: none !important;
|
background: none !important;
|
||||||
|
background-color: transparent !important;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
display: block;
|
display: block;
|
||||||
color: inherit !important;
|
color: inherit !important;
|
||||||
|
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
contain: layout style;
|
contain: layout style;
|
||||||
|
@ -54,17 +55,27 @@ button {
|
||||||
contain: layout style;
|
contain: layout style;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardPadder-backdrop, .cardPadder-mixedBackdrop, .cardPadder-smallBackdrop, .cardPadder-overflowBackdrop, .cardPadder-overflowSmallBackdrop {
|
.cardPadder-backdrop,
|
||||||
|
.cardPadder-mixedBackdrop,
|
||||||
|
.cardPadder-smallBackdrop,
|
||||||
|
.cardPadder-overflowBackdrop,
|
||||||
|
.cardPadder-overflowSmallBackdrop {
|
||||||
padding-bottom: 56.25%;
|
padding-bottom: 56.25%;
|
||||||
contain: strict;
|
contain: strict;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardPadder-square, .cardPadder-mixedSquare, .cardPadder-overflowSquare, .overflowSquareCard-textCardPadder {
|
.cardPadder-square,
|
||||||
|
.cardPadder-mixedSquare,
|
||||||
|
.cardPadder-overflowSquare,
|
||||||
|
.overflowSquareCard-textCardPadder {
|
||||||
padding-bottom: 100%;
|
padding-bottom: 100%;
|
||||||
contain: strict;
|
contain: strict;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardPadder-portrait, .cardPadder-mixedPortrait, .cardPadder-overflowPortrait, .overflowPortraitCard-textCardPadder {
|
.cardPadder-portrait,
|
||||||
|
.cardPadder-mixedPortrait,
|
||||||
|
.cardPadder-overflowPortrait,
|
||||||
|
.overflowPortraitCard-textCardPadder {
|
||||||
padding-bottom: 150%;
|
padding-bottom: 150%;
|
||||||
contain: strict;
|
contain: strict;
|
||||||
}
|
}
|
||||||
|
@ -79,23 +90,26 @@ button {
|
||||||
margin: 0.6em;
|
margin: 0.6em;
|
||||||
transition: none;
|
transition: none;
|
||||||
border: 0 solid transparent;
|
border: 0 solid transparent;
|
||||||
|
|
||||||
|
/* These both are needed in case cardBox is a button */
|
||||||
|
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
contain: layout;
|
contain: layout;
|
||||||
contain: style;
|
contain: style;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card.show-animation .cardBox {
|
||||||
|
will-change: transform;
|
||||||
|
transition: transform 200ms ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
.card.show-focus:not(.show-animation) .cardBox {
|
.card.show-focus:not(.show-animation) .cardBox {
|
||||||
margin: .4em;
|
margin: 0.4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card.show-focus:not(.show-animation) .cardBox.visualCardBox,
|
.card.show-focus:not(.show-animation) .cardBox.visualCardBox,
|
||||||
.card.show-focus:not(.show-animation) .cardBox:not(.visualCardBox) .cardScalable {
|
.card.show-focus:not(.show-animation) .cardBox:not(.visualCardBox) .cardScalable {
|
||||||
border: .5em solid transparent;
|
border: 0.5em solid transparent;
|
||||||
}
|
|
||||||
|
|
||||||
.card.show-animation .cardBox {
|
|
||||||
will-change: transform;
|
|
||||||
transition: transform 200ms ease-out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.card.show-animation:focus > .cardBox {
|
.card.show-animation:focus > .cardBox {
|
||||||
|
@ -120,7 +134,7 @@ button {
|
||||||
|
|
||||||
.btnCardOptions {
|
.btnCardOptions {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: .25em;
|
bottom: 0.25em;
|
||||||
right: 0;
|
right: 0;
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
@ -131,8 +145,8 @@ button {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
top: .3em;
|
top: 0.3em;
|
||||||
left: .3em;
|
left: 0.3em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
width: 1.6em;
|
width: 1.6em;
|
||||||
|
@ -146,12 +160,14 @@ button {
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center center;
|
background-position: center center;
|
||||||
|
display: -webkit-flex;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
background-clip: content-box !important;
|
background-clip: content-box !important;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
|
|
||||||
/* This is only needed for scalable cards */
|
/* This is only needed for scalable cards */
|
||||||
height: 100%;
|
height: 100%;
|
||||||
contain: strict;
|
contain: strict;
|
||||||
|
@ -173,12 +189,16 @@ button {
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
|
||||||
/* Needed in case this is a button */
|
/* Needed in case this is a button */
|
||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
/* Needed in case this is a button */
|
/* Needed in case this is a button */
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
|
|
||||||
/* Needed in safari */
|
/* Needed in safari */
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
contain: strict;
|
contain: strict;
|
||||||
}
|
}
|
||||||
|
@ -207,10 +227,6 @@ button {
|
||||||
box-shadow: 0 0.0725em 0.29em 0 rgba(0, 0, 0, 0.37);
|
box-shadow: 0 0.0725em 0.29em 0 rgba(0, 0, 0, 0.37);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardImageContainer {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cardImage {
|
.cardImage {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -226,6 +242,7 @@ button {
|
||||||
.cardImage-img {
|
.cardImage-img {
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
|
||||||
/* This is simply for lazy image purposes, to ensure the image is visible sooner when scrolling */
|
/* This is simply for lazy image purposes, to ensure the image is visible sooner when scrolling */
|
||||||
min-height: 70%;
|
min-height: 70%;
|
||||||
min-width: 70%;
|
min-width: 70%;
|
||||||
|
@ -252,17 +269,17 @@ button {
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardFooter {
|
.cardFooter {
|
||||||
padding: .3em .3em .5em .3em;
|
padding: 0.3em 0.3em 0.5em 0.3em;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.visualCardBox {
|
.visualCardBox {
|
||||||
box-shadow: 0 0.0725em 0.29em 0 rgba(0, 0, 0, 0.37);
|
box-shadow: 0 0.0725em 0.29em 0 rgba(0, 0, 0, 0.37);
|
||||||
border-radius: .145em;
|
border-radius: 0.145em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.innerCardFooter {
|
.innerCardFooter {
|
||||||
background: rgba(0,0,0,.7);
|
background: rgba(0, 0, 0, 0.7);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
@ -282,7 +299,7 @@ button {
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardText {
|
.cardText {
|
||||||
padding: .06em .5em;
|
padding: 0.06em 0.5em;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
@ -294,7 +311,24 @@ button {
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardText-first {
|
.cardText-first {
|
||||||
padding-top: .24em;
|
padding-top: 0.24em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.textActionButton {
|
||||||
|
border: 0 !important;
|
||||||
|
background: transparent;
|
||||||
|
padding: 0 !important;
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||||
|
outline: none !important;
|
||||||
|
color: inherit;
|
||||||
|
vertical-align: middle;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.textActionButton:hover {
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardText > .textActionButton {
|
.cardText > .textActionButton {
|
||||||
|
@ -304,7 +338,7 @@ button {
|
||||||
}
|
}
|
||||||
|
|
||||||
.innerCardFooter > .cardText {
|
.innerCardFooter > .cardText {
|
||||||
padding: .3em .5em;
|
padding: 0.3em 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardFooter-withlogo {
|
.cardFooter-withlogo {
|
||||||
|
@ -336,36 +370,19 @@ button {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.textActionButton {
|
.cardImageContainer .cardImageIcon {
|
||||||
border: 0 !important;
|
|
||||||
background: transparent;
|
|
||||||
border: 0 !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
cursor: pointer;
|
|
||||||
outline: none !important;
|
|
||||||
color: inherit;
|
|
||||||
vertical-align: middle;
|
|
||||||
font-family: inherit;
|
|
||||||
font-size: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.textActionButton:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cardImageIcon {
|
|
||||||
font-size: 5em;
|
font-size: 5em;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardImageIcon-small {
|
.cardImageIcon-small {
|
||||||
font-size: 3em;
|
font-size: 3em !important;
|
||||||
margin-bottom: .1em;
|
margin-bottom: 0.1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardIndicators {
|
.cardIndicators {
|
||||||
right: .225em;
|
right: 0.225em;
|
||||||
top: .225em;
|
top: 0.225em;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -382,16 +399,16 @@ button {
|
||||||
}
|
}
|
||||||
|
|
||||||
.programAttributeIndicator {
|
.programAttributeIndicator {
|
||||||
padding: .18em .5em;
|
padding: 0.18em 0.5em;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardOverlayButton {
|
.cardOverlayButton {
|
||||||
color: rgba(255, 255, 255, .76);
|
color: rgba(255, 255, 255, 0.76);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
padding: .75em;
|
padding: 0.75em;
|
||||||
font-size: 88%;
|
font-size: 88%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,7 +419,7 @@ button {
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardOverlayButtonIcon {
|
.cardOverlayButtonIcon {
|
||||||
background-color: rgba(0,0,0,.7) !important;
|
background-color: rgba(0, 0, 0, 0.7) !important;
|
||||||
border-radius: 100em;
|
border-radius: 100em;
|
||||||
width: 1.5em !important;
|
width: 1.5em !important;
|
||||||
height: 1.5em !important;
|
height: 1.5em !important;
|
||||||
|
@ -412,6 +429,12 @@ button {
|
||||||
font-size: 1.66956521739130434em !important;
|
font-size: 1.66956521739130434em !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cardOverlayButtonIcon.material-icons {
|
||||||
|
/* material-icons override display, so we need to
|
||||||
|
make a better matching selector to set it to flex */
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
.cardOverlayButton-centered {
|
.cardOverlayButton-centered {
|
||||||
bottom: initial;
|
bottom: initial;
|
||||||
right: initial;
|
right: initial;
|
||||||
|
@ -424,10 +447,10 @@ button {
|
||||||
height: 2.6em;
|
height: 2.6em;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
background-color: rgba(0,0,0,.5) !important;
|
background-color: rgba(0, 0, 0, 0.5) !important;
|
||||||
border: .06em solid rgba(255,255,255,.6);
|
border: 0.06em solid rgba(255, 255, 255, 0.6);
|
||||||
padding: .38em !important;
|
padding: 0.38em !important;
|
||||||
color: rgba(255, 255, 255, .76);
|
color: rgba(255, 255, 255, 0.76);
|
||||||
transition: transform 200ms ease-out;
|
transition: transform 200ms ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,13 +497,15 @@ button {
|
||||||
width: 33.333333333333333333333333333333%;
|
width: 33.333333333333333333333333333333%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.squareCard, .portraitCard {
|
.squareCard,
|
||||||
|
.portraitCard {
|
||||||
width: 33.333333333333333333333333333333%;
|
width: 33.333333333333333333333333333333%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 43.75em) {
|
@media (min-width: 43.75em) {
|
||||||
.squareCard, .portraitCard {
|
.squareCard,
|
||||||
|
.portraitCard {
|
||||||
width: 25%;
|
width: 25%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -496,7 +521,8 @@ button {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.squareCard, .portraitCard {
|
.squareCard,
|
||||||
|
.portraitCard {
|
||||||
width: 20%;
|
width: 20%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,7 +542,8 @@ button {
|
||||||
width: 25%;
|
width: 25%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.squareCard, .portraitCard {
|
.squareCard,
|
||||||
|
.portraitCard {
|
||||||
width: 16.666666666666666666666666666667%;
|
width: 16.666666666666666666666666666667%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,9 +556,9 @@ button {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@media (min-width: 87.5em) {
|
@media (min-width: 87.5em) {
|
||||||
.squareCard, .portraitCard {
|
.squareCard,
|
||||||
|
.portraitCard {
|
||||||
width: 14.285714285714285714285714285714%;
|
width: 14.285714285714285714285714285714%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,13 +576,15 @@ button {
|
||||||
width: 20%;
|
width: 20%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.squareCard, .portraitCard {
|
.squareCard,
|
||||||
|
.portraitCard {
|
||||||
width: 12.5%;
|
width: 12.5%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 120em) {
|
@media (min-width: 120em) {
|
||||||
.squareCard, .portraitCard {
|
.squareCard,
|
||||||
|
.portraitCard {
|
||||||
width: 11.111111111111111111111111111111%;
|
width: 11.111111111111111111111111111111%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -565,7 +594,8 @@ button {
|
||||||
width: 25%;
|
width: 25%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.squareCard, .portraitCard {
|
.squareCard,
|
||||||
|
.portraitCard {
|
||||||
width: 10%;
|
width: 10%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -596,7 +626,8 @@ button {
|
||||||
width: 72vw;
|
width: 72vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overflowSquareCard, .overflowPortraitCard {
|
.overflowSquareCard,
|
||||||
|
.overflowPortraitCard {
|
||||||
width: 40vw;
|
width: 40vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -621,29 +652,34 @@ button {
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 43.75em) {
|
@media (min-width: 43.75em) {
|
||||||
.overflowSquareCard, .overflowPortraitCard {
|
.overflowSquareCard,
|
||||||
|
.overflowPortraitCard {
|
||||||
width: 23.1vw;
|
width: 23.1vw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 48.125em) {
|
@media (min-width: 48.125em) {
|
||||||
.overflowBackdropCard, .overflowSmallBackdropCard {
|
.overflowBackdropCard,
|
||||||
|
.overflowSmallBackdropCard {
|
||||||
width: 30vw;
|
width: 30vw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (orientation: landscape) {
|
@media (orientation: landscape) {
|
||||||
.overflowBackdropCard, .overflowSmallBackdropCard {
|
.overflowBackdropCard,
|
||||||
|
.overflowSmallBackdropCard {
|
||||||
width: 30vw;
|
width: 30vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overflowSquareCard, .overflowPortraitCard {
|
.overflowSquareCard,
|
||||||
|
.overflowPortraitCard {
|
||||||
width: 23.1vw;
|
width: 23.1vw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (orientation: landscape) and (min-width: 48.125em) {
|
@media (orientation: landscape) and (min-width: 48.125em) {
|
||||||
.overflowBackdropCard, .overflowSmallBackdropCard {
|
.overflowBackdropCard,
|
||||||
|
.overflowSmallBackdropCard {
|
||||||
width: 23.1vw;
|
width: 23.1vw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -655,55 +691,60 @@ button {
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 50em) {
|
@media (min-width: 50em) {
|
||||||
.overflowSquareCard, .overflowPortraitCard {
|
.overflowSquareCard,
|
||||||
|
.overflowPortraitCard {
|
||||||
width: 18.5vw;
|
width: 18.5vw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 75em) {
|
@media (min-width: 75em) {
|
||||||
.overflowBackdropCard, .overflowSmallBackdropCard {
|
.overflowBackdropCard,
|
||||||
|
.overflowSmallBackdropCard {
|
||||||
width: 23.1vw;
|
width: 23.1vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overflowSquareCard, .overflowPortraitCard {
|
.overflowSquareCard,
|
||||||
|
.overflowPortraitCard {
|
||||||
width: 15.5vw;
|
width: 15.5vw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 87.5em) {
|
@media (min-width: 87.5em) {
|
||||||
.overflowSquareCard, .overflowPortraitCard {
|
.overflowSquareCard,
|
||||||
|
.overflowPortraitCard {
|
||||||
width: 13.3vw;
|
width: 13.3vw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 100em) {
|
@media (min-width: 100em) {
|
||||||
|
.overflowBackdropCard,
|
||||||
.overflowBackdropCard, .overflowSmallBackdropCard {
|
.overflowSmallBackdropCard {
|
||||||
width: 18.7vw;
|
width: 18.7vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overflowSquareCard, .overflowPortraitCard {
|
.overflowSquareCard,
|
||||||
|
.overflowPortraitCard {
|
||||||
width: 11.6vw;
|
width: 11.6vw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 120em) {
|
@media (min-width: 120em) {
|
||||||
|
.overflowSquareCard,
|
||||||
.overflowSquareCard, .overflowPortraitCard {
|
.overflowPortraitCard {
|
||||||
width: 10.3vw;
|
width: 10.41vw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 131.25em) {
|
@media (min-width: 131.25em) {
|
||||||
|
.overflowSquareCard,
|
||||||
.overflowSquareCard, .overflowPortraitCard {
|
.overflowPortraitCard {
|
||||||
width: 9.3vw;
|
width: 9.3vw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 156.25em) {
|
@media (min-width: 156.25em) {
|
||||||
|
.overflowBackdropCard,
|
||||||
.overflowBackdropCard, .overflowSmallBackdropCard {
|
.overflowSmallBackdropCard {
|
||||||
width: 15.6vw;
|
width: 15.6vw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -720,7 +761,8 @@ button {
|
||||||
padding-bottom: 87.75%;
|
padding-bottom: 87.75%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.itemsContainer-tv > .overflowSquareCard, .itemsContainer-tv > .overflowPortraitCard {
|
.itemsContainer-tv > .overflowSquareCard,
|
||||||
|
.itemsContainer-tv > .overflowPortraitCard {
|
||||||
width: 15.6vw;
|
width: 15.6vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -731,7 +773,7 @@ button {
|
||||||
.cardOverlayContainer {
|
.cardOverlayContainer {
|
||||||
background: rgba(0, 0, 0, 0.5);
|
background: rgba(0, 0, 0, 0.5);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity .2s;
|
transition: opacity 0.2s;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
@ -748,7 +790,7 @@ button {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: 0.2s;
|
transition: 0.2s;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
padding: 0.5em;
|
padding: 0.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cardOverlayButtonIcon-hover {
|
.cardOverlayButtonIcon-hover {
|
||||||
|
|
|
@ -68,9 +68,9 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browse
|
||||||
|
|
||||||
return apiClient.getScaledImageUrl(item.Id, {
|
return apiClient.getScaledImageUrl(item.Id, {
|
||||||
|
|
||||||
maxWidth: maxWidth,
|
maxWidth: maxWidth * 2,
|
||||||
tag: chapter.ImageTag,
|
tag: chapter.ImageTag,
|
||||||
type: "Chapter",
|
type: 'Chapter',
|
||||||
index: index
|
index: index
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ define(['datetime', 'imageLoader', 'connectionManager', 'layoutManager', 'browse
|
||||||
var cardImageContainer = imgUrl ? ('<div class="' + cardImageContainerClass + ' lazy" data-src="' + imgUrl + '">') : ('<div class="' + cardImageContainerClass + '">');
|
var cardImageContainer = imgUrl ? ('<div class="' + cardImageContainerClass + ' lazy" data-src="' + imgUrl + '">') : ('<div class="' + cardImageContainerClass + '">');
|
||||||
|
|
||||||
if (!imgUrl) {
|
if (!imgUrl) {
|
||||||
cardImageContainer += '<i class="md-icon cardImageIcon">local_movies</i>';
|
cardImageContainer += '<span class="material-icons cardImageIcon local_movies"></span>';
|
||||||
}
|
}
|
||||||
|
|
||||||
var nameHtml = '';
|
var nameHtml = '';
|
||||||
|
|
34
src/components/castSenderApi.js
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
define([], function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
if (window.appMode === 'cordova' || window.appMode === 'android') {
|
||||||
|
return {
|
||||||
|
load: function () {
|
||||||
|
window.chrome = window.chrome || {};
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
var ccLoaded = false;
|
||||||
|
return {
|
||||||
|
load: function () {
|
||||||
|
if (ccLoaded) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
var fileref = document.createElement('script');
|
||||||
|
fileref.setAttribute('type', 'text/javascript');
|
||||||
|
|
||||||
|
fileref.onload = function () {
|
||||||
|
ccLoaded = true;
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
fileref.setAttribute('src', 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js');
|
||||||
|
document.querySelector('head').appendChild(fileref);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,44 +1,33 @@
|
||||||
define(["dialogHelper", "loading", "connectionManager", "globalize", "actionsheet", "emby-input", "paper-icon-button-light", "emby-button", "listViewStyle", "material-icons", "formDialogStyle"], function (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 parentWithClass(elem, className) {
|
|
||||||
while (!elem.classList || !elem.classList.contains(className)) {
|
|
||||||
elem = elem.parentNode;
|
|
||||||
if (!elem) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return elem;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = 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 = 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,
|
||||||
|
@ -59,56 +48,56 @@ define(["dialogHelper", "loading", "connectionManager", "globalize", "actionshee
|
||||||
|
|
||||||
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="md-icon 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="md-icon">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">';
|
||||||
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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,27 +108,27 @@ define(["dialogHelper", "loading", "connectionManager", "globalize", "actionshee
|
||||||
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="md-icon">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);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,69 +37,69 @@ define(['events'], function (events) {
|
||||||
// 5) It wasn't as smart as it could have been about what should be part of a
|
// 5) It wasn't as smart as it could have been about what should be part of a
|
||||||
// URL and what should be part of human language.
|
// URL and what should be part of human language.
|
||||||
|
|
||||||
var protocols = "(?:(?:http|https|rtsp|ftp):\\/\\/)";
|
var protocols = '(?:(?:http|https|rtsp|ftp):\\/\\/)';
|
||||||
var credentials = "(?:(?:[a-z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-f0-9]{2})){1,64}" // username (1-64 normal or url escaped characters)
|
var credentials = "(?:(?:[a-z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-f0-9]{2})){1,64}" // username (1-64 normal or url escaped characters)
|
||||||
+ "(?:\\:(?:[a-z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-f0-9]{2})){1,25})?" // followed by optional password (: + 1-25 normal or url escaped characters)
|
+ "(?:\\:(?:[a-z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-f0-9]{2})){1,25})?" // followed by optional password (: + 1-25 normal or url escaped characters)
|
||||||
+ "\\@)";
|
+ '\\@)';
|
||||||
|
|
||||||
// IPv6 Regex http://forums.intermapper.com/viewtopic.php?t=452
|
// IPv6 Regex http://forums.intermapper.com/viewtopic.php?t=452
|
||||||
// by Dartware, LLC is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License
|
// by Dartware, LLC is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License
|
||||||
// http://intermapper.com/
|
// http://intermapper.com/
|
||||||
var ipv6 = "("
|
var ipv6 = '('
|
||||||
+ "(([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))"
|
+ '(([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))'
|
||||||
+ "|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))"
|
+ '|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))'
|
||||||
+ "|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))"
|
+ '|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))'
|
||||||
+ "|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
|
+ '|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))'
|
||||||
+ "|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
|
+ '|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))'
|
||||||
+ "|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
|
+ '|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))'
|
||||||
+ "|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
|
+ '|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))'
|
||||||
+ "|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))"
|
+ '|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))'
|
||||||
+ ")(%.+)?";
|
+ ')(%.+)?';
|
||||||
|
|
||||||
var ipv4 = "(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\."
|
var ipv4 = '(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.'
|
||||||
+ "(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\."
|
+ '(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.'
|
||||||
+ "(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\."
|
+ '(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.'
|
||||||
+ "(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])";
|
+ '(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])';
|
||||||
|
|
||||||
// This would have been a lot cleaner if JS RegExp supported conditionals...
|
// This would have been a lot cleaner if JS RegExp supported conditionals...
|
||||||
var linkRegExpString =
|
var linkRegExpString =
|
||||||
|
|
||||||
// begin match for protocol / username / password / host
|
// begin match for protocol / username / password / host
|
||||||
"(?:"
|
'(?:'
|
||||||
|
|
||||||
// ============================
|
// ============================
|
||||||
// If we have a recognized protocol at the beginning of the URL, we're
|
// If we have a recognized protocol at the beginning of the URL, we're
|
||||||
// more relaxed about what we accept, because we assume the user wants
|
// more relaxed about what we accept, because we assume the user wants
|
||||||
// this to be a URL, and we're not accidentally matching human language
|
// this to be a URL, and we're not accidentally matching human language
|
||||||
+ protocols + "?"
|
+ protocols + '?'
|
||||||
|
|
||||||
// optional username:password@
|
// optional username:password@
|
||||||
+ credentials + "?"
|
+ credentials + '?'
|
||||||
|
|
||||||
// IP address (both v4 and v6)
|
// IP address (both v4 and v6)
|
||||||
+ "(?:"
|
+ '(?:'
|
||||||
|
|
||||||
// IPv6
|
// IPv6
|
||||||
+ ipv6
|
+ ipv6
|
||||||
|
|
||||||
// IPv4
|
// IPv4
|
||||||
+ "|" + ipv4
|
+ '|' + ipv4
|
||||||
|
|
||||||
+ ")"
|
+ ')'
|
||||||
|
|
||||||
// end match for protocol / username / password / host
|
// end match for protocol / username / password / host
|
||||||
+ ")"
|
+ ')'
|
||||||
|
|
||||||
// optional port number
|
// optional port number
|
||||||
+ "(?:\\:\\d{1,5})?"
|
+ '(?:\\:\\d{1,5})?'
|
||||||
|
|
||||||
// plus optional path and query params (no unicode allowed here?)
|
// plus optional path and query params (no unicode allowed here?)
|
||||||
+ "(?:"
|
+ '(?:'
|
||||||
+ "\\/(?:"
|
+ '\\/(?:'
|
||||||
// some characters we'll accept because it's unlikely human language
|
// some characters we'll accept because it's unlikely human language
|
||||||
// would use them after a URL unless they were part of the url
|
// would use them after a URL unless they were part of the url
|
||||||
+ "(?:[a-z0-9\\/\\@\\&\\#\\~\\*\\_\\-\\+])"
|
+ '(?:[a-z0-9\\/\\@\\&\\#\\~\\*\\_\\-\\+])'
|
||||||
+ "|(?:\\%[a-f0-9]{2})"
|
+ '|(?:\\%[a-f0-9]{2})'
|
||||||
// some characters are much more likely to be used AFTER a url and
|
// some characters are much more likely to be used AFTER a url and
|
||||||
// were not intended to be included in the url itself. Mostly end
|
// were not intended to be included in the url itself. Mostly end
|
||||||
// of sentence type things. It's also likely that the URL would
|
// of sentence type things. It's also likely that the URL would
|
||||||
|
@ -108,9 +108,9 @@ define(['events'], function (events) {
|
||||||
// they must be followed by another character that we're reasonably
|
// they must be followed by another character that we're reasonably
|
||||||
// sure is part of the url
|
// sure is part of the url
|
||||||
+ "|(?:[\\;\\?\\:\\.\\!\\'\\(\\)\\,\\=]+(?=(?:[a-z0-9\\/\\@\\&\\#\\~\\*\\_\\-\\+])|(?:\\%[a-f0-9]{2})))"
|
+ "|(?:[\\;\\?\\:\\.\\!\\'\\(\\)\\,\\=]+(?=(?:[a-z0-9\\/\\@\\&\\#\\~\\*\\_\\-\\+])|(?:\\%[a-f0-9]{2})))"
|
||||||
+ ")*"
|
+ ')*'
|
||||||
+ "|\\b|\$"
|
+ '|\\b|\$'
|
||||||
+ ")";
|
+ ')';
|
||||||
|
|
||||||
// regex = XRegExp(regex,'gi');
|
// regex = XRegExp(regex,'gi');
|
||||||
var linkRegExp = RegExp(linkRegExpString, 'gi');
|
var linkRegExp = RegExp(linkRegExpString, 'gi');
|
||||||
|
@ -120,7 +120,7 @@ define(['events'], function (events) {
|
||||||
// if url doesn't begin with a known protocol, add http by default
|
// if url doesn't begin with a known protocol, add http by default
|
||||||
function ensureProtocol(url) {
|
function ensureProtocol(url) {
|
||||||
if (!url.match(protocolRegExp)) {
|
if (!url.match(protocolRegExp)) {
|
||||||
url = "http://" + url;
|
url = 'http://' + url;
|
||||||
}
|
}
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
@ -131,8 +131,9 @@ define(['events'], function (events) {
|
||||||
var links = [];
|
var links = [];
|
||||||
var match;
|
var match;
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-cond-assign
|
||||||
while (match = linkRegExp.exec(text)) {
|
while (match = linkRegExp.exec(text)) {
|
||||||
// console.log(matches);
|
console.debug(match);
|
||||||
var txt = match[0];
|
var txt = match[0];
|
||||||
var pos = match.index;
|
var pos = match.index;
|
||||||
var len = txt.length;
|
var len = txt.length;
|
||||||
|
@ -187,9 +188,9 @@ define(['events'], function (events) {
|
||||||
return apiClient.getEndpointInfo().then(function (endpoint) {
|
return apiClient.getEndpointInfo().then(function (endpoint) {
|
||||||
if (endpoint.IsInNetwork) {
|
if (endpoint.IsInNetwork) {
|
||||||
return apiClient.getPublicSystemInfo().then(function (info) {
|
return apiClient.getPublicSystemInfo().then(function (info) {
|
||||||
var localAddress = info.LocalAddress
|
var localAddress = info.LocalAddress;
|
||||||
if (!localAddress) {
|
if (!localAddress) {
|
||||||
console.log("No valid local address returned, defaulting to external one")
|
console.debug('No valid local address returned, defaulting to external one');
|
||||||
localAddress = serverAddress;
|
localAddress = serverAddress;
|
||||||
}
|
}
|
||||||
addToCache(serverAddress, localAddress);
|
addToCache(serverAddress, localAddress);
|
||||||
|
|
|
@ -5,7 +5,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
var currentResolve;
|
var currentResolve;
|
||||||
var currentReject;
|
var currentReject;
|
||||||
|
|
||||||
var PlayerName = 'Chromecast';
|
var PlayerName = 'Google Cast';
|
||||||
|
|
||||||
function sendConnectionResult(isOk) {
|
function sendConnectionResult(isOk) {
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
|
|
||||||
// production version registered with google
|
// production version registered with google
|
||||||
// replace this value if you want to test changes on another instance
|
// replace this value if you want to test changes on another instance
|
||||||
var applicationID = "F007D354";
|
var applicationID = 'F007D354';
|
||||||
|
|
||||||
var messageNamespace = 'urn:x-cast:com.connectsdk';
|
var messageNamespace = 'urn:x-cast:com.connectsdk';
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
this.sessionListener.bind(this),
|
this.sessionListener.bind(this),
|
||||||
this.receiverListener.bind(this));
|
this.receiverListener.bind(this));
|
||||||
|
|
||||||
console.log('chromecast.initialize');
|
console.debug('chromecast.initialize');
|
||||||
chrome.cast.initialize(apiConfig, this.onInitSuccess.bind(this), this.errorHandler);
|
chrome.cast.initialize(apiConfig, this.onInitSuccess.bind(this), this.errorHandler);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -114,14 +114,14 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
*/
|
*/
|
||||||
CastPlayer.prototype.onInitSuccess = function () {
|
CastPlayer.prototype.onInitSuccess = function () {
|
||||||
this.isInitialized = true;
|
this.isInitialized = true;
|
||||||
console.log("chromecast init success");
|
console.debug('chromecast init success');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic error callback function
|
* Generic error callback function
|
||||||
*/
|
*/
|
||||||
CastPlayer.prototype.onError = function () {
|
CastPlayer.prototype.onError = function () {
|
||||||
console.log("chromecast error");
|
console.debug('chromecast error');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -177,10 +177,10 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
*/
|
*/
|
||||||
CastPlayer.prototype.receiverListener = function (e) {
|
CastPlayer.prototype.receiverListener = function (e) {
|
||||||
if (e === 'available') {
|
if (e === 'available') {
|
||||||
console.log("chromecast receiver found");
|
console.debug('chromecast receiver found');
|
||||||
this.hasReceivers = true;
|
this.hasReceivers = true;
|
||||||
} else {
|
} else {
|
||||||
console.log("chromecast receiver list empty");
|
console.debug('chromecast receiver list empty');
|
||||||
this.hasReceivers = false;
|
this.hasReceivers = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -190,15 +190,15 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
*/
|
*/
|
||||||
CastPlayer.prototype.sessionUpdateListener = function (isAlive) {
|
CastPlayer.prototype.sessionUpdateListener = function (isAlive) {
|
||||||
if (isAlive) {
|
if (isAlive) {
|
||||||
console.log('sessionUpdateListener: already alive');
|
console.debug('sessionUpdateListener: already alive');
|
||||||
} else {
|
} else {
|
||||||
this.session = null;
|
this.session = null;
|
||||||
this.deviceState = DEVICE_STATE.IDLE;
|
this.deviceState = DEVICE_STATE.IDLE;
|
||||||
this.castPlayerState = PLAYER_STATE.IDLE;
|
this.castPlayerState = PLAYER_STATE.IDLE;
|
||||||
document.removeEventListener("volumeupbutton", onVolumeUpKeyDown, false);
|
document.removeEventListener('volumeupbutton', onVolumeUpKeyDown, false);
|
||||||
document.removeEventListener("volumedownbutton", onVolumeDownKeyDown, false);
|
document.removeEventListener('volumedownbutton', onVolumeDownKeyDown, false);
|
||||||
|
|
||||||
console.log('sessionUpdateListener: setting currentMediaSession to null');
|
console.debug('sessionUpdateListener: setting currentMediaSession to null');
|
||||||
this.currentMediaSession = null;
|
this.currentMediaSession = null;
|
||||||
|
|
||||||
sendConnectionResult(false);
|
sendConnectionResult(false);
|
||||||
|
@ -211,7 +211,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
* session request in opt_sessionRequest.
|
* session request in opt_sessionRequest.
|
||||||
*/
|
*/
|
||||||
CastPlayer.prototype.launchApp = function () {
|
CastPlayer.prototype.launchApp = function () {
|
||||||
console.log("chromecast launching app...");
|
console.debug('chromecast launching app...');
|
||||||
chrome.cast.requestSession(this.onRequestSessionSuccess.bind(this), this.onLaunchError.bind(this));
|
chrome.cast.requestSession(this.onRequestSessionSuccess.bind(this), this.onLaunchError.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
* @param {Object} e A chrome.cast.Session object
|
* @param {Object} e A chrome.cast.Session object
|
||||||
*/
|
*/
|
||||||
CastPlayer.prototype.onRequestSessionSuccess = function (e) {
|
CastPlayer.prototype.onRequestSessionSuccess = function (e) {
|
||||||
console.log("chromecast session success: " + e.sessionId);
|
console.debug('chromecast session success: ' + e.sessionId);
|
||||||
this.onSessionConnected(e);
|
this.onSessionConnected(e);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -232,8 +232,8 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
this.session.addMediaListener(this.sessionMediaListener.bind(this));
|
this.session.addMediaListener(this.sessionMediaListener.bind(this));
|
||||||
this.session.addUpdateListener(this.sessionUpdateListener.bind(this));
|
this.session.addUpdateListener(this.sessionUpdateListener.bind(this));
|
||||||
|
|
||||||
document.addEventListener("volumeupbutton", onVolumeUpKeyDown, false);
|
document.addEventListener('volumeupbutton', onVolumeUpKeyDown, false);
|
||||||
document.addEventListener("volumedownbutton", onVolumeDownKeyDown, false);
|
document.addEventListener('volumedownbutton', onVolumeDownKeyDown, false);
|
||||||
|
|
||||||
events.trigger(this, 'connect');
|
events.trigger(this, 'connect');
|
||||||
this.sendMessage({
|
this.sendMessage({
|
||||||
|
@ -262,7 +262,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
* Callback function for launch error
|
* Callback function for launch error
|
||||||
*/
|
*/
|
||||||
CastPlayer.prototype.onLaunchError = function () {
|
CastPlayer.prototype.onLaunchError = function () {
|
||||||
console.log("chromecast launch error");
|
console.debug('chromecast launch error');
|
||||||
this.deviceState = DEVICE_STATE.ERROR;
|
this.deviceState = DEVICE_STATE.ERROR;
|
||||||
sendConnectionResult(false);
|
sendConnectionResult(false);
|
||||||
};
|
};
|
||||||
|
@ -280,12 +280,12 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
* Callback function for stop app success
|
* Callback function for stop app success
|
||||||
*/
|
*/
|
||||||
CastPlayer.prototype.onStopAppSuccess = function (message) {
|
CastPlayer.prototype.onStopAppSuccess = function (message) {
|
||||||
console.log(message);
|
console.debug(message);
|
||||||
|
|
||||||
this.deviceState = DEVICE_STATE.IDLE;
|
this.deviceState = DEVICE_STATE.IDLE;
|
||||||
this.castPlayerState = PLAYER_STATE.IDLE;
|
this.castPlayerState = PLAYER_STATE.IDLE;
|
||||||
document.removeEventListener("volumeupbutton", onVolumeUpKeyDown, false);
|
document.removeEventListener('volumeupbutton', onVolumeUpKeyDown, false);
|
||||||
document.removeEventListener("volumedownbutton", onVolumeDownKeyDown, false);
|
document.removeEventListener('volumedownbutton', onVolumeDownKeyDown, false);
|
||||||
|
|
||||||
this.currentMediaSession = null;
|
this.currentMediaSession = null;
|
||||||
};
|
};
|
||||||
|
@ -296,7 +296,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
*/
|
*/
|
||||||
CastPlayer.prototype.loadMedia = function (options, command) {
|
CastPlayer.prototype.loadMedia = function (options, command) {
|
||||||
if (!this.session) {
|
if (!this.session) {
|
||||||
console.log("no session");
|
console.debug('no session');
|
||||||
return Promise.reject();
|
return Promise.reject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,7 +377,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
};
|
};
|
||||||
|
|
||||||
CastPlayer.prototype.onPlayCommandSuccess = function () {
|
CastPlayer.prototype.onPlayCommandSuccess = function () {
|
||||||
//console.log('Message was sent to receiver ok.');
|
console.debug('Message was sent to receiver ok.');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -386,7 +386,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
*/
|
*/
|
||||||
CastPlayer.prototype.onMediaDiscovered = function (how, mediaSession) {
|
CastPlayer.prototype.onMediaDiscovered = function (how, mediaSession) {
|
||||||
|
|
||||||
//console.log("chromecast new media session ID:" + mediaSession.mediaSessionId + ' (' + how + ')');
|
console.debug('chromecast new media session ID:' + mediaSession.mediaSessionId + ' (' + how + ')');
|
||||||
this.currentMediaSession = mediaSession;
|
this.currentMediaSession = mediaSession;
|
||||||
|
|
||||||
if (how === 'loadMedia') {
|
if (how === 'loadMedia') {
|
||||||
|
@ -405,7 +405,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
* @param {!Boolean} e true/false
|
* @param {!Boolean} e true/false
|
||||||
*/
|
*/
|
||||||
CastPlayer.prototype.onMediaStatusUpdate = function (e) {
|
CastPlayer.prototype.onMediaStatusUpdate = function (e) {
|
||||||
//console.log("chromecast updating media: " + e);
|
console.debug('chromecast updating media: ' + e);
|
||||||
if (e === false) {
|
if (e === false) {
|
||||||
this.castPlayerState = PLAYER_STATE.IDLE;
|
this.castPlayerState = PLAYER_STATE.IDLE;
|
||||||
}
|
}
|
||||||
|
@ -417,7 +417,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
*/
|
*/
|
||||||
CastPlayer.prototype.setReceiverVolume = function (mute, vol) {
|
CastPlayer.prototype.setReceiverVolume = function (mute, vol) {
|
||||||
if (!this.currentMediaSession) {
|
if (!this.currentMediaSession) {
|
||||||
//console.log('this.currentMediaSession is null');
|
console.debug('this.currentMediaSession is null');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,7 +443,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
* Callback function for media command success
|
* Callback function for media command success
|
||||||
*/
|
*/
|
||||||
CastPlayer.prototype.mediaCommandSuccessCallback = function (info, e) {
|
CastPlayer.prototype.mediaCommandSuccessCallback = function (info, e) {
|
||||||
//console.log(info);
|
console.debug(info);
|
||||||
};
|
};
|
||||||
|
|
||||||
function normalizeImages(state) {
|
function normalizeImages(state) {
|
||||||
|
@ -482,7 +482,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
query.Limit = query.Limit || 100;
|
query.Limit = query.Limit || 100;
|
||||||
query.ExcludeLocationTypes = "Virtual";
|
query.ExcludeLocationTypes = 'Virtual';
|
||||||
query.EnableTotalRecordCount = false;
|
query.EnableTotalRecordCount = false;
|
||||||
|
|
||||||
return apiClient.getItems(userId, query);
|
return apiClient.getItems(userId, query);
|
||||||
|
@ -493,7 +493,7 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
|
|
||||||
events.on(instance._castPlayer, eventName, function (e, data) {
|
events.on(instance._castPlayer, eventName, function (e, data) {
|
||||||
|
|
||||||
//console.log('cc: ' + eventName);
|
console.debug('cc: ' + eventName);
|
||||||
var state = instance.getPlayerStateInternal(data);
|
var state = instance.getPlayerStateInternal(data);
|
||||||
|
|
||||||
events.trigger(instance, eventName, [state]);
|
events.trigger(instance, eventName, [state]);
|
||||||
|
@ -506,13 +506,13 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
instance._castPlayer = new CastPlayer();
|
instance._castPlayer = new CastPlayer();
|
||||||
|
|
||||||
// To allow the native android app to override
|
// To allow the native android app to override
|
||||||
document.dispatchEvent(new CustomEvent("chromecastloaded", {
|
document.dispatchEvent(new CustomEvent('chromecastloaded', {
|
||||||
detail: {
|
detail: {
|
||||||
player: instance
|
player: instance
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
events.on(instance._castPlayer, "connect", function (e) {
|
events.on(instance._castPlayer, 'connect', function (e) {
|
||||||
|
|
||||||
if (currentResolve) {
|
if (currentResolve) {
|
||||||
sendConnectionResult(true);
|
sendConnectionResult(true);
|
||||||
|
@ -520,27 +520,27 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
playbackManager.setActivePlayer(PlayerName, instance.getCurrentTargetInfo());
|
playbackManager.setActivePlayer(PlayerName, instance.getCurrentTargetInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('cc: connect');
|
console.debug('cc: connect');
|
||||||
// Reset this so that statechange will fire
|
// Reset this so that statechange will fire
|
||||||
instance.lastPlayerData = null;
|
instance.lastPlayerData = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
events.on(instance._castPlayer, "playbackstart", function (e, data) {
|
events.on(instance._castPlayer, 'playbackstart', function (e, data) {
|
||||||
|
|
||||||
console.log('cc: playbackstart');
|
console.debug('cc: playbackstart');
|
||||||
|
|
||||||
instance._castPlayer.initializeCastPlayer();
|
instance._castPlayer.initializeCastPlayer();
|
||||||
|
|
||||||
var state = instance.getPlayerStateInternal(data);
|
var state = instance.getPlayerStateInternal(data);
|
||||||
events.trigger(instance, "playbackstart", [state]);
|
events.trigger(instance, 'playbackstart', [state]);
|
||||||
});
|
});
|
||||||
|
|
||||||
events.on(instance._castPlayer, "playbackstop", function (e, data) {
|
events.on(instance._castPlayer, 'playbackstop', function (e, data) {
|
||||||
|
|
||||||
console.log('cc: playbackstop');
|
console.debug('cc: playbackstop');
|
||||||
var state = instance.getPlayerStateInternal(data);
|
var state = instance.getPlayerStateInternal(data);
|
||||||
|
|
||||||
events.trigger(instance, "playbackstop", [state]);
|
events.trigger(instance, 'playbackstop', [state]);
|
||||||
|
|
||||||
var state = instance.lastPlayerData.PlayState || {};
|
var state = instance.lastPlayerData.PlayState || {};
|
||||||
var volume = state.VolumeLevel || 0.5;
|
var volume = state.VolumeLevel || 0.5;
|
||||||
|
@ -553,12 +553,12 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
instance.lastPlayerData.PlayState.IsMuted = mute;
|
instance.lastPlayerData.PlayState.IsMuted = mute;
|
||||||
});
|
});
|
||||||
|
|
||||||
events.on(instance._castPlayer, "playbackprogress", function (e, data) {
|
events.on(instance._castPlayer, 'playbackprogress', function (e, data) {
|
||||||
|
|
||||||
//console.log('cc: positionchange');
|
console.debug('cc: positionchange');
|
||||||
var state = instance.getPlayerStateInternal(data);
|
var state = instance.getPlayerStateInternal(data);
|
||||||
|
|
||||||
events.trigger(instance, "timeupdate", [state]);
|
events.trigger(instance, 'timeupdate', [state]);
|
||||||
});
|
});
|
||||||
|
|
||||||
bindEventForRelay(instance, 'timeupdate');
|
bindEventForRelay(instance, 'timeupdate');
|
||||||
|
@ -567,12 +567,12 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
bindEventForRelay(instance, 'volumechange');
|
bindEventForRelay(instance, 'volumechange');
|
||||||
bindEventForRelay(instance, 'repeatmodechange');
|
bindEventForRelay(instance, 'repeatmodechange');
|
||||||
|
|
||||||
events.on(instance._castPlayer, "playstatechange", function (e, data) {
|
events.on(instance._castPlayer, 'playstatechange', function (e, data) {
|
||||||
|
|
||||||
//console.log('cc: playstatechange');
|
console.debug('cc: playstatechange');
|
||||||
var state = instance.getPlayerStateInternal(data);
|
var state = instance.getPlayerStateInternal(data);
|
||||||
|
|
||||||
events.trigger(instance, "pause", [state]);
|
events.trigger(instance, 'pause', [state]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,24 +630,24 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
name: PlayerName,
|
name: PlayerName,
|
||||||
id: PlayerName,
|
id: PlayerName,
|
||||||
playerName: PlayerName,
|
playerName: PlayerName,
|
||||||
playableMediaTypes: ["Audio", "Video"],
|
playableMediaTypes: ['Audio', 'Video'],
|
||||||
isLocalPlayer: false,
|
isLocalPlayer: false,
|
||||||
appName: PlayerName,
|
appName: PlayerName,
|
||||||
deviceName: appName,
|
deviceName: appName,
|
||||||
supportedCommands: [
|
supportedCommands: [
|
||||||
"VolumeUp",
|
'VolumeUp',
|
||||||
"VolumeDown",
|
'VolumeDown',
|
||||||
"Mute",
|
'Mute',
|
||||||
"Unmute",
|
'Unmute',
|
||||||
"ToggleMute",
|
'ToggleMute',
|
||||||
"SetVolume",
|
'SetVolume',
|
||||||
"SetAudioStreamIndex",
|
'SetAudioStreamIndex',
|
||||||
"SetSubtitleStreamIndex",
|
'SetSubtitleStreamIndex',
|
||||||
"DisplayContent",
|
'DisplayContent',
|
||||||
"SetRepeatMode",
|
'SetRepeatMode',
|
||||||
"EndSession",
|
'EndSession',
|
||||||
"PlayMediaSource",
|
'PlayMediaSource',
|
||||||
"PlayTrailers"
|
'PlayTrailers'
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -664,10 +664,10 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
|
|
||||||
normalizeImages(data);
|
normalizeImages(data);
|
||||||
|
|
||||||
//console.log(JSON.stringify(data));
|
console.debug(JSON.stringify(data));
|
||||||
|
|
||||||
if (triggerStateChange) {
|
if (triggerStateChange) {
|
||||||
events.trigger(this, "statechange", [data]);
|
events.trigger(this, 'statechange', [data]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
@ -686,6 +686,13 @@ define(['appSettings', 'userSettings', 'playbackManager', 'connectionManager', '
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.items.length > 1 && options && options.ids) {
|
||||||
|
// Use the original request id array for sorting the result in the proper order
|
||||||
|
options.items.sort(function (a, b) {
|
||||||
|
return options.ids.indexOf(a.Id) - options.ids.indexOf(b.Id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return this._castPlayer.loadMedia(options, command);
|
return this._castPlayer.loadMedia(options, command);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,12 @@
|
||||||
define(['dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'flexStyles'], function (dialogHelper, loading, appHost, layoutManager, connectionManager, appRouter, globalize) {
|
define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'flexStyles'], function (dom, dialogHelper, loading, appHost, layoutManager, connectionManager, appRouter, globalize) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var currentServerId;
|
var currentServerId;
|
||||||
|
|
||||||
function parentWithClass(elem, className) {
|
|
||||||
|
|
||||||
while (!elem.classList || !elem.classList.contains(className)) {
|
|
||||||
elem = elem.parentNode;
|
|
||||||
|
|
||||||
if (!elem) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return elem;
|
|
||||||
}
|
|
||||||
|
|
||||||
function onSubmit(e) {
|
function onSubmit(e) {
|
||||||
loading.show();
|
loading.show();
|
||||||
|
|
||||||
var panel = parentWithClass(this, 'dialog');
|
var panel = dom.parentWithClass(this, 'dialog');
|
||||||
|
|
||||||
var collectionId = panel.querySelector('#selectCollectionToAddTo').value;
|
var collectionId = panel.querySelector('#selectCollectionToAddTo').value;
|
||||||
|
|
||||||
|
@ -37,7 +24,7 @@ define(['dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManage
|
||||||
|
|
||||||
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,
|
||||||
|
@ -45,9 +32,9 @@ define(['dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManage
|
||||||
});
|
});
|
||||||
|
|
||||||
apiClient.ajax({
|
apiClient.ajax({
|
||||||
type: "POST",
|
type: 'POST',
|
||||||
url: url,
|
url: url,
|
||||||
dataType: "json"
|
dataType: 'json'
|
||||||
|
|
||||||
}).then(function (result) {
|
}).then(function (result) {
|
||||||
|
|
||||||
|
@ -69,13 +56,13 @@ define(['dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManage
|
||||||
|
|
||||||
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 () {
|
||||||
|
@ -106,8 +93,8 @@ define(['dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManage
|
||||||
var options = {
|
var options = {
|
||||||
|
|
||||||
Recursive: true,
|
Recursive: true,
|
||||||
IncludeItemTypes: "BoxSet",
|
IncludeItemTypes: 'BoxSet',
|
||||||
SortBy: "SortName",
|
SortBy: 'SortName',
|
||||||
EnableTotalRecordCount: false
|
EnableTotalRecordCount: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -243,13 +230,13 @@ define(['dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManage
|
||||||
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="md-icon">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="md-icon">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,8 +1,32 @@
|
||||||
define(['dialog', 'globalize'], function (dialog, globalize) {
|
define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
return function (text, title) {
|
function replaceAll(str, find, replace) {
|
||||||
|
return str.split(find).join(replace);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (browser.tv && window.confirm) {
|
||||||
|
// Use the native confirm dialog
|
||||||
|
return function (options) {
|
||||||
|
if (typeof options === 'string') {
|
||||||
|
options = {
|
||||||
|
title: '',
|
||||||
|
text: options
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var text = replaceAll(options.text || '', '<br/>', '\n');
|
||||||
|
var result = confirm(text);
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
return Promise.resolve();
|
||||||
|
} else {
|
||||||
|
return Promise.reject();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// Use our own dialog
|
||||||
|
return function (text, title) {
|
||||||
var options;
|
var options;
|
||||||
if (typeof text === 'string') {
|
if (typeof text === 'string') {
|
||||||
options = {
|
options = {
|
||||||
|
@ -37,4 +61,5 @@ define(['dialog', 'globalize'], function (dialog, globalize) {
|
||||||
return Promise.reject();
|
return Promise.reject();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
define([], function () {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
function replaceAll(str, find, replace) {
|
|
||||||
|
|
||||||
return str.split(find).join(replace);
|
|
||||||
}
|
|
||||||
|
|
||||||
return function (options) {
|
|
||||||
|
|
||||||
if (typeof options === 'string') {
|
|
||||||
options = {
|
|
||||||
title: '',
|
|
||||||
text: options
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var text = replaceAll(options.text || '', '<br/>', '\n');
|
|
||||||
var result = confirm(text);
|
|
||||||
|
|
||||||
if (result) {
|
|
||||||
return Promise.resolve();
|
|
||||||
} else {
|
|
||||||
return Promise.reject();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -32,7 +32,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||||
try {
|
try {
|
||||||
parentNode.removeChild(elem);
|
parentNode.removeChild(elem);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('Error removing dialog element: ' + err);
|
console.error('error removing dialog element: ' + err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -169,6 +169,15 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||||
}, {
|
}, {
|
||||||
passive: true
|
passive: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
dom.addEventListener((dlg.dialogContainer || backdrop), 'contextmenu', function (e) {
|
||||||
|
if (e.target === dlg.dialogContainer) {
|
||||||
|
// Close the application dialog menu
|
||||||
|
close(dlg);
|
||||||
|
// Prevent the default browser context menu from appearing
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function isHistoryEnabled(dlg) {
|
function isHistoryEnabled(dlg) {
|
||||||
|
@ -242,9 +251,15 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||||
|
|
||||||
var onAnimationFinish = function () {
|
var onAnimationFinish = function () {
|
||||||
focusManager.pushScope(dlg);
|
focusManager.pushScope(dlg);
|
||||||
|
|
||||||
if (dlg.getAttribute('data-autofocus') === 'true') {
|
if (dlg.getAttribute('data-autofocus') === 'true') {
|
||||||
focusManager.autoFocus(dlg);
|
focusManager.autoFocus(dlg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (document.activeElement && !dlg.contains(document.activeElement)) {
|
||||||
|
// Blur foreign element to prevent triggering of an action from the previous scope
|
||||||
|
document.activeElement.blur();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (enableAnimation()) {
|
if (enableAnimation()) {
|
||||||
|
|
|
@ -15,10 +15,12 @@
|
||||||
|
|
||||||
.dialog {
|
.dialog {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border-radius: .2em;
|
border-radius: 0.2em;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
border: 0;
|
border: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
will-change: transform, opacity;
|
will-change: transform, opacity;
|
||||||
|
|
||||||
/* Strict does not work well with actionsheet */
|
/* Strict does not work well with actionsheet */
|
||||||
contain: style paint;
|
contain: style paint;
|
||||||
box-shadow: 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.4);
|
box-shadow: 0 16px 24px 2px rgba(0, 0, 0, 0.14), 0 6px 30px 5px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.4);
|
||||||
|
@ -50,13 +52,13 @@
|
||||||
|
|
||||||
to {
|
to {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scale(.5);
|
transform: scale(0.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes scaleup {
|
@keyframes scaleup {
|
||||||
from {
|
from {
|
||||||
transform: scale(.5);
|
transform: scale(0.5);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +79,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fadeout {
|
@keyframes fadeout {
|
||||||
|
|
||||||
from {
|
from {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
@ -100,7 +101,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes slidedown {
|
@keyframes slidedown {
|
||||||
|
|
||||||
from {
|
from {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: none;
|
transform: none;
|
||||||
|
@ -113,8 +113,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 80em), all and (max-height: 45em) {
|
@media all and (max-width: 80em), all and (max-height: 45em) {
|
||||||
|
.dialog-fixedSize,
|
||||||
.dialog-fixedSize, .dialog-fullscreen-lowres {
|
.dialog-fullscreen-lowres {
|
||||||
position: fixed !important;
|
position: fixed !important;
|
||||||
top: 0 !important;
|
top: 0 !important;
|
||||||
bottom: 0 !important;
|
bottom: 0 !important;
|
||||||
|
@ -126,7 +126,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (min-width: 80em) and (min-height: 45em) {
|
@media all and (min-width: 80em) and (min-height: 45em) {
|
||||||
|
|
||||||
.dialog-medium {
|
.dialog-medium {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
height: 80%;
|
height: 80%;
|
||||||
|
@ -168,5 +167,5 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialogBackdropOpened {
|
.dialogBackdropOpened {
|
||||||
opacity: .5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#ulDirectoryPickerList a {
|
#ulDirectoryPickerList a {
|
||||||
padding-top: .4em;
|
padding-top: 0.4em;
|
||||||
padding-bottom: .4em
|
padding-bottom: 0.4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lblDirectoryPickerPath {
|
.lblDirectoryPickerPath {
|
||||||
white-space: nowrap
|
white-space: nowrap;
|
||||||
}
|
}
|
|
@ -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() {
|
||||||
|
@ -7,24 +7,24 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
|
||||||
systemInfo = info;
|
systemInfo = info;
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDialogClosed() {
|
function onDialogClosed() {
|
||||||
loading.hide()
|
loading.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
promises.push(ApiClient.getDirectoryContents(path, fileOptions));
|
promises.push(ApiClient.getDirectoryContents(path, fileOptions));
|
||||||
|
@ -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,74 @@ 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="md-icon" style="font-size:inherit;">arrow_forward</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").replace("{0}", "<b>\\\\server</b>").replace("{1}", "<b>\\\\192.168.1.101</b>");
|
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="md-icon">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');
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -144,75 +144,74 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
|
||||||
function alertText(text) {
|
function alertText(text) {
|
||||||
alertTextWithOptions({
|
alertTextWithOptions({
|
||||||
text: text
|
text: text
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
}
|
}
|
||||||
}).catch(function(response) {
|
}).catch(function(response) {
|
||||||
if (response) {
|
if (response) {
|
||||||
// TODO All alerts (across the project), should use Globalize.translate()
|
|
||||||
if (response.status === 404) {
|
if (response.status === 404) {
|
||||||
alertText("The path could not be found. Please ensure the path is valid and try again.");
|
alertText(globalize.translate('PathNotFound'));
|
||||||
return Promise.reject();
|
return Promise.reject();
|
||||||
}
|
}
|
||||||
if (response.status === 500) {
|
if (response.status === 500) {
|
||||||
if (validateWriteable) {
|
if (validateWriteable) {
|
||||||
alertText("Jellyfin Server requires write access to this folder. Please ensure write access and try again.");
|
alertText(globalize.translate('WriteAccessRequired'));
|
||||||
} else {
|
} else {
|
||||||
alertText("The path could not be found. Please ensure the path is valid and try again.")
|
alertText(globalize.translate('PathNotFound'));
|
||||||
}
|
}
|
||||||
return Promise.reject()
|
return Promise.reject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve()
|
return Promise.resolve();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
|
@ -225,11 +224,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 '';
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -254,35 +253,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: 'medium-tall',
|
||||||
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="md-icon">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);
|
||||||
|
@ -294,9 +293,9 @@ define(['loading', 'dialogHelper', 'dom', 'listViewStyle', 'emby-input', 'paper-
|
||||||
if (currentDialog) {
|
if (currentDialog) {
|
||||||
dialogHelper.close(currentDialog);
|
dialogHelper.close(currentDialog);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var systemInfo;
|
var systemInfo;
|
||||||
return directoryBrowser
|
return directoryBrowser;
|
||||||
});
|
});
|
||||||
|
|
|
@ -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) {
|
||||||
|
@ -180,11 +180,14 @@ 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('#chkBackdrops').checked = userSettings.enableBackdrops();
|
context.querySelector('#chkBackdrops').checked = userSettings.enableBackdrops();
|
||||||
|
|
||||||
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() || '';
|
||||||
|
|
||||||
|
@ -214,8 +217,11 @@ 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.enableBackdrops(context.querySelector('#chkBackdrops').checked);
|
userSettingsInstance.enableBackdrops(context.querySelector('#chkBackdrops').checked);
|
||||||
|
|
||||||
if (user.Id === apiClient.getCurrentUserId()) {
|
if (user.Id === apiClient.getCurrentUserId()) {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
<h2 class="sectionTitle">
|
<h2 class="sectionTitle">
|
||||||
${Display}
|
${Display}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div class="selectContainer languageSection hide">
|
<div class="selectContainer languageSection hide">
|
||||||
<select id="selectLanguage" is="emby-select" label="${LabelDisplayLanguage}">
|
<select id="selectLanguage" is="emby-select" label="${LabelDisplayLanguage}">
|
||||||
<option value="">${Auto}</option>
|
<option value="">${Auto}</option>
|
||||||
|
@ -55,14 +56,14 @@
|
||||||
<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>
|
||||||
|
|
||||||
<div class="selectContainer fldDateTimeLocale hide">
|
<div class="selectContainer fldDateTimeLocale hide">
|
||||||
<select is="emby-select" class="selectDateTimeLocale" label="${LabelDateTimeLocale}">
|
<select is="emby-select" class="selectDateTimeLocale" label="${LabelDateTimeLocale}">
|
||||||
<option value="">${AutoBasedOnLanguageSetting}</option>
|
<option value="">${Auto}</option>
|
||||||
<option value="ar">Arabic</option>
|
<option value="ar">Arabic</option>
|
||||||
<option value="be-BY">Belarusian (Belarus)</option>
|
<option value="be-BY">Belarusian (Belarus)</option>
|
||||||
<option value="bg-BG">Bulgarian (Bulgaria)</option>
|
<option value="bg-BG">Bulgarian (Bulgaria)</option>
|
||||||
|
@ -133,6 +134,7 @@
|
||||||
<div class="selectContainer selectDashboardThemeContainer hide">
|
<div class="selectContainer selectDashboardThemeContainer hide">
|
||||||
<select id="selectDashboardTheme" is="emby-select" label="${LabelDashboardTheme}"></select>
|
<select id="selectDashboardTheme" is="emby-select" label="${LabelDashboardTheme}"></select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="selectContainer hide selectScreensaverContainer">
|
<div class="selectContainer hide selectScreensaverContainer">
|
||||||
<select is="emby-select" class="selectScreensaver" label="${LabelScreensaver}"></select>
|
<select is="emby-select" class="selectScreensaver" label="${LabelScreensaver}"></select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -141,6 +143,19 @@
|
||||||
<select is="emby-select" class="selectSoundEffects" label="${LabelSoundEffects}"></select>
|
<select is="emby-select" class="selectSoundEffects" label="${LabelSoundEffects}"></select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="inputContainer inputContainer-withDescription fldFadein">
|
||||||
|
<input is="emby-input" type="number" id="txtLibraryPageSize" pattern="[0-9]*" required="required" min="0" max="1000" step="1" label="${LabelLibraryPageSize}" />
|
||||||
|
<div class="fieldDescription">${LabelLibraryPageSizeHelp}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="checkboxContainer checkboxContainer-withDescription fldFadein">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" is="emby-checkbox" id="chkFadein" />
|
||||||
|
<span>${EnableFastImageFadeIn}</span>
|
||||||
|
</label>
|
||||||
|
<div class="fieldDescription checkboxFieldDescription">${EnableFastImageFadeInHelp}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription fldBackdrops hide">
|
<div class="checkboxContainer checkboxContainer-withDescription fldBackdrops hide">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" is="emby-checkbox" id="chkBackdrops" />
|
<input type="checkbox" is="emby-checkbox" id="chkBackdrops" />
|
||||||
|
@ -148,6 +163,7 @@
|
||||||
</label>
|
</label>
|
||||||
<div class="fieldDescription checkboxFieldDescription">${EnableBackdropsHelp}</div>
|
<div class="fieldDescription checkboxFieldDescription">${EnableBackdropsHelp}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription fldThemeSong hide">
|
<div class="checkboxContainer checkboxContainer-withDescription fldThemeSong hide">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" is="emby-checkbox" id="chkThemeSong" />
|
<input type="checkbox" is="emby-checkbox" id="chkThemeSong" />
|
||||||
|
@ -155,6 +171,7 @@
|
||||||
</label>
|
</label>
|
||||||
<div class="fieldDescription checkboxFieldDescription">${EnableThemeSongsHelp}</div>
|
<div class="fieldDescription checkboxFieldDescription">${EnableThemeSongsHelp}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription fldThemeVideo hide">
|
<div class="checkboxContainer checkboxContainer-withDescription fldThemeVideo hide">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" is="emby-checkbox" id="chkThemeVideo" />
|
<input type="checkbox" is="emby-checkbox" id="chkThemeVideo" />
|
||||||
|
|
|
@ -1,181 +0,0 @@
|
||||||
define([], function () {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
function parentWithAttribute(elem, name, value) {
|
|
||||||
|
|
||||||
while ((value ? elem.getAttribute(name) !== value : !elem.getAttribute(name))) {
|
|
||||||
elem = elem.parentNode;
|
|
||||||
|
|
||||||
if (!elem || !elem.getAttribute) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return elem;
|
|
||||||
}
|
|
||||||
|
|
||||||
function parentWithTag(elem, tagNames) {
|
|
||||||
|
|
||||||
// accept both string and array passed in
|
|
||||||
if (!Array.isArray(tagNames)) {
|
|
||||||
tagNames = [tagNames];
|
|
||||||
}
|
|
||||||
|
|
||||||
while (tagNames.indexOf(elem.tagName || '') === -1) {
|
|
||||||
elem = elem.parentNode;
|
|
||||||
|
|
||||||
if (!elem) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return elem;
|
|
||||||
}
|
|
||||||
|
|
||||||
function containsAnyClass(classList, classNames) {
|
|
||||||
|
|
||||||
for (var i = 0, length = classNames.length; i < length; i++) {
|
|
||||||
if (classList.contains(classNames[i])) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function parentWithClass(elem, classNames) {
|
|
||||||
|
|
||||||
// accept both string and array passed in
|
|
||||||
if (!Array.isArray(classNames)) {
|
|
||||||
classNames = [classNames];
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!elem.classList || !containsAnyClass(elem.classList, classNames)) {
|
|
||||||
elem = elem.parentNode;
|
|
||||||
|
|
||||||
if (!elem) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return elem;
|
|
||||||
}
|
|
||||||
|
|
||||||
var supportsCaptureOption = false;
|
|
||||||
try {
|
|
||||||
var opts = Object.defineProperty({}, 'capture', {
|
|
||||||
get: function () {
|
|
||||||
supportsCaptureOption = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
window.addEventListener("test", null, opts);
|
|
||||||
} catch (e) {
|
|
||||||
console.log('error checking capture support');
|
|
||||||
}
|
|
||||||
|
|
||||||
function addEventListenerWithOptions(target, type, handler, options) {
|
|
||||||
var optionsOrCapture = options;
|
|
||||||
if (!supportsCaptureOption) {
|
|
||||||
optionsOrCapture = options.capture;
|
|
||||||
}
|
|
||||||
target.addEventListener(type, handler, optionsOrCapture);
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeEventListenerWithOptions(target, type, handler, options) {
|
|
||||||
var optionsOrCapture = options;
|
|
||||||
if (!supportsCaptureOption) {
|
|
||||||
optionsOrCapture = options.capture;
|
|
||||||
}
|
|
||||||
target.removeEventListener(type, handler, optionsOrCapture);
|
|
||||||
}
|
|
||||||
|
|
||||||
var windowSize;
|
|
||||||
var windowSizeEventsBound;
|
|
||||||
function clearWindowSize() {
|
|
||||||
windowSize = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getWindowSize() {
|
|
||||||
if (!windowSize) {
|
|
||||||
windowSize = {
|
|
||||||
innerHeight: window.innerHeight,
|
|
||||||
innerWidth: window.innerWidth
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!windowSizeEventsBound) {
|
|
||||||
windowSizeEventsBound = true;
|
|
||||||
addEventListenerWithOptions(window, "orientationchange", clearWindowSize, { passive: true });
|
|
||||||
addEventListenerWithOptions(window, 'resize', clearWindowSize, { passive: true });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return windowSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
var _animationEvent;
|
|
||||||
function whichAnimationEvent() {
|
|
||||||
|
|
||||||
if (_animationEvent) {
|
|
||||||
return _animationEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
var t;
|
|
||||||
var el = document.createElement("div");
|
|
||||||
var animations = {
|
|
||||||
"animation": "animationend",
|
|
||||||
"OAnimation": "oAnimationEnd",
|
|
||||||
"MozAnimation": "animationend",
|
|
||||||
"WebkitAnimation": "webkitAnimationEnd"
|
|
||||||
};
|
|
||||||
for (t in animations) {
|
|
||||||
if (el.style[t] !== undefined) {
|
|
||||||
_animationEvent = animations[t];
|
|
||||||
return animations[t];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_animationEvent = 'animationend';
|
|
||||||
return _animationEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
function whichAnimationCancelEvent() {
|
|
||||||
|
|
||||||
return whichAnimationEvent().replace('animationend', 'animationcancel').replace('AnimationEnd', 'AnimationCancel');
|
|
||||||
}
|
|
||||||
|
|
||||||
var _transitionEvent;
|
|
||||||
function whichTransitionEvent() {
|
|
||||||
if (_transitionEvent) {
|
|
||||||
return _transitionEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
var t;
|
|
||||||
var el = document.createElement("div");
|
|
||||||
var transitions = {
|
|
||||||
"transition": "transitionend",
|
|
||||||
"OTransition": "oTransitionEnd",
|
|
||||||
"MozTransition": "transitionend",
|
|
||||||
"WebkitTransition": "webkitTransitionEnd"
|
|
||||||
};
|
|
||||||
for (t in transitions) {
|
|
||||||
if (el.style[t] !== undefined) {
|
|
||||||
_transitionEvent = transitions[t];
|
|
||||||
return transitions[t];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_transitionEvent = 'transitionend';
|
|
||||||
return _transitionEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
parentWithAttribute: parentWithAttribute,
|
|
||||||
parentWithClass: parentWithClass,
|
|
||||||
parentWithTag: parentWithTag,
|
|
||||||
addEventListener: addEventListenerWithOptions,
|
|
||||||
removeEventListener: removeEventListenerWithOptions,
|
|
||||||
getWindowSize: getWindowSize,
|
|
||||||
whichTransitionEvent: whichTransitionEvent,
|
|
||||||
whichAnimationEvent: whichAnimationEvent,
|
|
||||||
whichAnimationCancelEvent: whichAnimationCancelEvent
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -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="md-icon">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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ define([], function () {
|
||||||
|
|
||||||
function fetchWithTimeout(url, options, timeoutMs) {
|
function fetchWithTimeout(url, options, timeoutMs) {
|
||||||
|
|
||||||
console.log('fetchWithTimeout: timeoutMs: ' + timeoutMs + ', url: ' + url);
|
console.debug('fetchWithTimeout: timeoutMs: ' + timeoutMs + ', url: ' + url);
|
||||||
|
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
|
|
||||||
|
@ -63,14 +63,14 @@ define([], function () {
|
||||||
fetch(url, options).then(function (response) {
|
fetch(url, options).then(function (response) {
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
|
|
||||||
console.log('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.log('fetchWithTimeout: timed out connecting to url: ' + url);
|
console.debug('fetchWithTimeout: timed out connecting to url: ' + url);
|
||||||
|
|
||||||
reject();
|
reject();
|
||||||
});
|
});
|
||||||
|
@ -86,28 +86,24 @@ define([], function () {
|
||||||
var value = params[key];
|
var value = params[key];
|
||||||
|
|
||||||
if (value !== null && value !== undefined && value !== '') {
|
if (value !== null && value !== undefined && value !== '') {
|
||||||
values.push(encodeURIComponent(key) + "=" + encodeURIComponent(value));
|
values.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return values.join('&');
|
return values.join('&');
|
||||||
}
|
}
|
||||||
|
|
||||||
function ajax(request) {
|
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.log('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.log('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().indexOf('text/') === 0) {
|
||||||
|
@ -118,10 +114,8 @@ define([], function () {
|
||||||
} else {
|
} else {
|
||||||
return Promise.reject(response);
|
return Promise.reject(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
}, function (err) {
|
}, function (err) {
|
||||||
|
console.error('request failed to url: ' + request.url);
|
||||||
console.log('request failed to url: ' + request.url);
|
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|