Merge branch 'master' into migrate-to-ES6-18
This commit is contained in:
@@ -59,7 +59,15 @@ jobs:
|
||||
pool:
|
||||
vmImage: 'ubuntu-latest'
|
||||
|
||||
variables:
|
||||
- name: JellyfinVersion
|
||||
value: 0.0.0
|
||||
|
||||
steps:
|
||||
- script: echo "##vso[task.setvariable variable=JellyfinVersion]$( awk -F '/' '{ print $NF }' <<<'$(Build.SourceBranch)' | sed 's/^v//' )"
|
||||
displayName: Set release version (stable)
|
||||
condition: startsWith(variables['Build.SourceBranch'], 'refs/tags')
|
||||
|
||||
- task: Docker@2
|
||||
displayName: 'Push Unstable Image'
|
||||
condition: startsWith(variables['Build.SourceBranch'], 'refs/heads/master')
|
||||
@@ -84,7 +92,7 @@ jobs:
|
||||
containerRegistry: Docker Hub
|
||||
tags: |
|
||||
stable-$(Build.BuildNumber)
|
||||
stable
|
||||
$(JellyfinVersion)
|
||||
|
||||
- job: CollectArtifacts
|
||||
displayName: 'Collect Artifacts'
|
||||
|
||||
@@ -2,4 +2,4 @@ version: 1
|
||||
update_configs:
|
||||
- package_manager: "javascript"
|
||||
directory: "/"
|
||||
update_schedule: "weekly"
|
||||
update_schedule: "live"
|
||||
|
||||
+7
-5
@@ -28,7 +28,7 @@ module.exports = {
|
||||
],
|
||||
rules: {
|
||||
'block-spacing': ['error'],
|
||||
'brace-style': ['error'],
|
||||
'brace-style': ['error', "1tbs", { "allowSingleLine": true }],
|
||||
'comma-dangle': ['error', 'never'],
|
||||
'comma-spacing': ['error'],
|
||||
'eol-last': ['error'],
|
||||
@@ -39,7 +39,10 @@ module.exports = {
|
||||
'no-multi-spaces': ['error'],
|
||||
'no-multiple-empty-lines': ['error', { 'max': 1 }],
|
||||
'no-trailing-spaces': ['error'],
|
||||
'no-unused-expressions': ['error', { 'allowShortCircuit': true, 'allowTernary': true, 'allowTaggedTemplates': true }],
|
||||
"no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": true }],
|
||||
'one-var': ['error', 'never'],
|
||||
'padded-blocks': ['error', 'never'],
|
||||
'quotes': ['error', 'single', { 'avoidEscape': true, 'allowTemplateLiterals': false }],
|
||||
'semi': ['error'],
|
||||
'space-before-blocks': ['error'],
|
||||
@@ -98,9 +101,8 @@ module.exports = {
|
||||
},
|
||||
rules: {
|
||||
// TODO: Fix warnings and remove these rules
|
||||
'no-redeclare': ['warn'],
|
||||
'no-unused-vars': ['warn'],
|
||||
'no-useless-escape': ['warn'],
|
||||
'no-redeclare': ['off'],
|
||||
'no-useless-escape': ['off'],
|
||||
// TODO: Remove after ES6 migration is complete
|
||||
'import/no-unresolved': ['off']
|
||||
},
|
||||
@@ -193,4 +195,4 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
+3
-1
@@ -1,4 +1,6 @@
|
||||
.ci @dkanada @EraYaN
|
||||
.github @jellyfin/core
|
||||
build.sh @joshuaboniface
|
||||
fedora @joshuaboniface
|
||||
debian @joshuaboniface
|
||||
.copr @joshuaboniface
|
||||
deployment @joshuaboniface
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a bug report
|
||||
title: ''
|
||||
name: Bug Report
|
||||
about: You have noticed a general issue or regression, and would like to report it
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
**Describe The Bug**
|
||||
<!-- A clear and concise description of what the bug is. -->
|
||||
|
||||
**To Reproduce**
|
||||
**Steps To Reproduce**
|
||||
<!-- Steps to reproduce the behavior: -->
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
**Expected Behavior**
|
||||
<!-- A clear and concise description of what you expected to happen. -->
|
||||
|
||||
**Logs**
|
||||
@@ -27,9 +24,9 @@ assignees: ''
|
||||
<!-- If applicable, add screenshots to help explain your problem. -->
|
||||
|
||||
**System (please complete the following information):**
|
||||
- OS: [e.g. Docker, Debian, Windows]
|
||||
- Platform: [e.g. Linux, Windows, iPhone, Tizen]
|
||||
- Browser: [e.g. Firefox, Chrome, Safari]
|
||||
- Jellyfin Version: [e.g. 10.0.1]
|
||||
- Jellyfin Version: [e.g. 10.6.0]
|
||||
|
||||
**Additional context**
|
||||
**Additional Context**
|
||||
<!-- Add any other context about the problem here. -->
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
name: Playback Issue
|
||||
about: You have playback issues with some files
|
||||
labels: playback
|
||||
---
|
||||
|
||||
**Describe The Bug**
|
||||
<!-- A clear and concise description of what the bug is. -->
|
||||
|
||||
**Media Information**
|
||||
<!-- Please paste any ffprobe or MediaInfo logs. -->
|
||||
|
||||
**Screenshots**
|
||||
<!-- Add screenshots from the Playback Data and Media Info. -->
|
||||
|
||||
**System (please complete the following information):**
|
||||
- Platform: [e.g. Linux, Windows, iPhone, Tizen]
|
||||
- Browser: [e.g. Firefox, Chrome, Safari]
|
||||
- Jellyfin Version: [e.g. 10.6.0]
|
||||
|
||||
**Additional Context**
|
||||
<!-- Add any other context about the problem here. -->
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
name: Technical Discussion
|
||||
about: You want to discuss technical aspects of changes you intend to make
|
||||
labels: enhancement
|
||||
---
|
||||
|
||||
<!-- Explain the change and the motivations behind it.
|
||||
|
||||
For example, if you plan to rely on a new dependency, explain why and what
|
||||
it brings to the project.
|
||||
|
||||
If you plan to make significant changes, go roughly over the steps you intend
|
||||
to take and how you would divide the change in PRs of a manageable size. -->
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
name: Meta Issue
|
||||
about: You want to track a number of other issues as part of a larger project
|
||||
labels: meta
|
||||
---
|
||||
|
||||
* [ ] Issue 1 [#123]
|
||||
* [ ] Issue 2 [#456]
|
||||
* [ ] ...
|
||||
@@ -0,0 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Feature Request
|
||||
url: https://features.jellyfin.org/
|
||||
about: Please head over to our feature request hub to vote on or submit a feature.
|
||||
- name: Help Or Question
|
||||
url: https://matrix.to/#/#jellyfin-troubleshooting:matrix.org
|
||||
about: Please join the troubleshooting Matrix channel to get some help.
|
||||
@@ -0,0 +1,24 @@
|
||||
# Support
|
||||
|
||||
Jellyfin contributors have limited availability to address general support
|
||||
questions. Please make sure you are using the latest version of Jellyfin.
|
||||
|
||||
When looking for support or information, please first search for your
|
||||
question in these venues:
|
||||
|
||||
* [Jellyfin Forum](https://forum.jellyfin.org)
|
||||
* [Jellyfin Documentation](https://docs.jellyfin.org)
|
||||
* [Open or **closed** issues in the organization](https://github.com/issues?q=sort%3Aupdated-desc+org%3Ajellyfin+is%3Aissue+)
|
||||
|
||||
If you didn't find an answer in the resources above, contributors and other
|
||||
users are reachable through the following channels:
|
||||
|
||||
* #jellyfin on [Matrix](https://matrix.to/#/#jellyfin:matrix.org%22) or [IRC](https://webchat.freenode.net/#jellyfin)
|
||||
* #jellyfin-troubleshooting on [Matrix](https://matrix.to/#/#jellyfin-troubleshooting:matrix.org) or [IRC](https://webchat.freenode.net/#jellyfin-troubleshooting)
|
||||
* [/r/jellyfin on Reddit](https://www.reddit.com/r/jellyfin)
|
||||
|
||||
GitHub issues are for tracking enhancements and bugs, not general support.
|
||||
|
||||
The open source license grants you the freedom to use Jellyfin.
|
||||
It does not guarantee commitments of other people's time.
|
||||
Please be respectful and manage your expectations.
|
||||
@@ -44,6 +44,7 @@ Jellyfin Web is the frontend used for most of the clients available for end user
|
||||
|
||||
### Dependencies
|
||||
|
||||
- [Node.js](https://nodejs.org/en/download/)
|
||||
- [Yarn 1.22.4](https://classic.yarnpkg.com/en/docs/install)
|
||||
- Gulp-cli
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
---
|
||||
# We just wrap `build` so this is really it
|
||||
name: "jellyfin-web"
|
||||
version: "10.6.0"
|
||||
version: "10.7.0"
|
||||
packages:
|
||||
- debian.all
|
||||
- fedora.all
|
||||
|
||||
+9
-14
@@ -4,6 +4,7 @@
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o xtrace
|
||||
|
||||
usage() {
|
||||
echo -e "bump_version - increase the shared version and generate changelogs"
|
||||
@@ -23,10 +24,7 @@ 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/'
|
||||
)"
|
||||
old_version="$( grep "appVersion" ${shared_version_file} | head -1 | sed -E "s/var appVersion = '([0-9\.]+)';/\1/" | tr -d '[:space:]' )"
|
||||
echo "Old version in appHost is: $old_version"
|
||||
|
||||
# Set the shared version to the specified new_version
|
||||
@@ -34,11 +32,8 @@ old_version_sed="$( sed 's/\./\\./g' <<<"${old_version}" )" # Escape the '.' cha
|
||||
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`"
|
||||
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
|
||||
@@ -54,7 +49,7 @@ fi
|
||||
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
|
||||
echo -e "jellyfin-web (${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}
|
||||
|
||||
@@ -65,15 +60,15 @@ cat ${debian_changelog_file} >> ${debian_changelog_temp}
|
||||
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_spec_file="fedora/jellyfin-web.spec"
|
||||
fedora_changelog_temp="$( mktemp )"
|
||||
fedora_spec_temp_dir="$( mktemp -d )"
|
||||
fedora_spec_temp="${fedora_spec_temp_dir}/jellyfin.spec.tmp"
|
||||
fedora_spec_temp="${fedora_spec_temp_dir}/jellyfin-web.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
|
||||
csplit jellyfin-web.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
|
||||
@@ -92,5 +87,5 @@ mv ${fedora_spec_temp} ${fedora_spec_file}
|
||||
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 add ${shared_version_file} ${build_file} ${debian_changelog_file} ${fedora_spec_file}
|
||||
git status
|
||||
|
||||
Vendored
+6
@@ -1,3 +1,9 @@
|
||||
jellyfin-web (10.7.0-1) unstable; urgency=medium
|
||||
|
||||
* Forthcoming stable release
|
||||
|
||||
-- Jellyfin Packaging Team <packaging@jellyfin.org> Mon, 27 Jul 2020 19:13:31 -0400
|
||||
|
||||
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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
%global debug_package %{nil}
|
||||
|
||||
Name: jellyfin-web
|
||||
Version: 10.6.0
|
||||
Version: 10.7.0
|
||||
Release: 1%{?dist}
|
||||
Summary: The Free Software Media System web client
|
||||
License: GPLv3
|
||||
@@ -39,5 +39,7 @@ mv dist %{buildroot}%{_datadir}/jellyfin-web
|
||||
%{_datadir}/licenses/jellyfin/LICENSE
|
||||
|
||||
%changelog
|
||||
* Mon Jul 27 2020 Jellyfin Packaging Team <packaging@jellyfin.org>
|
||||
- Forthcoming stable release
|
||||
* Mon Mar 23 2020 Jellyfin Packaging Team <packaging@jellyfin.org>
|
||||
- Forthcoming stable release
|
||||
|
||||
+143
-15
@@ -5,18 +5,18 @@
|
||||
"repository": "https://github.com/jellyfin/jellyfin-web",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.10.3",
|
||||
"@babel/core": "^7.10.5",
|
||||
"@babel/plugin-proposal-class-properties": "^7.10.1",
|
||||
"@babel/plugin-proposal-private-methods": "^7.10.1",
|
||||
"@babel/plugin-transform-modules-amd": "^7.9.6",
|
||||
"@babel/plugin-transform-modules-amd": "^7.10.5",
|
||||
"@babel/polyfill": "^7.8.7",
|
||||
"@babel/preset-env": "^7.10.3",
|
||||
"autoprefixer": "^9.8.5",
|
||||
"babel-eslint": "^11.0.0-beta.2",
|
||||
"babel-loader": "^8.0.6",
|
||||
"browser-sync": "^2.26.7",
|
||||
"browser-sync": "^2.26.12",
|
||||
"copy-webpack-plugin": "^5.1.1",
|
||||
"css-loader": "^3.6.0",
|
||||
"css-loader": "^4.0.0",
|
||||
"cssnano": "^4.1.10",
|
||||
"del": "^5.1.0",
|
||||
"eslint": "^6.8.0",
|
||||
@@ -37,7 +37,7 @@
|
||||
"gulp-postcss": "^8.0.0",
|
||||
"gulp-sass": "^4.0.2",
|
||||
"gulp-sourcemaps": "^2.6.5",
|
||||
"gulp-terser": "^1.2.0",
|
||||
"gulp-terser": "^1.2.1",
|
||||
"html-webpack-plugin": "^4.3.0",
|
||||
"lazypipe": "^1.0.2",
|
||||
"node-sass": "^4.13.1",
|
||||
@@ -48,7 +48,7 @@
|
||||
"stylelint-config-rational-order": "^0.1.2",
|
||||
"stylelint-no-browser-hacks": "^1.2.1",
|
||||
"stylelint-order": "^4.1.0",
|
||||
"webpack": "^4.41.5",
|
||||
"webpack": "^4.44.0",
|
||||
"webpack-merge": "^4.2.2",
|
||||
"webpack-stream": "^5.2.1"
|
||||
},
|
||||
@@ -57,15 +57,15 @@
|
||||
"blurhash": "^1.1.3",
|
||||
"classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz",
|
||||
"core-js": "^3.6.5",
|
||||
"date-fns": "^2.14.0",
|
||||
"date-fns": "^2.15.0",
|
||||
"epubjs": "^0.3.85",
|
||||
"fast-text-encoding": "^1.0.3",
|
||||
"flv.js": "^1.5.0",
|
||||
"headroom.js": "^0.11.0",
|
||||
"hls.js": "^0.14.0",
|
||||
"hls.js": "^0.14.6",
|
||||
"howler": "^2.2.0",
|
||||
"intersection-observer": "^0.11.0",
|
||||
"jellyfin-apiclient": "^1.3.0",
|
||||
"jellyfin-apiclient": "^1.4.1",
|
||||
"jellyfin-noto": "https://github.com/jellyfin/jellyfin-noto",
|
||||
"jquery": "^3.5.1",
|
||||
"jstree": "^3.3.10",
|
||||
@@ -76,7 +76,6 @@
|
||||
"query-string": "^6.13.1",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"screenfull": "^5.0.2",
|
||||
"shaka-player": "^2.5.13",
|
||||
"sortablejs": "^1.10.2",
|
||||
"swiper": "^5.4.5",
|
||||
"webcomponents.js": "^0.7.24",
|
||||
@@ -91,13 +90,48 @@
|
||||
"test": [
|
||||
"src/components/accessSchedule/accessSchedule.js",
|
||||
"src/components/actionSheet/actionSheet.js",
|
||||
"src/components/activitylog.js",
|
||||
"src/components/alert.js",
|
||||
"src/components/alphaPicker/alphaPicker.js",
|
||||
"src/components/appFooter/appFooter.js",
|
||||
"src/components/autoFocuser.js",
|
||||
"src/components/backdrop/backdrop.js",
|
||||
"src/components/cardbuilder/cardBuilder.js",
|
||||
"src/components/cardbuilder/chaptercardbuilder.js",
|
||||
"src/components/cardbuilder/peoplecardbuilder.js",
|
||||
"src/components/channelMapper/channelMapper.js",
|
||||
"src/components/collectionEditor/collectionEditor.js",
|
||||
"src/components/confirm/confirm.js",
|
||||
"src/components/dialog/dialog.js",
|
||||
"src/components/dialogHelper/dialogHelper.js",
|
||||
"src/components/directorybrowser/directorybrowser.js",
|
||||
"src/components/displaySettings/displaySettings.js",
|
||||
"src/components/fetchhelper.js",
|
||||
"src/components/filterdialog/filterdialog.js",
|
||||
"src/components/groupedcards.js",
|
||||
"src/components/homeScreenSettings/homeScreenSettings.js",
|
||||
"src/components/homesections/homesections.js",
|
||||
"src/components/htmlMediaHelper.js",
|
||||
"src/components/imageOptionsEditor/imageOptionsEditor.js",
|
||||
"src/components/images/imageLoader.js",
|
||||
"src/components/imageDownloader/imageDownloader.js",
|
||||
"src/components/imageeditor/imageeditor.js",
|
||||
"src/components/imageUploader/imageUploader.js",
|
||||
"src/components/indicators/indicators.js",
|
||||
"src/components/itemContextMenu.js",
|
||||
"src/components/itemidentifier/itemidentifier.js",
|
||||
"src/components/itemMediaInfo/itemMediaInfo.js",
|
||||
"src/components/lazyLoader/lazyLoaderIntersectionObserver.js",
|
||||
"src/components/libraryoptionseditor/libraryoptionseditor.js",
|
||||
"src/components/listview/listview.js",
|
||||
"src/components/maintabsmanager.js",
|
||||
"src/components/mediainfo/mediainfo.js",
|
||||
"src/components/mediaLibraryCreator/mediaLibraryCreator.js",
|
||||
"src/components/mediaLibraryEditor/mediaLibraryEditor.js",
|
||||
"src/components/metadataEditor/metadataEditor.js",
|
||||
"src/components/metadataEditor/personEditor.js",
|
||||
"src/components/multiSelect/multiSelect.js",
|
||||
"src/components/nowPlayingBar/nowPlayingBar.js",
|
||||
"src/components/playback/brightnessosd.js",
|
||||
"src/components/playback/mediasession.js",
|
||||
"src/components/playback/nowplayinghelper.js",
|
||||
@@ -107,13 +141,38 @@
|
||||
"src/components/playback/playmethodhelper.js",
|
||||
"src/components/playback/remotecontrolautoplay.js",
|
||||
"src/components/playback/volumeosd.js",
|
||||
"src/components/playbackSettings/playbackSettings.js",
|
||||
"src/components/playerstats/playerstats.js",
|
||||
"src/components/playlisteditor/playlisteditor.js",
|
||||
"src/components/playmenu.js",
|
||||
"src/components/prompt/prompt.js",
|
||||
"src/components/sanatizefilename.js",
|
||||
"src/components/scrollManager.js",
|
||||
"src/components/search/searchfields.js",
|
||||
"src/components/search/searchresults.js",
|
||||
"src/components/settingshelper.js",
|
||||
"src/components/shortcuts.js",
|
||||
"src/components/subtitlesettings/subtitleappearancehelper.js",
|
||||
"src/components/subtitlesettings/subtitlesettings.js",
|
||||
"src/components/syncPlay/groupSelectionMenu.js",
|
||||
"src/components/syncPlay/playbackPermissionManager.js",
|
||||
"src/components/syncPlay/syncPlayManager.js",
|
||||
"src/components/syncPlay/timeSyncManager.js",
|
||||
"src/controllers/session/addServer/index.js",
|
||||
"src/controllers/session/forgotPassword/index.js",
|
||||
"src/controllers/session/redeemPassword/index.js",
|
||||
"src/controllers/session/login/index.js",
|
||||
"src/controllers/session/selectServer/index.js",
|
||||
"src/controllers/dashboard/apikeys.js",
|
||||
"src/controllers/dashboard/dashboard.js",
|
||||
"src/controllers/dashboard/devices/device.js",
|
||||
"src/controllers/dashboard/devices/devices.js",
|
||||
"src/controllers/dashboard/dlna/profile.js",
|
||||
"src/controllers/dashboard/dlna/profiles.js",
|
||||
"src/controllers/dashboard/dlna/settings.js",
|
||||
"src/controllers/dashboard/encodingsettings.js",
|
||||
"src/controllers/dashboard/general.js",
|
||||
"src/controllers/dashboard/librarydisplay.js",
|
||||
"src/controllers/dashboard/logs.js",
|
||||
"src/controllers/dashboard/plugins/repositories.js",
|
||||
"src/controllers/music/musicalbums.js",
|
||||
@@ -126,23 +185,91 @@
|
||||
"src/controllers/user/home.js",
|
||||
"src/controllers/user/playback.js",
|
||||
"src/controllers/user/subtitles.js",
|
||||
"src/controllers/dashboard/mediaLibrary.js",
|
||||
"src/controllers/dashboard/metadataImages.js",
|
||||
"src/controllers/dashboard/metadatanfo.js",
|
||||
"src/controllers/dashboard/networking.js",
|
||||
"src/controllers/dashboard/playback.js",
|
||||
"src/controllers/dashboard/plugins/repositories/index.js",
|
||||
"src/controllers/dashboard/scheduledtasks/scheduledtask.js",
|
||||
"src/controllers/dashboard/scheduledtasks/scheduledtasks.js",
|
||||
"src/controllers/dashboard/serveractivity.js",
|
||||
"src/controllers/dashboard/streaming.js",
|
||||
"src/controllers/dashboard/users/useredit.js",
|
||||
"src/controllers/dashboard/users/userlibraryaccess.js",
|
||||
"src/controllers/dashboard/users/usernew.js",
|
||||
"src/controllers/dashboard/users/userparentalcontrol.js",
|
||||
"src/controllers/dashboard/users/userpasswordpage.js",
|
||||
"src/controllers/dashboard/users/userprofilespage.js",
|
||||
"src/controllers/playback/queue/index.js",
|
||||
"src/controllers/playback/video/index.js",
|
||||
"src/controllers/searchpage.js",
|
||||
"src/controllers/shows/episodes.js",
|
||||
"src/controllers/shows/tvgenres.js",
|
||||
"src/controllers/shows/tvlatest.js",
|
||||
"src/controllers/shows/tvrecommended.js",
|
||||
"src/controllers/shows/tvshows.js",
|
||||
"src/controllers/shows/tvstudios.js",
|
||||
"src/controllers/shows/tvupcoming.js",
|
||||
"src/controllers/user/display/index.js",
|
||||
"src/controllers/user/home/index.js",
|
||||
"src/controllers/user/menu/index.js",
|
||||
"src/controllers/user/playback/index.js",
|
||||
"src/controllers/user/profile/index.js",
|
||||
"src/controllers/user/subtitles/index.js",
|
||||
"src/controllers/user/subtitles/index.js",
|
||||
"src/controllers/wizard/finish/index.js",
|
||||
"src/controllers/wizard/remote/index.js",
|
||||
"src/controllers/wizard/settings/index.js",
|
||||
"src/controllers/wizard/start/index.js",
|
||||
"src/controllers/wizard/user/index.js",
|
||||
"src/elements/emby-button/emby-button.js",
|
||||
"src/elements/emby-button/paper-icon-button-light.js",
|
||||
"src/elements/emby-checkbox/emby-checkbox.js",
|
||||
"src/elements/emby-collapse/emby-collapse.js",
|
||||
"src/elements/emby-input/emby-input.js",
|
||||
"src/elements/emby-itemrefreshindicator/emby-itemrefreshindicator.js",
|
||||
"src/elements/emby-itemscontainer/emby-itemscontainer.js",
|
||||
"src/elements/emby-playstatebutton/emby-playstatebutton.js",
|
||||
"src/elements/emby-programcell/emby-programcell.js",
|
||||
"src/elements/emby-progressbar/emby-progressbar.js",
|
||||
"src/elements/emby-progressring/emby-progressring.js",
|
||||
"src/elements/emby-radio/emby-radio.js",
|
||||
"src/elements/emby-ratingbutton/emby-ratingbutton.js",
|
||||
"src/elements/emby-scrollbuttons/emby-scrollbuttons.js",
|
||||
"src/elements/emby-scroller/emby-scroller.js",
|
||||
"src/elements/emby-select/emby-select.js",
|
||||
"src/elements/emby-slider/emby-slider.js",
|
||||
"src/elements/emby-tabs/emby-tabs.js",
|
||||
"src/elements/emby-textarea/emby-textarea.js",
|
||||
"src/elements/emby-toggle/emby-toggle.js",
|
||||
"src/plugins/backdropScreensaver/plugin.js",
|
||||
"src/plugins/bookPlayer/plugin.js",
|
||||
"src/plugins/bookPlayer/tableOfContents.js",
|
||||
"src/plugins/photoPlayer/plugin.js",
|
||||
"src/plugins/youtubePlayer/plugin.js",
|
||||
"src/scripts/alphanumericshortcuts.js",
|
||||
"src/scripts/autoBackdrops.js",
|
||||
"src/scripts/datetime.js",
|
||||
"src/scripts/deleteHelper.js",
|
||||
"src/scripts/dfnshelper.js",
|
||||
"src/scripts/dom.js",
|
||||
"src/scripts/editorsidebar.js",
|
||||
"src/scripts/fileDownloader.js",
|
||||
"src/scripts/filesystem.js",
|
||||
"src/scripts/globalize.js",
|
||||
"src/scripts/imagehelper.js",
|
||||
"src/scripts/inputManager.js",
|
||||
"src/plugins/backdropScreensaver/plugin.js",
|
||||
"src/components/filterdialog/filterdialog.js",
|
||||
"src/components/fetchhelper.js",
|
||||
"src/scripts/keyboardNavigation.js",
|
||||
"src/scripts/libraryBrowser.js",
|
||||
"src/scripts/multiDownload.js",
|
||||
"src/scripts/playlists.js",
|
||||
"src/scripts/settings/appSettings.js",
|
||||
"src/scripts/settings/userSettings.js",
|
||||
"src/scripts/settings/webSettings.js"
|
||||
"src/scripts/settings/webSettings.js",
|
||||
"src/scripts/taskbutton.js",
|
||||
"src/scripts/themeLoader.js",
|
||||
"src/scripts/touchHelper.js"
|
||||
],
|
||||
"plugins": [
|
||||
"@babel/plugin-transform-modules-amd",
|
||||
@@ -157,7 +284,7 @@
|
||||
"last 2 Chrome versions",
|
||||
"last 2 ChromeAndroid versions",
|
||||
"last 2 Safari versions",
|
||||
"last 2 iOS versions",
|
||||
"iOS > 10",
|
||||
"last 2 Edge versions",
|
||||
"Chrome 27",
|
||||
"Chrome 38",
|
||||
@@ -165,6 +292,7 @@
|
||||
"Chrome 53",
|
||||
"Chrome 56",
|
||||
"Chrome 63",
|
||||
"Edge 18",
|
||||
"Firefox ESR"
|
||||
],
|
||||
"scripts": {
|
||||
|
||||
@@ -129,3 +129,17 @@ div[data-role=page] {
|
||||
.hide-scroll {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.w-100 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.margin-auto-x {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.margin-auto-y {
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 24 24"><title>Microsoft Edge icon</title><path d="M21.86 17.86q.14 0 .25.12.1.13.1.25t-.11.33l-.32.46-.43.53-.44.5q-.21.25-.38.42l-.22.23q-.58.53-1.34 1.04-.76.51-1.6.91-.86.4-1.74.64t-1.67.24q-.9 0-1.69-.28-.8-.28-1.48-.78-.68-.5-1.22-1.17-.53-.66-.92-1.44-.38-.77-.58-1.6-.2-.83-.2-1.67 0-1 .32-1.96.33-.97.87-1.8.14.95.55 1.77.41.82 1.02 1.5.6.68 1.38 1.21.78.54 1.64.9.86.36 1.77.56.92.2 1.8.2 1.12 0 2.18-.24 1.06-.23 2.06-.72l.2-.1.2-.05zm-15.5-1.27q0 1.1.27 2.15.27 1.06.78 2.03.51.96 1.24 1.77.74.82 1.66 1.4-1.47-.2-2.8-.74-1.33-.55-2.48-1.37-1.15-.83-2.08-1.9-.92-1.07-1.58-2.33T.36 14.94Q0 13.54 0 12.06q0-.81.32-1.49.31-.68.83-1.23.53-.55 1.2-.96.66-.4 1.35-.66.74-.27 1.5-.39.78-.12 1.55-.12.7 0 1.42.1.72.12 1.4.35.68.23 1.32.57.63.35 1.16.83-.35 0-.7.07-.33.07-.65.23v-.02q-.63.28-1.2.74-.57.46-1.05 1.04-.48.58-.87 1.26-.38.67-.65 1.39-.27.71-.42 1.44-.15.72-.15 1.38zM11.96.06q1.7 0 3.33.39 1.63.38 3.07 1.15 1.43.77 2.62 1.93 1.18 1.16 1.98 2.7.49.94.76 1.96.28 1 .28 2.08 0 .89-.23 1.7-.24.8-.69 1.48-.45.68-1.1 1.22-.64.53-1.45.88-.54.24-1.11.36-.58.13-1.16.13-.42 0-.97-.03-.54-.03-1.1-.12-.55-.1-1.05-.28-.5-.19-.84-.5-.12-.09-.23-.24-.1-.16-.1-.33 0-.15.16-.35.16-.2.35-.5.2-.28.36-.68.16-.4.16-.95 0-1.06-.4-1.96-.4-.91-1.06-1.64-.66-.74-1.52-1.28-.86-.55-1.79-.89-.84-.3-1.72-.44-.87-.14-1.76-.14-1.55 0-3.06.45T.94 7.55q.71-1.74 1.81-3.13 1.1-1.38 2.52-2.35Q6.68 1.1 8.37.58q1.7-.52 3.58-.52Z" fill="#fff"/></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -78,12 +78,6 @@ _define('webcomponents', function() {
|
||||
return webcomponents;
|
||||
});
|
||||
|
||||
// shaka
|
||||
var shaka = require('shaka-player');
|
||||
_define('shaka', function() {
|
||||
return shaka;
|
||||
});
|
||||
|
||||
// libass-wasm
|
||||
var libassWasm = require('libass-wasm');
|
||||
_define('JavascriptSubtitlesOctopus', function() {
|
||||
|
||||
@@ -59,15 +59,14 @@ import 'formDialogStyle';
|
||||
|
||||
export function show(options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// TODO: remove require
|
||||
require(['text!./components/accessSchedule/accessSchedule.template.html'], template => {
|
||||
import('text!./accessSchedule.template.html').then(({default: template}) => {
|
||||
const dlg = dialogHelper.createDialog({
|
||||
removeOnClose: true,
|
||||
size: 'small'
|
||||
});
|
||||
dlg.classList.add('formDialog');
|
||||
let html = '';
|
||||
html += globalize.translateDocument(template);
|
||||
html += globalize.translateHtml(template);
|
||||
dlg.innerHTML = html;
|
||||
populateHours(dlg);
|
||||
loadSchedule(dlg, options.schedule);
|
||||
|
||||
@@ -9,7 +9,6 @@ import 'scrollStyles';
|
||||
import 'listViewStyle';
|
||||
|
||||
function getOffsets(elems) {
|
||||
|
||||
let results = [];
|
||||
|
||||
if (!document) {
|
||||
@@ -31,7 +30,6 @@ function getOffsets(elems) {
|
||||
}
|
||||
|
||||
function getPosition(options, dlg) {
|
||||
|
||||
const windowSize = dom.getWindowSize();
|
||||
const windowHeight = windowSize.innerHeight;
|
||||
const windowWidth = windowSize.innerWidth;
|
||||
@@ -73,14 +71,13 @@ function getPosition(options, dlg) {
|
||||
}
|
||||
|
||||
function centerFocus(elem, horiz, on) {
|
||||
require(['scrollHelper'], function (scrollHelper) {
|
||||
import('scrollHelper').then(({default: scrollHelper}) => {
|
||||
const fn = on ? 'on' : 'off';
|
||||
scrollHelper.centerFocus[fn](elem, horiz);
|
||||
});
|
||||
}
|
||||
|
||||
export function show(options) {
|
||||
|
||||
// items
|
||||
// positionTo
|
||||
// showCancel
|
||||
@@ -98,7 +95,6 @@ export function show(options) {
|
||||
isFullscreen = true;
|
||||
dialogOptions.autoFocus = true;
|
||||
} else {
|
||||
|
||||
dialogOptions.modal = false;
|
||||
dialogOptions.entryAnimation = options.entryAnimation;
|
||||
dialogOptions.exitAnimation = options.exitAnimation;
|
||||
@@ -136,7 +132,6 @@ export function show(options) {
|
||||
let icons = [];
|
||||
let itemIcon;
|
||||
for (const item of options.items) {
|
||||
|
||||
itemIcon = item.icon || (item.selected ? 'check' : null);
|
||||
|
||||
if (itemIcon) {
|
||||
@@ -161,7 +156,6 @@ export function show(options) {
|
||||
}
|
||||
|
||||
if (options.title) {
|
||||
|
||||
html += '<h1 class="actionSheetTitle">' + options.title + '</h1>';
|
||||
}
|
||||
if (options.text) {
|
||||
@@ -197,7 +191,6 @@ export function show(options) {
|
||||
const item = options.items[i];
|
||||
|
||||
if (item.divider) {
|
||||
|
||||
html += '<div class="actionsheetDivider"></div>';
|
||||
continue;
|
||||
}
|
||||
@@ -255,8 +248,6 @@ export function show(options) {
|
||||
});
|
||||
}
|
||||
|
||||
// Seeing an issue in some non-chrome browsers where this is requiring a double click
|
||||
//var eventName = browser.firefox ? 'mousedown' : 'click';
|
||||
let selectedId;
|
||||
|
||||
let timeout;
|
||||
@@ -267,26 +258,20 @@ export function show(options) {
|
||||
}
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
let isResolved;
|
||||
|
||||
dlg.addEventListener('click', function (e) {
|
||||
|
||||
const actionSheetMenuItem = dom.parentWithClass(e.target, 'actionSheetMenuItem');
|
||||
|
||||
if (actionSheetMenuItem) {
|
||||
selectedId = actionSheetMenuItem.getAttribute('data-id');
|
||||
|
||||
if (options.resolveOnClick) {
|
||||
|
||||
if (options.resolveOnClick.indexOf) {
|
||||
|
||||
if (options.resolveOnClick.indexOf(selectedId) !== -1) {
|
||||
|
||||
resolve(selectedId);
|
||||
isResolved = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
resolve(selectedId);
|
||||
isResolved = true;
|
||||
@@ -295,11 +280,9 @@ export function show(options) {
|
||||
|
||||
dialogHelper.close(dlg);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
dlg.addEventListener('close', function () {
|
||||
|
||||
if (layoutManager.tv) {
|
||||
centerFocus(dlg.querySelector('.actionSheetScroller'), false, false);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings', 'serverNotifications', 'connectionManager', 'emby-button', 'listViewStyle'], function (events, globalize, dom, datefns, dfnshelper, userSettings, serverNotifications, connectionManager) {
|
||||
'use strict';
|
||||
import events from 'events';
|
||||
import globalize from 'globalize';
|
||||
import dom from 'dom';
|
||||
import * as datefns from 'date-fns';
|
||||
import dfnshelper from 'dfnshelper';
|
||||
import serverNotifications from 'serverNotifications';
|
||||
import connectionManager from 'connectionManager';
|
||||
import 'emby-button';
|
||||
import 'listViewStyle';
|
||||
|
||||
/* eslint-disable indent */
|
||||
|
||||
function getEntryHtml(entry, apiClient) {
|
||||
var html = '';
|
||||
let html = '';
|
||||
html += '<div class="listItem listItem-border">';
|
||||
var color = '#00a4dc';
|
||||
var icon = 'notifications';
|
||||
let color = '#00a4dc';
|
||||
let icon = 'notifications';
|
||||
|
||||
if ('Error' == entry.Severity || 'Fatal' == entry.Severity || 'Warn' == entry.Severity) {
|
||||
color = '#cc0000';
|
||||
@@ -56,9 +65,10 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings',
|
||||
}
|
||||
|
||||
limit = limit || parseInt(elem.getAttribute('data-activitylimit') || '7');
|
||||
var minDate = new Date();
|
||||
var hasUserId = 'false' !== elem.getAttribute('data-useractivity');
|
||||
const minDate = new Date();
|
||||
const hasUserId = 'false' !== elem.getAttribute('data-useractivity');
|
||||
|
||||
// TODO: Use date-fns
|
||||
if (hasUserId) {
|
||||
minDate.setTime(minDate.getTime() - 24 * 60 * 60 * 1000); // one day back
|
||||
} else {
|
||||
@@ -74,7 +84,7 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings',
|
||||
elem.setAttribute('data-activitystartindex', startIndex);
|
||||
elem.setAttribute('data-activitylimit', limit);
|
||||
if (!startIndex) {
|
||||
var activityContainer = dom.parentWithClass(elem, 'activityContainer');
|
||||
const activityContainer = dom.parentWithClass(elem, 'activityContainer');
|
||||
|
||||
if (activityContainer) {
|
||||
if (result.Items.length) {
|
||||
@@ -91,7 +101,7 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings',
|
||||
}
|
||||
|
||||
function onActivityLogUpdate(e, apiClient, data) {
|
||||
var options = this.options;
|
||||
const options = this.options;
|
||||
|
||||
if (options && options.serverId === apiClient.serverId()) {
|
||||
reloadData(this, options.element, apiClient);
|
||||
@@ -99,14 +109,14 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings',
|
||||
}
|
||||
|
||||
function onListClick(e) {
|
||||
var btnEntryInfo = dom.parentWithClass(e.target, 'btnEntryInfo');
|
||||
const btnEntryInfo = dom.parentWithClass(e.target, 'btnEntryInfo');
|
||||
|
||||
if (btnEntryInfo) {
|
||||
var id = btnEntryInfo.getAttribute('data-id');
|
||||
var items = this.items;
|
||||
const id = btnEntryInfo.getAttribute('data-id');
|
||||
const items = this.items;
|
||||
|
||||
if (items) {
|
||||
var item = items.filter(function (i) {
|
||||
const item = items.filter(function (i) {
|
||||
return i.Id.toString() === id;
|
||||
})[0];
|
||||
|
||||
@@ -118,35 +128,35 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings',
|
||||
}
|
||||
|
||||
function showItemOverview(item) {
|
||||
require(['alert'], function (alert) {
|
||||
import('alert').then(({default: alert}) => {
|
||||
alert({
|
||||
text: item.Overview
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function ActivityLog(options) {
|
||||
class ActivityLog {
|
||||
constructor(options) {
|
||||
this.options = options;
|
||||
var element = options.element;
|
||||
const element = options.element;
|
||||
element.classList.add('activityLogListWidget');
|
||||
element.addEventListener('click', onListClick.bind(this));
|
||||
var apiClient = connectionManager.getApiClient(options.serverId);
|
||||
const apiClient = connectionManager.getApiClient(options.serverId);
|
||||
reloadData(this, element, apiClient);
|
||||
var onUpdate = onActivityLogUpdate.bind(this);
|
||||
const onUpdate = onActivityLogUpdate.bind(this);
|
||||
this.updateFn = onUpdate;
|
||||
events.on(serverNotifications, 'ActivityLogEntry', onUpdate);
|
||||
apiClient.sendMessage('ActivityLogEntryStart', '0,1500');
|
||||
}
|
||||
|
||||
ActivityLog.prototype.destroy = function () {
|
||||
var options = this.options;
|
||||
destroy() {
|
||||
const options = this.options;
|
||||
|
||||
if (options) {
|
||||
options.element.classList.remove('activityLogListWidget');
|
||||
connectionManager.getApiClient(options.serverId).sendMessage('ActivityLogEntryStop', '0,1500');
|
||||
}
|
||||
|
||||
var onUpdate = this.updateFn;
|
||||
const onUpdate = this.updateFn;
|
||||
|
||||
if (onUpdate) {
|
||||
events.off(serverNotifications, 'ActivityLogEntry', onUpdate);
|
||||
@@ -154,7 +164,9 @@ define(['events', 'globalize', 'dom', 'date-fns', 'dfnshelper', 'userSettings',
|
||||
|
||||
this.items = null;
|
||||
this.options = null;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return ActivityLog;
|
||||
});
|
||||
export default ActivityLog;
|
||||
|
||||
/* eslint-enable indent */
|
||||
|
||||
+13
-10
@@ -1,14 +1,16 @@
|
||||
define(['browser', 'dialog', 'globalize'], function (browser, dialog, globalize) {
|
||||
'use strict';
|
||||
import browser from 'browser';
|
||||
import dialog from 'dialog';
|
||||
import globalize from 'globalize';
|
||||
|
||||
/* eslint-disable indent */
|
||||
|
||||
function replaceAll(originalString, strReplace, strWith) {
|
||||
var reg = new RegExp(strReplace, 'ig');
|
||||
const reg = new RegExp(strReplace, 'ig');
|
||||
return originalString.replace(reg, strWith);
|
||||
}
|
||||
|
||||
return function (text, title) {
|
||||
|
||||
var options;
|
||||
export default function (text, title) {
|
||||
let options;
|
||||
if (typeof text === 'string') {
|
||||
options = {
|
||||
title: title,
|
||||
@@ -21,7 +23,7 @@ define(['browser', 'dialog', 'globalize'], function (browser, dialog, globalize)
|
||||
if (browser.tv && window.alert) {
|
||||
alert(replaceAll(options.text || '', '<br/>', '\n'));
|
||||
} else {
|
||||
var items = [];
|
||||
const items = [];
|
||||
|
||||
items.push({
|
||||
name: globalize.translate('ButtonGotIt'),
|
||||
@@ -31,7 +33,7 @@ define(['browser', 'dialog', 'globalize'], function (browser, dialog, globalize)
|
||||
|
||||
options.buttons = items;
|
||||
|
||||
return dialog(options).then(function (result) {
|
||||
return dialog.show(options).then(function (result) {
|
||||
if (result === 'ok') {
|
||||
return Promise.resolve();
|
||||
}
|
||||
@@ -41,5 +43,6 @@ define(['browser', 'dialog', 'globalize'], function (browser, dialog, globalize)
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/* eslint-enable indent */
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-button-light', 'material-icons'], function (focusManager, layoutManager, dom) {
|
||||
'use strict';
|
||||
/* eslint-disable indent */
|
||||
|
||||
var selectedButtonClass = 'alphaPickerButton-selected';
|
||||
/**
|
||||
* Module alphaPicker.
|
||||
* @module components/alphaPicker/alphaPicker
|
||||
*/
|
||||
|
||||
import focusManager from 'focusManager';
|
||||
import layoutManager from 'layoutManager';
|
||||
import dom from 'dom';
|
||||
import 'css!./style.css';
|
||||
import 'paper-icon-button-light';
|
||||
import 'material-icons';
|
||||
|
||||
const selectedButtonClass = 'alphaPickerButton-selected';
|
||||
|
||||
function focus() {
|
||||
var scope = this;
|
||||
var selected = scope.querySelector('.' + selectedButtonClass);
|
||||
const scope = this;
|
||||
const selected = scope.querySelector(`.${selectedButtonClass}`);
|
||||
|
||||
if (selected) {
|
||||
focusManager.focus(selected);
|
||||
@@ -15,8 +26,7 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
|
||||
}
|
||||
|
||||
function getAlphaPickerButtonClassName(vertical) {
|
||||
|
||||
var alphaPickerButtonClassName = 'alphaPickerButton';
|
||||
let alphaPickerButtonClassName = 'alphaPickerButton';
|
||||
|
||||
if (layoutManager.tv) {
|
||||
alphaPickerButtonClassName += ' alphaPickerButton-tv';
|
||||
@@ -30,44 +40,42 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
|
||||
}
|
||||
|
||||
function getLetterButton(l, vertical) {
|
||||
return '<button data-value="' + l + '" class="' + getAlphaPickerButtonClassName(vertical) + '">' + l + '</button>';
|
||||
return `<button data-value="${l}" class="${getAlphaPickerButtonClassName(vertical)}">${l}</button>`;
|
||||
}
|
||||
|
||||
function mapLetters(letters, vertical) {
|
||||
|
||||
return letters.map(function (l) {
|
||||
return letters.map(l => {
|
||||
return getLetterButton(l, vertical);
|
||||
});
|
||||
}
|
||||
|
||||
function render(element, options) {
|
||||
|
||||
element.classList.add('alphaPicker');
|
||||
|
||||
if (layoutManager.tv) {
|
||||
element.classList.add('alphaPicker-tv');
|
||||
}
|
||||
|
||||
var vertical = element.classList.contains('alphaPicker-vertical');
|
||||
const vertical = element.classList.contains('alphaPicker-vertical');
|
||||
|
||||
if (!vertical) {
|
||||
element.classList.add('focuscontainer-x');
|
||||
}
|
||||
|
||||
var html = '';
|
||||
var letters;
|
||||
let html = '';
|
||||
let letters;
|
||||
|
||||
var alphaPickerButtonClassName = getAlphaPickerButtonClassName(vertical);
|
||||
const alphaPickerButtonClassName = getAlphaPickerButtonClassName(vertical);
|
||||
|
||||
var rowClassName = 'alphaPickerRow';
|
||||
let rowClassName = 'alphaPickerRow';
|
||||
|
||||
if (vertical) {
|
||||
rowClassName += ' alphaPickerRow-vertical';
|
||||
}
|
||||
|
||||
html += '<div class="' + rowClassName + '">';
|
||||
html += `<div class="${rowClassName}">`;
|
||||
if (options.mode === 'keyboard') {
|
||||
html += '<button data-value=" " is="paper-icon-button-light" class="' + alphaPickerButtonClassName + '"><span class="material-icons alphaPickerButtonIcon space_bar"></span></button>';
|
||||
html += `<button data-value=" " is="paper-icon-button-light" class="${alphaPickerButtonClassName}"><span class="material-icons alphaPickerButtonIcon space_bar"></span></button>`;
|
||||
} else {
|
||||
letters = ['#'];
|
||||
html += mapLetters(letters, vertical).join('');
|
||||
@@ -77,11 +85,11 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
|
||||
html += mapLetters(letters, vertical).join('');
|
||||
|
||||
if (options.mode === 'keyboard') {
|
||||
html += '<button data-value="backspace" is="paper-icon-button-light" class="' + alphaPickerButtonClassName + '"><span class="material-icons alphaPickerButtonIcon backspace"></span></button>';
|
||||
html += `<button data-value="backspace" is="paper-icon-button-light" class="${alphaPickerButtonClassName}"><span class="material-icons alphaPickerButtonIcon backspace"></span></button>`;
|
||||
html += '</div>';
|
||||
|
||||
letters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
|
||||
html += '<div class="' + rowClassName + '">';
|
||||
html += `<div class="${rowClassName}">`;
|
||||
html += '<br/>';
|
||||
html += mapLetters(letters, vertical).join('');
|
||||
html += '</div>';
|
||||
@@ -95,227 +103,211 @@ define(['focusManager', 'layoutManager', 'dom', 'css!./style.css', 'paper-icon-b
|
||||
element.focus = focus;
|
||||
}
|
||||
|
||||
function AlphaPicker(options) {
|
||||
export class AlphaPicker {
|
||||
constructor(options) {
|
||||
const self = this;
|
||||
|
||||
var self = this;
|
||||
this.options = options;
|
||||
this.options = options;
|
||||
|
||||
var element = options.element;
|
||||
var itemsContainer = options.itemsContainer;
|
||||
var itemClass = options.itemClass;
|
||||
const element = options.element;
|
||||
const itemsContainer = options.itemsContainer;
|
||||
const itemClass = options.itemClass;
|
||||
|
||||
var itemFocusValue;
|
||||
var itemFocusTimeout;
|
||||
let itemFocusValue;
|
||||
let itemFocusTimeout;
|
||||
|
||||
function onItemFocusTimeout() {
|
||||
itemFocusTimeout = null;
|
||||
self.value(itemFocusValue);
|
||||
}
|
||||
|
||||
var alphaFocusedElement;
|
||||
var alphaFocusTimeout;
|
||||
|
||||
function onAlphaFocusTimeout() {
|
||||
|
||||
alphaFocusTimeout = null;
|
||||
|
||||
if (document.activeElement === alphaFocusedElement) {
|
||||
var value = alphaFocusedElement.getAttribute('data-value');
|
||||
self.value(value, true);
|
||||
function onItemFocusTimeout() {
|
||||
itemFocusTimeout = null;
|
||||
self.value(itemFocusValue);
|
||||
}
|
||||
}
|
||||
|
||||
function onAlphaPickerInKeyboardModeClick(e) {
|
||||
let alphaFocusedElement;
|
||||
let alphaFocusTimeout;
|
||||
|
||||
var alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton');
|
||||
function onAlphaFocusTimeout() {
|
||||
alphaFocusTimeout = null;
|
||||
|
||||
if (alphaPickerButton) {
|
||||
var value = alphaPickerButton.getAttribute('data-value');
|
||||
|
||||
element.dispatchEvent(new CustomEvent('alphavalueclicked', {
|
||||
cancelable: false,
|
||||
detail: {
|
||||
value: value
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
function onAlphaPickerClick(e) {
|
||||
|
||||
var alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton');
|
||||
|
||||
if (alphaPickerButton) {
|
||||
var value = alphaPickerButton.getAttribute('data-value');
|
||||
if ((this._currentValue || '').toUpperCase() === value.toUpperCase()) {
|
||||
self.value(null, true);
|
||||
} else {
|
||||
if (document.activeElement === alphaFocusedElement) {
|
||||
const value = alphaFocusedElement.getAttribute('data-value');
|
||||
self.value(value, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onAlphaPickerFocusIn(e) {
|
||||
function onAlphaPickerInKeyboardModeClick(e) {
|
||||
const alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton');
|
||||
|
||||
if (alphaFocusTimeout) {
|
||||
clearTimeout(alphaFocusTimeout);
|
||||
alphaFocusTimeout = null;
|
||||
if (alphaPickerButton) {
|
||||
const value = alphaPickerButton.getAttribute('data-value');
|
||||
|
||||
element.dispatchEvent(new CustomEvent('alphavalueclicked', {
|
||||
cancelable: false,
|
||||
detail: {
|
||||
value
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
var alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton');
|
||||
function onAlphaPickerClick(e) {
|
||||
const alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton');
|
||||
|
||||
if (alphaPickerButton) {
|
||||
alphaFocusedElement = alphaPickerButton;
|
||||
alphaFocusTimeout = setTimeout(onAlphaFocusTimeout, 600);
|
||||
}
|
||||
}
|
||||
|
||||
function onItemsFocusIn(e) {
|
||||
|
||||
var item = dom.parentWithClass(e.target, itemClass);
|
||||
|
||||
if (item) {
|
||||
var prefix = item.getAttribute('data-prefix');
|
||||
if (prefix && prefix.length) {
|
||||
|
||||
itemFocusValue = prefix[0];
|
||||
if (itemFocusTimeout) {
|
||||
clearTimeout(itemFocusTimeout);
|
||||
if (alphaPickerButton) {
|
||||
const value = alphaPickerButton.getAttribute('data-value');
|
||||
if ((this._currentValue || '').toUpperCase() === value.toUpperCase()) {
|
||||
this.value(null, true);
|
||||
} else {
|
||||
this.value(value, true);
|
||||
}
|
||||
itemFocusTimeout = setTimeout(onItemFocusTimeout, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.enabled = function (enabled) {
|
||||
|
||||
if (enabled) {
|
||||
|
||||
if (itemsContainer) {
|
||||
itemsContainer.addEventListener('focus', onItemsFocusIn, true);
|
||||
function onAlphaPickerFocusIn(e) {
|
||||
if (alphaFocusTimeout) {
|
||||
clearTimeout(alphaFocusTimeout);
|
||||
alphaFocusTimeout = null;
|
||||
}
|
||||
|
||||
if (options.mode === 'keyboard') {
|
||||
element.addEventListener('click', onAlphaPickerInKeyboardModeClick);
|
||||
}
|
||||
const alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton');
|
||||
|
||||
if (options.valueChangeEvent !== 'click') {
|
||||
element.addEventListener('focus', onAlphaPickerFocusIn, true);
|
||||
if (alphaPickerButton) {
|
||||
alphaFocusedElement = alphaPickerButton;
|
||||
alphaFocusTimeout = setTimeout(onAlphaFocusTimeout, 600);
|
||||
}
|
||||
}
|
||||
|
||||
function onItemsFocusIn(e) {
|
||||
const item = dom.parentWithClass(e.target, itemClass);
|
||||
|
||||
if (item) {
|
||||
const prefix = item.getAttribute('data-prefix');
|
||||
if (prefix && prefix.length) {
|
||||
itemFocusValue = prefix[0];
|
||||
if (itemFocusTimeout) {
|
||||
clearTimeout(itemFocusTimeout);
|
||||
}
|
||||
itemFocusTimeout = setTimeout(onItemFocusTimeout, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.enabled = function (enabled) {
|
||||
if (enabled) {
|
||||
if (itemsContainer) {
|
||||
itemsContainer.addEventListener('focus', onItemsFocusIn, true);
|
||||
}
|
||||
|
||||
if (options.mode === 'keyboard') {
|
||||
element.addEventListener('click', onAlphaPickerInKeyboardModeClick);
|
||||
}
|
||||
|
||||
if (options.valueChangeEvent !== 'click') {
|
||||
element.addEventListener('focus', onAlphaPickerFocusIn, true);
|
||||
} else {
|
||||
element.addEventListener('click', onAlphaPickerClick.bind(this));
|
||||
}
|
||||
} else {
|
||||
element.addEventListener('click', onAlphaPickerClick.bind(this));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (itemsContainer) {
|
||||
itemsContainer.removeEventListener('focus', onItemsFocusIn, true);
|
||||
}
|
||||
|
||||
element.removeEventListener('click', onAlphaPickerInKeyboardModeClick);
|
||||
element.removeEventListener('focus', onAlphaPickerFocusIn, true);
|
||||
element.removeEventListener('click', onAlphaPickerClick.bind(this));
|
||||
}
|
||||
};
|
||||
|
||||
render(element, options);
|
||||
|
||||
this.enabled(true);
|
||||
this.visible(true);
|
||||
}
|
||||
|
||||
AlphaPicker.prototype.value = function (value, applyValue) {
|
||||
|
||||
var element = this.options.element;
|
||||
var btn;
|
||||
var selected;
|
||||
|
||||
if (value !== undefined) {
|
||||
if (value != null) {
|
||||
|
||||
value = value.toUpperCase();
|
||||
this._currentValue = value;
|
||||
|
||||
if (this.options.mode !== 'keyboard') {
|
||||
selected = element.querySelector('.' + selectedButtonClass);
|
||||
|
||||
try {
|
||||
btn = element.querySelector('.alphaPickerButton[data-value=\'' + value + '\']');
|
||||
} catch (err) {
|
||||
console.error('error in querySelector: ' + err);
|
||||
if (itemsContainer) {
|
||||
itemsContainer.removeEventListener('focus', onItemsFocusIn, true);
|
||||
}
|
||||
|
||||
if (btn && btn !== selected) {
|
||||
btn.classList.add(selectedButtonClass);
|
||||
element.removeEventListener('click', onAlphaPickerInKeyboardModeClick);
|
||||
element.removeEventListener('focus', onAlphaPickerFocusIn, true);
|
||||
element.removeEventListener('click', onAlphaPickerClick.bind(this));
|
||||
}
|
||||
};
|
||||
|
||||
render(element, options);
|
||||
|
||||
this.enabled(true);
|
||||
this.visible(true);
|
||||
}
|
||||
|
||||
value(value, applyValue) {
|
||||
const element = this.options.element;
|
||||
let btn;
|
||||
let selected;
|
||||
|
||||
if (value !== undefined) {
|
||||
if (value != null) {
|
||||
value = value.toUpperCase();
|
||||
this._currentValue = value;
|
||||
|
||||
if (this.options.mode !== 'keyboard') {
|
||||
selected = element.querySelector(`.${selectedButtonClass}`);
|
||||
|
||||
try {
|
||||
btn = element.querySelector(`.alphaPickerButton[data-value='${value}']`);
|
||||
} catch (err) {
|
||||
console.error('error in querySelector:', err);
|
||||
}
|
||||
|
||||
if (btn && btn !== selected) {
|
||||
btn.classList.add(selectedButtonClass);
|
||||
}
|
||||
if (selected && selected !== btn) {
|
||||
selected.classList.remove(selectedButtonClass);
|
||||
}
|
||||
}
|
||||
if (selected && selected !== btn) {
|
||||
} else {
|
||||
this._currentValue = value;
|
||||
|
||||
selected = element.querySelector(`.${selectedButtonClass}`);
|
||||
if (selected) {
|
||||
selected.classList.remove(selectedButtonClass);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this._currentValue = value;
|
||||
|
||||
selected = element.querySelector('.' + selectedButtonClass);
|
||||
if (selected) {
|
||||
selected.classList.remove(selectedButtonClass);
|
||||
}
|
||||
}
|
||||
|
||||
if (applyValue) {
|
||||
element.dispatchEvent(new CustomEvent('alphavaluechanged', {
|
||||
cancelable: false,
|
||||
detail: {
|
||||
value
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
return this._currentValue;
|
||||
}
|
||||
|
||||
if (applyValue) {
|
||||
element.dispatchEvent(new CustomEvent('alphavaluechanged', {
|
||||
cancelable: false,
|
||||
detail: {
|
||||
value: value
|
||||
}
|
||||
}));
|
||||
on(name, fn) {
|
||||
const element = this.options.element;
|
||||
element.addEventListener(name, fn);
|
||||
}
|
||||
|
||||
return this._currentValue;
|
||||
};
|
||||
|
||||
AlphaPicker.prototype.on = function (name, fn) {
|
||||
var element = this.options.element;
|
||||
element.addEventListener(name, fn);
|
||||
};
|
||||
|
||||
AlphaPicker.prototype.off = function (name, fn) {
|
||||
var element = this.options.element;
|
||||
element.removeEventListener(name, fn);
|
||||
};
|
||||
|
||||
AlphaPicker.prototype.visible = function (visible) {
|
||||
|
||||
var element = this.options.element;
|
||||
element.style.visibility = visible ? 'visible' : 'hidden';
|
||||
};
|
||||
|
||||
AlphaPicker.prototype.values = function () {
|
||||
|
||||
var element = this.options.element;
|
||||
var elems = element.querySelectorAll('.alphaPickerButton');
|
||||
var values = [];
|
||||
for (var i = 0, length = elems.length; i < length; i++) {
|
||||
|
||||
values.push(elems[i].getAttribute('data-value'));
|
||||
|
||||
off(name, fn) {
|
||||
const element = this.options.element;
|
||||
element.removeEventListener(name, fn);
|
||||
}
|
||||
|
||||
return values;
|
||||
};
|
||||
visible(visible) {
|
||||
const element = this.options.element;
|
||||
element.style.visibility = visible ? 'visible' : 'hidden';
|
||||
}
|
||||
|
||||
AlphaPicker.prototype.focus = function () {
|
||||
values() {
|
||||
const element = this.options.element;
|
||||
const elems = element.querySelectorAll('.alphaPickerButton');
|
||||
const values = [];
|
||||
for (let i = 0, length = elems.length; i < length; i++) {
|
||||
values.push(elems[i].getAttribute('data-value'));
|
||||
}
|
||||
|
||||
var element = this.options.element;
|
||||
focusManager.autoFocus(element, true);
|
||||
};
|
||||
return values;
|
||||
}
|
||||
|
||||
AlphaPicker.prototype.destroy = function () {
|
||||
focus() {
|
||||
const element = this.options.element;
|
||||
focusManager.autoFocus(element, true);
|
||||
}
|
||||
|
||||
var element = this.options.element;
|
||||
this.enabled(false);
|
||||
element.classList.remove('focuscontainer-x');
|
||||
this.options = null;
|
||||
};
|
||||
destroy() {
|
||||
const element = this.options.element;
|
||||
this.enabled(false);
|
||||
element.classList.remove('focuscontainer-x');
|
||||
this.options = null;
|
||||
}
|
||||
}
|
||||
|
||||
return AlphaPicker;
|
||||
});
|
||||
/* eslint-enable indent */
|
||||
export default AlphaPicker;
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
define(['browser', 'css!./appFooter'], function (browser) {
|
||||
'use strict';
|
||||
import 'css!./appFooter';
|
||||
|
||||
function render(options) {
|
||||
var elem = document.createElement('div');
|
||||
elem.classList.add('appfooter');
|
||||
function render(options) {
|
||||
const elem = document.createElement('div');
|
||||
elem.classList.add('appfooter');
|
||||
|
||||
document.body.appendChild(elem);
|
||||
document.body.appendChild(elem);
|
||||
|
||||
return elem;
|
||||
}
|
||||
return elem;
|
||||
}
|
||||
|
||||
function appFooter(options) {
|
||||
var self = this;
|
||||
class appFooter {
|
||||
constructor(options) {
|
||||
const self = this;
|
||||
|
||||
self.element = render(options);
|
||||
self.add = function (elem) {
|
||||
@@ -26,12 +26,11 @@ define(['browser', 'css!./appFooter'], function (browser) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
appFooter.prototype.destroy = function () {
|
||||
destroy() {
|
||||
var self = this;
|
||||
|
||||
self.element = null;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return appFooter;
|
||||
});
|
||||
export default appFooter;
|
||||
|
||||
@@ -16,12 +16,12 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
|
||||
show('/settings/settings.html');
|
||||
},
|
||||
showNowPlaying: function () {
|
||||
show('/nowplaying.html');
|
||||
show('queue');
|
||||
}
|
||||
};
|
||||
|
||||
function beginConnectionWizard() {
|
||||
backdrop.clear();
|
||||
backdrop.clearBackdrop();
|
||||
loading.show();
|
||||
connectionManager.connect({
|
||||
enableAutoLogin: appSettings.enableAutoLogin()
|
||||
@@ -53,7 +53,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
|
||||
break;
|
||||
case 'ServerUpdateNeeded':
|
||||
require(['alert'], function (alert) {
|
||||
alert({
|
||||
alert.default({
|
||||
text: globalize.translate('ServerUpdateNeeded', 'https://github.com/jellyfin/jellyfin'),
|
||||
html: globalize.translate('ServerUpdateNeeded', '<a href="https://github.com/jellyfin/jellyfin">https://github.com/jellyfin/jellyfin</a>')
|
||||
}).then(function () {
|
||||
@@ -153,20 +153,14 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
|
||||
};
|
||||
|
||||
if (!isBackNav) {
|
||||
// Don't force a new view for home due to the back menu
|
||||
//if (route.type !== 'home') {
|
||||
onNewViewNeeded();
|
||||
return;
|
||||
//}
|
||||
}
|
||||
viewManager.tryRestoreView(currentRequest, function () {
|
||||
|
||||
// done
|
||||
currentRouteInfo = {
|
||||
route: route,
|
||||
path: ctx.path
|
||||
};
|
||||
|
||||
}).catch(function (result) {
|
||||
if (!result || !result.cancelled) {
|
||||
onNewViewNeeded();
|
||||
@@ -197,12 +191,10 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
|
||||
}
|
||||
|
||||
function onRequestFail(e, data) {
|
||||
|
||||
var apiClient = this;
|
||||
|
||||
if (data.status === 403) {
|
||||
if (data.errorCode === 'ParentalControl') {
|
||||
|
||||
var isCurrentAllowed = currentRouteInfo ? (currentRouteInfo.route.anonymous || currentRouteInfo.route.startup) : true;
|
||||
|
||||
// Bounce to the login screen, but not if a password entry fails, obviously
|
||||
@@ -210,7 +202,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
|
||||
showForcedLogoutMessage(globalize.translate('AccessRestrictedTryAgainLater'));
|
||||
appRouter.showLocalLogin(apiClient.serverId());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -237,7 +228,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
|
||||
if (navigator.connection) {
|
||||
var max = navigator.connection.downlinkMax;
|
||||
if (max && max > 0 && max < Number.POSITIVE_INFINITY) {
|
||||
|
||||
max /= 8;
|
||||
max *= 1000000;
|
||||
max *= 0.7;
|
||||
@@ -255,7 +245,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
|
||||
}
|
||||
|
||||
function onApiClientCreated(e, newApiClient) {
|
||||
|
||||
newApiClient.normalizeImageOptions = normalizeImageOptions;
|
||||
|
||||
if (browser.iOS) {
|
||||
@@ -269,12 +258,10 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
|
||||
}
|
||||
|
||||
function initApiClient(apiClient) {
|
||||
|
||||
onApiClientCreated({}, apiClient);
|
||||
}
|
||||
|
||||
function initApiClients() {
|
||||
|
||||
connectionManager.getApiClients().forEach(initApiClient);
|
||||
|
||||
events.on(connectionManager, 'apiclientcreated', onApiClientCreated);
|
||||
@@ -290,7 +277,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
|
||||
|
||||
var firstConnectionResult;
|
||||
function start(options) {
|
||||
|
||||
loading.show();
|
||||
|
||||
initApiClients();
|
||||
@@ -302,53 +288,29 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
|
||||
enableAutoLogin: appSettings.enableAutoLogin()
|
||||
|
||||
}).then(function (result) {
|
||||
|
||||
firstConnectionResult = result;
|
||||
|
||||
options = options || {};
|
||||
|
||||
page({
|
||||
click: options.click !== false,
|
||||
hashbang: options.hashbang !== false,
|
||||
enableHistory: enableHistory()
|
||||
hashbang: options.hashbang !== false
|
||||
});
|
||||
}).catch().then(function() {
|
||||
loading.hide();
|
||||
});
|
||||
}
|
||||
|
||||
function enableHistory() {
|
||||
|
||||
//if (browser.edgeUwp) {
|
||||
// return false;
|
||||
//}
|
||||
|
||||
// shows status bar on navigation
|
||||
if (browser.xboxOne) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Does not support history
|
||||
if (browser.orsay) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function enableNativeHistory() {
|
||||
return false;
|
||||
}
|
||||
|
||||
function authenticate(ctx, route, callback) {
|
||||
|
||||
var firstResult = firstConnectionResult;
|
||||
if (firstResult) {
|
||||
|
||||
firstConnectionResult = null;
|
||||
|
||||
if (firstResult.State !== 'SignedIn' && !route.anonymous) {
|
||||
|
||||
handleConnectionResult(firstResult);
|
||||
return;
|
||||
}
|
||||
@@ -377,7 +339,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
|
||||
}
|
||||
|
||||
if (apiClient && apiClient.isLoggedIn()) {
|
||||
|
||||
console.debug('appRouter - user is authenticated');
|
||||
|
||||
if (route.isDefaultRoute) {
|
||||
@@ -385,11 +346,8 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
|
||||
loadUserSkinWithOptions(ctx);
|
||||
return;
|
||||
} else if (route.roles) {
|
||||
|
||||
validateRoles(apiClient, route.roles).then(function () {
|
||||
|
||||
callback();
|
||||
|
||||
}, beginConnectionWizard);
|
||||
return;
|
||||
}
|
||||
@@ -431,8 +389,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
|
||||
var isDummyBackToHome;
|
||||
|
||||
function loadContent(ctx, route, html, request) {
|
||||
|
||||
html = globalize.translateDocument(html, route.dictionary);
|
||||
html = globalize.translateHtml(html, route.dictionary);
|
||||
request.view = html;
|
||||
|
||||
viewManager.loadView(request);
|
||||
@@ -491,7 +448,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
|
||||
}
|
||||
|
||||
function getWindowLocationSearch(win) {
|
||||
|
||||
var currentPath = currentRouteInfo ? (currentRouteInfo.path || '') : '';
|
||||
|
||||
var index = currentPath.indexOf('?');
|
||||
@@ -535,9 +491,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
|
||||
if (!document.querySelector('.dialogContainer') && startPages.indexOf(curr.type) !== -1) {
|
||||
return false;
|
||||
}
|
||||
if (enableHistory()) {
|
||||
return history.length > 1;
|
||||
}
|
||||
|
||||
return (page.len || 0) > 0;
|
||||
}
|
||||
|
||||
@@ -624,7 +578,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
|
||||
}
|
||||
|
||||
if (level === 'full' || level === 2) {
|
||||
backdrop.clear(true);
|
||||
backdrop.clearBackdrop(true);
|
||||
document.documentElement.classList.add('transparentDocument');
|
||||
backgroundContainer.classList.add('backgroundContainer-transparent');
|
||||
backdropContainer.classList.add('hide');
|
||||
@@ -644,7 +598,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
|
||||
function pushState(state, title, url) {
|
||||
state.navigate = false;
|
||||
history.pushState(state, title, url);
|
||||
|
||||
}
|
||||
|
||||
function setBaseRoute() {
|
||||
|
||||
@@ -105,6 +105,8 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
|
||||
deviceName = 'Sony PS4';
|
||||
} else if (browser.chrome) {
|
||||
deviceName = 'Chrome';
|
||||
} else if (browser.edgeChromium) {
|
||||
deviceName = 'Edge Chromium';
|
||||
} else if (browser.edge) {
|
||||
deviceName = 'Edge';
|
||||
} else if (browser.firefox) {
|
||||
@@ -257,12 +259,6 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
|
||||
features.push('fullscreenchange');
|
||||
}
|
||||
|
||||
if (browser.chrome || browser.edge && !browser.slow) {
|
||||
if (!browser.noAnimation && !browser.edgeUwp && !browser.xboxOne) {
|
||||
features.push('imageanalysis');
|
||||
}
|
||||
}
|
||||
|
||||
if (browser.tv || browser.xboxOne || browser.ps4 || browser.mobile) {
|
||||
features.push('physicalvolumecontrol');
|
||||
}
|
||||
@@ -297,7 +293,7 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
|
||||
features.push('fileinput');
|
||||
}
|
||||
|
||||
if (browser.chrome) {
|
||||
if (browser.chrome || browser.edgeChromium) {
|
||||
features.push('chromecast');
|
||||
}
|
||||
|
||||
@@ -353,7 +349,7 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
|
||||
var deviceId;
|
||||
var deviceName;
|
||||
var appName = 'Jellyfin Web';
|
||||
var appVersion = '10.6.0';
|
||||
var appVersion = '10.7.0';
|
||||
|
||||
var appHost = {
|
||||
getWindowState: function () {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings', 'css!./backdrop'], function (browser, connectionManager, playbackManager, dom, userSettings) {
|
||||
'use strict';
|
||||
import browser from 'browser';
|
||||
import connectionManager from 'connectionManager';
|
||||
import playbackManager from 'playbackManager';
|
||||
import dom from 'dom';
|
||||
import * as userSettings from 'userSettings';
|
||||
import 'css!./backdrop';
|
||||
|
||||
/* eslint-disable indent */
|
||||
|
||||
function enableAnimation(elem) {
|
||||
if (browser.slow) {
|
||||
@@ -22,71 +28,70 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
|
||||
return true;
|
||||
}
|
||||
|
||||
function Backdrop() {
|
||||
}
|
||||
class Backdrop {
|
||||
load(url, parent, existingBackdropImage) {
|
||||
const img = new Image();
|
||||
const self = this;
|
||||
|
||||
Backdrop.prototype.load = function (url, parent, existingBackdropImage) {
|
||||
var img = new Image();
|
||||
var self = this;
|
||||
|
||||
img.onload = function () {
|
||||
if (self.isDestroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
var backdropImage = document.createElement('div');
|
||||
backdropImage.classList.add('backdropImage');
|
||||
backdropImage.classList.add('displayingBackdropImage');
|
||||
backdropImage.style.backgroundImage = "url('" + url + "')";
|
||||
backdropImage.setAttribute('data-url', url);
|
||||
|
||||
backdropImage.classList.add('backdropImageFadeIn');
|
||||
parent.appendChild(backdropImage);
|
||||
|
||||
if (!enableAnimation(backdropImage)) {
|
||||
if (existingBackdropImage && existingBackdropImage.parentNode) {
|
||||
existingBackdropImage.parentNode.removeChild(existingBackdropImage);
|
||||
img.onload = () => {
|
||||
if (self.isDestroyed) {
|
||||
return;
|
||||
}
|
||||
internalBackdrop(true);
|
||||
return;
|
||||
}
|
||||
|
||||
var onAnimationComplete = function () {
|
||||
dom.removeEventListener(backdropImage, dom.whichAnimationEvent(), onAnimationComplete, {
|
||||
const backdropImage = document.createElement('div');
|
||||
backdropImage.classList.add('backdropImage');
|
||||
backdropImage.classList.add('displayingBackdropImage');
|
||||
backdropImage.style.backgroundImage = `url('${url}')`;
|
||||
backdropImage.setAttribute('data-url', url);
|
||||
|
||||
backdropImage.classList.add('backdropImageFadeIn');
|
||||
parent.appendChild(backdropImage);
|
||||
|
||||
if (!enableAnimation(backdropImage)) {
|
||||
if (existingBackdropImage && existingBackdropImage.parentNode) {
|
||||
existingBackdropImage.parentNode.removeChild(existingBackdropImage);
|
||||
}
|
||||
internalBackdrop(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const onAnimationComplete = () => {
|
||||
dom.removeEventListener(backdropImage, dom.whichAnimationEvent(), onAnimationComplete, {
|
||||
once: true
|
||||
});
|
||||
if (backdropImage === self.currentAnimatingElement) {
|
||||
self.currentAnimatingElement = null;
|
||||
}
|
||||
if (existingBackdropImage && existingBackdropImage.parentNode) {
|
||||
existingBackdropImage.parentNode.removeChild(existingBackdropImage);
|
||||
}
|
||||
};
|
||||
|
||||
dom.addEventListener(backdropImage, dom.whichAnimationEvent(), onAnimationComplete, {
|
||||
once: true
|
||||
});
|
||||
if (backdropImage === self.currentAnimatingElement) {
|
||||
self.currentAnimatingElement = null;
|
||||
}
|
||||
if (existingBackdropImage && existingBackdropImage.parentNode) {
|
||||
existingBackdropImage.parentNode.removeChild(existingBackdropImage);
|
||||
}
|
||||
|
||||
internalBackdrop(true);
|
||||
};
|
||||
|
||||
dom.addEventListener(backdropImage, dom.whichAnimationEvent(), onAnimationComplete, {
|
||||
once: true
|
||||
});
|
||||
|
||||
internalBackdrop(true);
|
||||
};
|
||||
|
||||
img.src = url;
|
||||
};
|
||||
|
||||
Backdrop.prototype.cancelAnimation = function () {
|
||||
var elem = this.currentAnimatingElement;
|
||||
if (elem) {
|
||||
elem.classList.remove('backdropImageFadeIn');
|
||||
this.currentAnimatingElement = null;
|
||||
img.src = url;
|
||||
}
|
||||
};
|
||||
|
||||
Backdrop.prototype.destroy = function () {
|
||||
this.isDestroyed = true;
|
||||
this.cancelAnimation();
|
||||
};
|
||||
cancelAnimation() {
|
||||
const elem = this.currentAnimatingElement;
|
||||
if (elem) {
|
||||
elem.classList.remove('backdropImageFadeIn');
|
||||
this.currentAnimatingElement = null;
|
||||
}
|
||||
}
|
||||
|
||||
var backdropContainer;
|
||||
destroy() {
|
||||
this.isDestroyed = true;
|
||||
this.cancelAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
let backdropContainer;
|
||||
function getBackdropContainer() {
|
||||
if (!backdropContainer) {
|
||||
backdropContainer = document.querySelector('.backdropContainer');
|
||||
@@ -101,7 +106,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
|
||||
return backdropContainer;
|
||||
}
|
||||
|
||||
function clearBackdrop(clearAll) {
|
||||
export function clearBackdrop(clearAll) {
|
||||
clearRotation();
|
||||
|
||||
if (currentLoadingBackdrop) {
|
||||
@@ -109,7 +114,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
|
||||
currentLoadingBackdrop = null;
|
||||
}
|
||||
|
||||
var elem = getBackdropContainer();
|
||||
const elem = getBackdropContainer();
|
||||
elem.innerHTML = '';
|
||||
|
||||
if (clearAll) {
|
||||
@@ -119,7 +124,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
|
||||
internalBackdrop(false);
|
||||
}
|
||||
|
||||
var backgroundContainer;
|
||||
let backgroundContainer;
|
||||
function getBackgroundContainer() {
|
||||
if (!backgroundContainer) {
|
||||
backgroundContainer = document.querySelector('.backgroundContainer');
|
||||
@@ -135,31 +140,27 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
|
||||
}
|
||||
}
|
||||
|
||||
var hasInternalBackdrop;
|
||||
let hasInternalBackdrop;
|
||||
function internalBackdrop(enabled) {
|
||||
hasInternalBackdrop = enabled;
|
||||
setBackgroundContainerBackgroundEnabled();
|
||||
}
|
||||
|
||||
var hasExternalBackdrop;
|
||||
function externalBackdrop(enabled) {
|
||||
let hasExternalBackdrop;
|
||||
export function externalBackdrop(enabled) {
|
||||
hasExternalBackdrop = enabled;
|
||||
setBackgroundContainerBackgroundEnabled();
|
||||
}
|
||||
|
||||
function getRandom(min, max) {
|
||||
return Math.floor(Math.random() * (max - min) + min);
|
||||
}
|
||||
|
||||
var currentLoadingBackdrop;
|
||||
let currentLoadingBackdrop;
|
||||
function setBackdropImage(url) {
|
||||
if (currentLoadingBackdrop) {
|
||||
currentLoadingBackdrop.destroy();
|
||||
currentLoadingBackdrop = null;
|
||||
}
|
||||
|
||||
var elem = getBackdropContainer();
|
||||
var existingBackdropImage = elem.querySelector('.displayingBackdropImage');
|
||||
const elem = getBackdropContainer();
|
||||
const existingBackdropImage = elem.querySelector('.displayingBackdropImage');
|
||||
|
||||
if (existingBackdropImage && existingBackdropImage.getAttribute('data-url') === url) {
|
||||
if (existingBackdropImage.getAttribute('data-url') === url) {
|
||||
@@ -168,7 +169,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
|
||||
existingBackdropImage.classList.remove('displayingBackdropImage');
|
||||
}
|
||||
|
||||
var instance = new Backdrop();
|
||||
const instance = new Backdrop();
|
||||
instance.load(url, elem, existingBackdropImage);
|
||||
currentLoadingBackdrop = instance;
|
||||
}
|
||||
@@ -176,9 +177,9 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
|
||||
function getItemImageUrls(item, imageOptions) {
|
||||
imageOptions = imageOptions || {};
|
||||
|
||||
var apiClient = connectionManager.getApiClient(item.ServerId);
|
||||
const apiClient = connectionManager.getApiClient(item.ServerId);
|
||||
if (item.BackdropImageTags && item.BackdropImageTags.length > 0) {
|
||||
return item.BackdropImageTags.map(function (imgTag, index) {
|
||||
return item.BackdropImageTags.map((imgTag, index) => {
|
||||
return apiClient.getScaledImageUrl(item.BackdropItemId || item.Id, Object.assign(imageOptions, {
|
||||
type: 'Backdrop',
|
||||
tag: imgTag,
|
||||
@@ -189,7 +190,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
|
||||
}
|
||||
|
||||
if (item.ParentBackdropItemId && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) {
|
||||
return item.ParentBackdropImageTags.map(function (imgTag, index) {
|
||||
return item.ParentBackdropImageTags.map((imgTag, index) => {
|
||||
return apiClient.getScaledImageUrl(item.ParentBackdropItemId, Object.assign(imageOptions, {
|
||||
type: 'Backdrop',
|
||||
tag: imgTag,
|
||||
@@ -203,13 +204,13 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
|
||||
}
|
||||
|
||||
function getImageUrls(items, imageOptions) {
|
||||
var list = [];
|
||||
var onImg = function (img) {
|
||||
const list = [];
|
||||
const onImg = img => {
|
||||
list.push(img);
|
||||
};
|
||||
|
||||
for (var i = 0, length = items.length; i < length; i++) {
|
||||
var itemImages = getItemImageUrls(items[i], imageOptions);
|
||||
for (let i = 0, length = items.length; i < length; i++) {
|
||||
const itemImages = getItemImageUrls(items[i], imageOptions);
|
||||
itemImages.forEach(onImg);
|
||||
}
|
||||
|
||||
@@ -229,7 +230,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
|
||||
|
||||
// If you don't care about the order of the elements inside
|
||||
// the array, you should sort both arrays here.
|
||||
for (var i = 0; i < a.length; ++i) {
|
||||
for (let i = 0; i < a.length; ++i) {
|
||||
if (a[i] !== b[i]) {
|
||||
return false;
|
||||
}
|
||||
@@ -242,12 +243,12 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
|
||||
return userSettings.enableBackdrops();
|
||||
}
|
||||
|
||||
var rotationInterval;
|
||||
var currentRotatingImages = [];
|
||||
var currentRotationIndex = -1;
|
||||
function setBackdrops(items, imageOptions, enableImageRotation) {
|
||||
let rotationInterval;
|
||||
let currentRotatingImages = [];
|
||||
let currentRotationIndex = -1;
|
||||
export function setBackdrops(items, imageOptions, enableImageRotation) {
|
||||
if (enabled()) {
|
||||
var images = getImageUrls(items, imageOptions);
|
||||
const images = getImageUrls(items, imageOptions);
|
||||
|
||||
if (images.length) {
|
||||
startRotation(images, enableImageRotation);
|
||||
@@ -279,7 +280,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
|
||||
return;
|
||||
}
|
||||
|
||||
var newIndex = currentRotationIndex + 1;
|
||||
let newIndex = currentRotationIndex + 1;
|
||||
if (newIndex >= currentRotatingImages.length) {
|
||||
newIndex = 0;
|
||||
}
|
||||
@@ -289,7 +290,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
|
||||
}
|
||||
|
||||
function clearRotation() {
|
||||
var interval = rotationInterval;
|
||||
const interval = rotationInterval;
|
||||
if (interval) {
|
||||
clearInterval(interval);
|
||||
}
|
||||
@@ -299,7 +300,7 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
|
||||
currentRotationIndex = -1;
|
||||
}
|
||||
|
||||
function setBackdrop(url, imageOptions) {
|
||||
export function setBackdrop(url, imageOptions) {
|
||||
if (url && typeof url !== 'string') {
|
||||
url = getImageUrls([url], imageOptions)[0];
|
||||
}
|
||||
@@ -312,10 +313,11 @@ define(['browser', 'connectionManager', 'playbackManager', 'dom', 'userSettings'
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
setBackdrops: setBackdrops,
|
||||
setBackdrop: setBackdrop,
|
||||
clear: clearBackdrop,
|
||||
externalBackdrop: externalBackdrop
|
||||
};
|
||||
});
|
||||
/* eslint-enable indent */
|
||||
|
||||
export default {
|
||||
setBackdrops: setBackdrops,
|
||||
setBackdrop: setBackdrop,
|
||||
clearBackdrop: clearBackdrop,
|
||||
externalBackdrop: externalBackdrop
|
||||
};
|
||||
|
||||
@@ -291,12 +291,10 @@ import 'programStyles';
|
||||
const primaryImageAspectRatio = imageLoader.getPrimaryImageAspectRatio(items);
|
||||
|
||||
if (['auto', 'autohome', 'autooverflow', 'autoVertical'].includes(options.shape)) {
|
||||
|
||||
const requestedShape = options.shape;
|
||||
options.shape = null;
|
||||
|
||||
if (primaryImageAspectRatio) {
|
||||
|
||||
if (primaryImageAspectRatio >= 3) {
|
||||
options.shape = 'banner';
|
||||
options.coverImage = true;
|
||||
@@ -394,7 +392,6 @@ import 'programStyles';
|
||||
}
|
||||
|
||||
if (newIndexValue !== currentIndexValue) {
|
||||
|
||||
if (hasOpenRow) {
|
||||
html += '</div>';
|
||||
hasOpenRow = false;
|
||||
@@ -402,7 +399,6 @@ import 'programStyles';
|
||||
}
|
||||
|
||||
if (hasOpenSection) {
|
||||
|
||||
html += '</div>';
|
||||
|
||||
if (isVertical) {
|
||||
@@ -426,7 +422,6 @@ import 'programStyles';
|
||||
}
|
||||
|
||||
if (options.rows && itemsInRow === 0) {
|
||||
|
||||
if (hasOpenRow) {
|
||||
html += '</div>';
|
||||
hasOpenRow = false;
|
||||
@@ -686,7 +681,6 @@ import 'programStyles';
|
||||
let valid = 0;
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
|
||||
let currentCssClass = cssClass;
|
||||
let text = lines[i];
|
||||
|
||||
@@ -713,7 +707,6 @@ import 'programStyles';
|
||||
}
|
||||
|
||||
if (forceLines) {
|
||||
|
||||
let linesLength = maxLines || Math.min(lines.length, maxLines || lines.length);
|
||||
|
||||
while (valid < linesLength) {
|
||||
@@ -745,7 +738,6 @@ import 'programStyles';
|
||||
let airTimeText = '';
|
||||
|
||||
if (item.StartDate) {
|
||||
|
||||
try {
|
||||
let date = datetime.parseISO8601Date(item.StartDate);
|
||||
|
||||
@@ -792,7 +784,6 @@ import 'programStyles';
|
||||
const showOtherText = isOuterFooter ? !overlayText : overlayText;
|
||||
|
||||
if (isOuterFooter && options.cardLayout && layoutManager.mobile) {
|
||||
|
||||
if (options.cardFooterAside !== 'none') {
|
||||
html += '<button is="paper-icon-button-light" class="itemAction btnCardOptions cardText-secondary" data-action="menu"><span class="material-icons more_vert"></span></button>';
|
||||
}
|
||||
@@ -807,9 +798,7 @@ import 'programStyles';
|
||||
|
||||
if (showOtherText) {
|
||||
if ((options.showParentTitle || options.showParentTitleOrTitle) && !parentTitleUnderneath) {
|
||||
|
||||
if (isOuterFooter && item.Type === 'Episode' && item.SeriesName) {
|
||||
|
||||
if (item.SeriesId) {
|
||||
lines.push(getTextActionButton({
|
||||
Id: item.SeriesId,
|
||||
@@ -822,15 +811,12 @@ import 'programStyles';
|
||||
lines.push(item.SeriesName);
|
||||
}
|
||||
} else {
|
||||
|
||||
if (isUsingLiveTvNaming(item)) {
|
||||
|
||||
lines.push(item.Name);
|
||||
|
||||
if (!item.EpisodeTitle) {
|
||||
titleAdded = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
const parentTitle = item.SeriesName || item.Series || item.Album || item.AlbumArtist || '';
|
||||
|
||||
@@ -848,7 +834,6 @@ import 'programStyles';
|
||||
}
|
||||
|
||||
if (showMediaTitle) {
|
||||
|
||||
const name = options.showTitle === 'auto' && !item.IsFolder && item.MediaType === 'Photo' ? '' : itemHelper.getDisplayName(item, {
|
||||
includeParentInfo: options.includeParentInfoInTitle
|
||||
});
|
||||
@@ -865,7 +850,6 @@ import 'programStyles';
|
||||
|
||||
if (showOtherText) {
|
||||
if (options.showParentTitle && parentTitleUnderneath) {
|
||||
|
||||
if (isOuterFooter && item.AlbumArtists && item.AlbumArtists.length) {
|
||||
item.AlbumArtists[0].Type = 'MusicArtist';
|
||||
item.AlbumArtists[0].IsFolder = true;
|
||||
@@ -899,7 +883,6 @@ import 'programStyles';
|
||||
}
|
||||
|
||||
if (options.showPremiereDate) {
|
||||
|
||||
if (item.PremiereDate) {
|
||||
try {
|
||||
lines.push(datetime.toLocaleDateString(
|
||||
@@ -908,7 +891,6 @@ import 'programStyles';
|
||||
));
|
||||
} catch (err) {
|
||||
lines.push('');
|
||||
|
||||
}
|
||||
} else {
|
||||
lines.push('');
|
||||
@@ -916,14 +898,10 @@ import 'programStyles';
|
||||
}
|
||||
|
||||
if (options.showYear || options.showSeriesYear) {
|
||||
|
||||
if (item.Type === 'Series') {
|
||||
if (item.Status === 'Continuing') {
|
||||
|
||||
lines.push(globalize.translate('SeriesYearToPresent', item.ProductionYear || ''));
|
||||
|
||||
} else {
|
||||
|
||||
if (item.EndDate && item.ProductionYear) {
|
||||
const endYear = datetime.parseISO8601Date(item.EndDate).getFullYear();
|
||||
lines.push(item.ProductionYear + ((endYear === item.ProductionYear) ? '' : (' - ' + endYear)));
|
||||
@@ -937,9 +915,7 @@ import 'programStyles';
|
||||
}
|
||||
|
||||
if (options.showRuntime) {
|
||||
|
||||
if (item.RunTimeTicks) {
|
||||
|
||||
lines.push(datetime.getDisplayRunningTime(item.RunTimeTicks));
|
||||
} else {
|
||||
lines.push('');
|
||||
@@ -947,14 +923,11 @@ import 'programStyles';
|
||||
}
|
||||
|
||||
if (options.showAirTime) {
|
||||
|
||||
lines.push(getAirTimeText(item, options.showAirDateTime, options.showAirEndTime) || '');
|
||||
}
|
||||
|
||||
if (options.showChannelName) {
|
||||
|
||||
if (item.ChannelId) {
|
||||
|
||||
lines.push(getTextActionButton({
|
||||
|
||||
Id: item.ChannelId,
|
||||
@@ -971,7 +944,6 @@ import 'programStyles';
|
||||
}
|
||||
|
||||
if (options.showCurrentProgram && item.Type === 'TvChannel') {
|
||||
|
||||
if (item.CurrentProgram) {
|
||||
lines.push(item.CurrentProgram.Name);
|
||||
} else {
|
||||
@@ -980,7 +952,6 @@ import 'programStyles';
|
||||
}
|
||||
|
||||
if (options.showCurrentProgramTime && item.Type === 'TvChannel') {
|
||||
|
||||
if (item.CurrentProgram) {
|
||||
lines.push(getAirTimeText(item.CurrentProgram, false, true) || '');
|
||||
} else {
|
||||
@@ -990,7 +961,6 @@ import 'programStyles';
|
||||
|
||||
if (options.showSeriesTimerTime) {
|
||||
if (item.RecordAnyTime) {
|
||||
|
||||
lines.push(globalize.translate('Anytime'));
|
||||
} else {
|
||||
lines.push(datetime.getDisplayTime(item.StartDate));
|
||||
@@ -1025,7 +995,6 @@ import 'programStyles';
|
||||
}
|
||||
|
||||
if (html) {
|
||||
|
||||
if (!isOuterFooter || logoUrl || options.cardLayout) {
|
||||
html = '<div class="' + footerClass + '">' + html;
|
||||
|
||||
@@ -1071,27 +1040,21 @@ import 'programStyles';
|
||||
let childText;
|
||||
|
||||
if (item.Type === 'Playlist') {
|
||||
|
||||
childText = '';
|
||||
|
||||
if (item.RunTimeTicks) {
|
||||
|
||||
let minutes = item.RunTimeTicks / 600000000;
|
||||
|
||||
minutes = minutes || 1;
|
||||
|
||||
childText += globalize.translate('ValueMinutes', Math.round(minutes));
|
||||
|
||||
} else {
|
||||
childText += globalize.translate('ValueMinutes', 0);
|
||||
}
|
||||
|
||||
counts.push(childText);
|
||||
|
||||
} else if (item.Type === 'Genre' || item.Type === 'Studio') {
|
||||
|
||||
if (item.MovieCount) {
|
||||
|
||||
childText = item.MovieCount === 1 ?
|
||||
globalize.translate('ValueOneMovie') :
|
||||
globalize.translate('ValueMovieCount', item.MovieCount);
|
||||
@@ -1100,7 +1063,6 @@ import 'programStyles';
|
||||
}
|
||||
|
||||
if (item.SeriesCount) {
|
||||
|
||||
childText = item.SeriesCount === 1 ?
|
||||
globalize.translate('ValueOneSeries') :
|
||||
globalize.translate('ValueSeriesCount', item.SeriesCount);
|
||||
@@ -1108,18 +1070,14 @@ import 'programStyles';
|
||||
counts.push(childText);
|
||||
}
|
||||
if (item.EpisodeCount) {
|
||||
|
||||
childText = item.EpisodeCount === 1 ?
|
||||
globalize.translate('ValueOneEpisode') :
|
||||
globalize.translate('ValueEpisodeCount', item.EpisodeCount);
|
||||
|
||||
counts.push(childText);
|
||||
}
|
||||
|
||||
} else if (item.Type === 'MusicGenre' || options.context === 'MusicArtist') {
|
||||
|
||||
if (item.AlbumCount) {
|
||||
|
||||
childText = item.AlbumCount === 1 ?
|
||||
globalize.translate('ValueOneAlbum') :
|
||||
globalize.translate('ValueAlbumCount', item.AlbumCount);
|
||||
@@ -1127,7 +1085,6 @@ import 'programStyles';
|
||||
counts.push(childText);
|
||||
}
|
||||
if (item.SongCount) {
|
||||
|
||||
childText = item.SongCount === 1 ?
|
||||
globalize.translate('ValueOneSong') :
|
||||
globalize.translate('ValueSongCount', item.SongCount);
|
||||
@@ -1135,16 +1092,13 @@ import 'programStyles';
|
||||
counts.push(childText);
|
||||
}
|
||||
if (item.MusicVideoCount) {
|
||||
|
||||
childText = item.MusicVideoCount === 1 ?
|
||||
globalize.translate('ValueOneMusicVideo') :
|
||||
globalize.translate('ValueMusicVideoCount', item.MusicVideoCount);
|
||||
|
||||
counts.push(childText);
|
||||
}
|
||||
|
||||
} else if (item.Type === 'Series') {
|
||||
|
||||
childText = item.RecursiveItemCount === 1 ?
|
||||
globalize.translate('ValueOneEpisode') :
|
||||
globalize.translate('ValueEpisodeCount', item.RecursiveItemCount);
|
||||
@@ -1160,10 +1114,11 @@ import 'programStyles';
|
||||
/**
|
||||
* Imports the refresh indicator element.
|
||||
*/
|
||||
function requireRefreshIndicator() {
|
||||
function importRefreshIndicator() {
|
||||
if (!refreshIndicatorLoaded) {
|
||||
refreshIndicatorLoaded = true;
|
||||
require(['emby-itemrefreshindicator']);
|
||||
/* eslint-disable-next-line no-unused-expressions */
|
||||
import('emby-itemrefreshindicator');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1197,13 +1152,11 @@ import 'programStyles';
|
||||
let shape = options.shape;
|
||||
|
||||
if (shape === 'mixed') {
|
||||
|
||||
shape = null;
|
||||
|
||||
const primaryImageAspectRatio = item.PrimaryImageAspectRatio;
|
||||
|
||||
if (primaryImageAspectRatio) {
|
||||
|
||||
if (primaryImageAspectRatio >= 1.33) {
|
||||
shape = 'mixedBackdrop';
|
||||
} else if (primaryImageAspectRatio > 0.71) {
|
||||
@@ -1295,7 +1248,6 @@ import 'programStyles';
|
||||
}
|
||||
|
||||
if (overlayText) {
|
||||
|
||||
logoUrl = null;
|
||||
|
||||
footerCssClass = progressHtml ? 'innerCardFooter fullInnerCardFooter' : 'innerCardFooter';
|
||||
@@ -1404,7 +1356,6 @@ import 'programStyles';
|
||||
indicatorsHtml += indicators.getTypeIndicator(item);
|
||||
|
||||
if (options.showGroupCount) {
|
||||
|
||||
indicatorsHtml += indicators.getChildCountIndicatorHtml(item, {
|
||||
minCount: 1
|
||||
});
|
||||
@@ -1415,7 +1366,7 @@ import 'programStyles';
|
||||
if (item.Type === 'CollectionFolder' || item.CollectionType) {
|
||||
const refreshClass = item.RefreshProgress ? '' : ' class="hide"';
|
||||
indicatorsHtml += '<div is="emby-itemrefreshindicator"' + refreshClass + ' data-progress="' + (item.RefreshProgress || 0) + '" data-status="' + item.RefreshStatus + '"></div>';
|
||||
requireRefreshIndicator();
|
||||
importRefreshIndicator();
|
||||
}
|
||||
|
||||
if (indicatorsHtml) {
|
||||
@@ -1498,15 +1449,16 @@ import 'programStyles';
|
||||
const userData = item.UserData || {};
|
||||
|
||||
if (itemHelper.canMarkPlayed(item)) {
|
||||
require(['emby-playstatebutton']);
|
||||
/* eslint-disable-next-line no-unused-expressions */
|
||||
import('emby-playstatebutton');
|
||||
html += '<button is="emby-playstatebutton" type="button" data-action="none" class="' + btnCssClass + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-played="' + (userData.Played) + '"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover check"></span></button>';
|
||||
}
|
||||
|
||||
if (itemHelper.canRate(item)) {
|
||||
|
||||
const likes = userData.Likes == null ? '' : userData.Likes;
|
||||
|
||||
require(['emby-ratingbutton']);
|
||||
/* eslint-disable-next-line no-unused-expressions */
|
||||
import('emby-ratingbutton');
|
||||
html += '<button is="emby-ratingbutton" type="button" data-action="none" class="' + btnCssClass + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-likes="' + likes + '" data-isfavorite="' + (userData.IsFavorite) + '"><span class="material-icons cardOverlayButtonIcon cardOverlayButtonIcon-hover favorite"></span></button>';
|
||||
}
|
||||
|
||||
@@ -1583,7 +1535,6 @@ import 'programStyles';
|
||||
const html = buildCardsHtmlInternal(items, options);
|
||||
|
||||
if (html) {
|
||||
|
||||
if (options.itemsContainer.cardBuilderHtml !== html) {
|
||||
options.itemsContainer.innerHTML = html;
|
||||
|
||||
@@ -1596,7 +1547,6 @@ import 'programStyles';
|
||||
|
||||
imageLoader.lazyChildren(options.itemsContainer);
|
||||
} else {
|
||||
|
||||
options.itemsContainer.innerHTML = html;
|
||||
options.itemsContainer.cardBuilderHtml = null;
|
||||
}
|
||||
@@ -1620,7 +1570,6 @@ import 'programStyles';
|
||||
indicatorsElem = card.querySelector('.cardIndicators');
|
||||
|
||||
if (!indicatorsElem) {
|
||||
|
||||
const cardImageContainer = card.querySelector('.cardImageContainer');
|
||||
indicatorsElem = document.createElement('div');
|
||||
indicatorsElem.classList.add('cardIndicators');
|
||||
@@ -1644,11 +1593,9 @@ import 'programStyles';
|
||||
let itemProgressBar = null;
|
||||
|
||||
if (userData.Played) {
|
||||
|
||||
playedIndicator = card.querySelector('.playedIndicator');
|
||||
|
||||
if (!playedIndicator) {
|
||||
|
||||
playedIndicator = document.createElement('div');
|
||||
playedIndicator.classList.add('playedIndicator');
|
||||
playedIndicator.classList.add('indicator');
|
||||
@@ -1657,10 +1604,8 @@ import 'programStyles';
|
||||
}
|
||||
playedIndicator.innerHTML = '<span class="material-icons indicatorIcon check"></span>';
|
||||
} else {
|
||||
|
||||
playedIndicator = card.querySelector('.playedIndicator');
|
||||
if (playedIndicator) {
|
||||
|
||||
playedIndicator.parentNode.removeChild(playedIndicator);
|
||||
}
|
||||
}
|
||||
@@ -1668,7 +1613,6 @@ import 'programStyles';
|
||||
countIndicator = card.querySelector('.countIndicator');
|
||||
|
||||
if (!countIndicator) {
|
||||
|
||||
countIndicator = document.createElement('div');
|
||||
countIndicator.classList.add('countIndicator');
|
||||
indicatorsElem = ensureIndicators(card, indicatorsElem);
|
||||
@@ -1676,10 +1620,8 @@ import 'programStyles';
|
||||
}
|
||||
countIndicator.innerHTML = userData.UnplayedItemCount;
|
||||
} else if (enableCountIndicator) {
|
||||
|
||||
countIndicator = card.querySelector('.countIndicator');
|
||||
if (countIndicator) {
|
||||
|
||||
countIndicator.parentNode.removeChild(countIndicator);
|
||||
}
|
||||
}
|
||||
@@ -1691,7 +1633,6 @@ import 'programStyles';
|
||||
});
|
||||
|
||||
if (progressHtml) {
|
||||
|
||||
itemProgressBar = card.querySelector('.itemProgressBar');
|
||||
|
||||
if (!itemProgressBar) {
|
||||
@@ -1710,7 +1651,6 @@ import 'programStyles';
|
||||
|
||||
itemProgressBar.innerHTML = progressHtml;
|
||||
} else {
|
||||
|
||||
itemProgressBar = card.querySelector('.itemProgressBar');
|
||||
if (itemProgressBar) {
|
||||
itemProgressBar.parentNode.removeChild(itemProgressBar);
|
||||
|
||||
@@ -14,7 +14,6 @@ import browser from 'browser';
|
||||
const enableFocusTransform = !browser.slow && !browser.edge;
|
||||
|
||||
function buildChapterCardsHtml(item, chapters, options) {
|
||||
|
||||
// TODO move card creation code to Card component
|
||||
|
||||
let className = 'card itemAction chapterCard';
|
||||
@@ -35,7 +34,6 @@ import browser from 'browser';
|
||||
let shape = (options.backdropShape || 'backdrop');
|
||||
|
||||
if (videoStream.Width && videoStream.Height) {
|
||||
|
||||
if ((videoStream.Width / videoStream.Height) <= 1.2) {
|
||||
shape = (options.squareShape || 'square');
|
||||
}
|
||||
@@ -53,7 +51,6 @@ import browser from 'browser';
|
||||
const apiClient = connectionManager.getApiClient(item.ServerId);
|
||||
|
||||
for (let i = 0, length = chapters.length; i < length; i++) {
|
||||
|
||||
if (options.rows && itemsInRow === 0) {
|
||||
html += '<div class="cardColumn">';
|
||||
}
|
||||
@@ -73,9 +70,7 @@ import browser from 'browser';
|
||||
}
|
||||
|
||||
function getImgUrl({Id}, {ImageTag}, index, maxWidth, apiClient) {
|
||||
|
||||
if (ImageTag) {
|
||||
|
||||
return apiClient.getScaledImageUrl(Id, {
|
||||
|
||||
maxWidth: maxWidth * 2,
|
||||
@@ -89,7 +84,6 @@ import browser from 'browser';
|
||||
}
|
||||
|
||||
function buildChapterCard(item, apiClient, chapter, index, {width, coverImage}, className, shape) {
|
||||
|
||||
const imgUrl = getImgUrl(item, chapter, index, width || 400, apiClient);
|
||||
|
||||
let cardImageContainerClass = 'cardContent cardContent-shadow cardImageContainer chapterCardImageContainer';
|
||||
@@ -116,7 +110,6 @@ import browser from 'browser';
|
||||
}
|
||||
|
||||
export function buildChapterCards(item, chapters, options) {
|
||||
|
||||
if (options.parentContainer) {
|
||||
// Abort if the container has been disposed
|
||||
if (!document.body.contains(options.parentContainer)) {
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
import cardBuilder from 'cardBuilder';
|
||||
|
||||
export function buildPeopleCards(items, options) {
|
||||
|
||||
options = Object.assign(options || {}, {
|
||||
cardLayout: false,
|
||||
centerText: true,
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'actionsheet', 'emby-input', 'paper-icon-button-light', 'emby-button', 'listViewStyle', 'material-icons', 'formDialogStyle'], function (dom, dialogHelper, loading, connectionManager, globalize, actionsheet) {
|
||||
'use strict';
|
||||
import dom from 'dom';
|
||||
import dialogHelper from 'dialogHelper';
|
||||
import loading from 'loading';
|
||||
import connectionManager from 'connectionManager';
|
||||
import globalize from 'globalize';
|
||||
import actionsheet from 'actionsheet';
|
||||
import 'emby-input';
|
||||
import 'paper-icon-button-light';
|
||||
import 'emby-button';
|
||||
import 'listViewStyle';
|
||||
import 'material-icons';
|
||||
import 'formDialogStyle';
|
||||
|
||||
return function (options) {
|
||||
export default class channelMapper {
|
||||
constructor(options) {
|
||||
function mapChannel(button, channelId, providerChannelId) {
|
||||
loading.show();
|
||||
var providerId = options.providerId;
|
||||
const providerId = options.providerId;
|
||||
connectionManager.getApiClient(options.serverId).ajax({
|
||||
type: 'POST',
|
||||
url: ApiClient.getUrl('LiveTv/ChannelMappings'),
|
||||
@@ -14,8 +25,8 @@ define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'act
|
||||
providerChannelId: providerChannelId
|
||||
},
|
||||
dataType: 'json'
|
||||
}).then(function (mapping) {
|
||||
var listItem = dom.parentWithClass(button, 'listItem');
|
||||
}).then(mapping => {
|
||||
const listItem = dom.parentWithClass(button, 'listItem');
|
||||
button.setAttribute('data-providerid', mapping.ProviderChannelId);
|
||||
listItem.querySelector('.secondary').innerHTML = getMappingSecondaryName(mapping, currentMappingOptions.ProviderName);
|
||||
loading.hide();
|
||||
@@ -23,42 +34,42 @@ define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'act
|
||||
}
|
||||
|
||||
function onChannelsElementClick(e) {
|
||||
var btnMap = dom.parentWithClass(e.target, 'btnMap');
|
||||
const btnMap = dom.parentWithClass(e.target, 'btnMap');
|
||||
|
||||
if (btnMap) {
|
||||
var channelId = btnMap.getAttribute('data-id');
|
||||
var providerChannelId = btnMap.getAttribute('data-providerid');
|
||||
var menuItems = currentMappingOptions.ProviderChannels.map(function (m) {
|
||||
const channelId = btnMap.getAttribute('data-id');
|
||||
const providerChannelId = btnMap.getAttribute('data-providerid');
|
||||
const menuItems = currentMappingOptions.ProviderChannels.map(m => {
|
||||
return {
|
||||
name: m.Name,
|
||||
id: m.Id,
|
||||
selected: m.Id.toLowerCase() === providerChannelId.toLowerCase()
|
||||
};
|
||||
}).sort(function (a, b) {
|
||||
}).sort((a, b) => {
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
actionsheet.show({
|
||||
positionTo: btnMap,
|
||||
items: menuItems
|
||||
}).then(function (newChannelId) {
|
||||
}).then(newChannelId => {
|
||||
mapChannel(btnMap, channelId, newChannelId);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getChannelMappingOptions(serverId, providerId) {
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
const apiClient = connectionManager.getApiClient(serverId);
|
||||
return apiClient.getJSON(apiClient.getUrl('LiveTv/ChannelMappingOptions', {
|
||||
providerId: providerId
|
||||
}));
|
||||
}
|
||||
|
||||
function getMappingSecondaryName(mapping, providerName) {
|
||||
return (mapping.ProviderChannelName || '') + ' - ' + providerName;
|
||||
return `${mapping.ProviderChannelName || ''} - ${providerName}`;
|
||||
}
|
||||
|
||||
function getTunerChannelHtml(channel, providerName) {
|
||||
var html = '';
|
||||
let html = '';
|
||||
html += '<div class="listItem">';
|
||||
html += '<span class="material-icons listItemIcon dvr"></span>';
|
||||
html += '<div class="listItemBody two-line">';
|
||||
@@ -73,16 +84,16 @@ define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'act
|
||||
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
html += '<button class="btnMap autoSize" is="paper-icon-button-light" type="button" data-id="' + channel.Id + '" data-providerid="' + channel.ProviderChannelId + '"><span class="material-icons mode_edit"></span></button>';
|
||||
html += `<button class="btnMap autoSize" is="paper-icon-button-light" type="button" data-id="${channel.Id}" data-providerid="${channel.ProviderChannelId}"><span class="material-icons mode_edit"></span></button>`;
|
||||
return html += '</div>';
|
||||
}
|
||||
|
||||
function getEditorHtml() {
|
||||
var html = '';
|
||||
let html = '';
|
||||
html += '<div class="formDialogContent smoothScrollY">';
|
||||
html += '<div class="dialogContentInner dialog-content-centered">';
|
||||
html += '<form style="margin:auto;">';
|
||||
html += '<h1>' + globalize.translate('HeaderChannels') + '</h1>';
|
||||
html += `<h1>${globalize.translate('HeaderChannels')}</h1>`;
|
||||
html += '<div class="channels paperList">';
|
||||
html += '</div>';
|
||||
html += '</form>';
|
||||
@@ -91,30 +102,29 @@ define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'act
|
||||
}
|
||||
|
||||
function initEditor(dlg, options) {
|
||||
getChannelMappingOptions(options.serverId, options.providerId).then(function (result) {
|
||||
getChannelMappingOptions(options.serverId, options.providerId).then(result => {
|
||||
currentMappingOptions = result;
|
||||
var channelsElement = dlg.querySelector('.channels');
|
||||
channelsElement.innerHTML = result.TunerChannels.map(function (channel) {
|
||||
const channelsElement = dlg.querySelector('.channels');
|
||||
channelsElement.innerHTML = result.TunerChannels.map(channel => {
|
||||
return getTunerChannelHtml(channel, result.ProviderName);
|
||||
}).join('');
|
||||
channelsElement.addEventListener('click', onChannelsElementClick);
|
||||
});
|
||||
}
|
||||
|
||||
var currentMappingOptions;
|
||||
var self = this;
|
||||
let currentMappingOptions;
|
||||
|
||||
self.show = function () {
|
||||
var dialogOptions = {
|
||||
this.show = () => {
|
||||
const dialogOptions = {
|
||||
removeOnClose: true
|
||||
};
|
||||
dialogOptions.size = 'small';
|
||||
var dlg = dialogHelper.createDialog(dialogOptions);
|
||||
const dlg = dialogHelper.createDialog(dialogOptions);
|
||||
dlg.classList.add('formDialog');
|
||||
dlg.classList.add('ui-body-a');
|
||||
dlg.classList.add('background-theme-a');
|
||||
var html = '';
|
||||
var title = globalize.translate('MapChannels');
|
||||
let html = '';
|
||||
const title = globalize.translate('MapChannels');
|
||||
html += '<div class="formDialogHeader">';
|
||||
html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
|
||||
html += '<h3 class="formDialogHeaderTitle">';
|
||||
@@ -124,13 +134,13 @@ define(['dom', 'dialogHelper', 'loading', 'connectionManager', 'globalize', 'act
|
||||
html += getEditorHtml();
|
||||
dlg.innerHTML = html;
|
||||
initEditor(dlg, options);
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', function () {
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', () => {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
return new Promise(function (resolve, reject) {
|
||||
return new Promise(resolve => {
|
||||
dlg.addEventListener('close', resolve);
|
||||
dialogHelper.open(dlg);
|
||||
});
|
||||
};
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,31 @@
|
||||
define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'flexStyles'], function (dom, dialogHelper, loading, appHost, layoutManager, connectionManager, appRouter, globalize) {
|
||||
'use strict';
|
||||
import dom from 'dom';
|
||||
import dialogHelper from 'dialogHelper';
|
||||
import loading from 'loading';
|
||||
import layoutManager from 'layoutManager';
|
||||
import connectionManager from 'connectionManager';
|
||||
import appRouter from 'appRouter';
|
||||
import globalize from 'globalize';
|
||||
import 'emby-checkbox';
|
||||
import 'emby-input';
|
||||
import 'paper-icon-button-light';
|
||||
import 'emby-select';
|
||||
import 'material-icons';
|
||||
import 'css!./../formdialog';
|
||||
import 'emby-button';
|
||||
import 'flexStyles';
|
||||
|
||||
var currentServerId;
|
||||
/* eslint-disable indent */
|
||||
|
||||
let currentServerId;
|
||||
|
||||
function onSubmit(e) {
|
||||
loading.show();
|
||||
|
||||
var panel = dom.parentWithClass(this, 'dialog');
|
||||
const panel = dom.parentWithClass(this, 'dialog');
|
||||
|
||||
var collectionId = panel.querySelector('#selectCollectionToAddTo').value;
|
||||
const collectionId = panel.querySelector('#selectCollectionToAddTo').value;
|
||||
|
||||
var apiClient = connectionManager.getApiClient(currentServerId);
|
||||
const apiClient = connectionManager.getApiClient(currentServerId);
|
||||
|
||||
if (collectionId) {
|
||||
addToCollection(apiClient, panel, collectionId);
|
||||
@@ -23,8 +38,7 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
|
||||
}
|
||||
|
||||
function createCollection(apiClient, dlg) {
|
||||
|
||||
var url = apiClient.getUrl('Collections', {
|
||||
const url = apiClient.getUrl('Collections', {
|
||||
|
||||
Name: dlg.querySelector('#txtNewCollectionName').value,
|
||||
IsLocked: !dlg.querySelector('#chkEnableInternetMetadata').checked,
|
||||
@@ -36,27 +50,23 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
|
||||
url: url,
|
||||
dataType: 'json'
|
||||
|
||||
}).then(function (result) {
|
||||
|
||||
}).then(result => {
|
||||
loading.hide();
|
||||
|
||||
var id = result.Id;
|
||||
const id = result.Id;
|
||||
|
||||
dlg.submitted = true;
|
||||
dialogHelper.close(dlg);
|
||||
redirectToCollection(apiClient, id);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function redirectToCollection(apiClient, id) {
|
||||
|
||||
appRouter.showItem(id, apiClient.serverId());
|
||||
}
|
||||
|
||||
function addToCollection(apiClient, dlg, id) {
|
||||
|
||||
var url = apiClient.getUrl('Collections/' + id + '/Items', {
|
||||
const url = apiClient.getUrl(`Collections/${id}/Items`, {
|
||||
|
||||
Ids: dlg.querySelector('.fldSelectedItemIds').value || ''
|
||||
});
|
||||
@@ -65,14 +75,13 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
|
||||
type: 'POST',
|
||||
url: url
|
||||
|
||||
}).then(function () {
|
||||
|
||||
}).then(() => {
|
||||
loading.hide();
|
||||
|
||||
dlg.submitted = true;
|
||||
dialogHelper.close(dlg);
|
||||
|
||||
require(['toast'], function (toast) {
|
||||
import('toast').then(({default: toast}) => {
|
||||
toast(globalize.translate('MessageItemsAdded'));
|
||||
});
|
||||
});
|
||||
@@ -83,14 +92,13 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
|
||||
}
|
||||
|
||||
function populateCollections(panel) {
|
||||
|
||||
loading.show();
|
||||
|
||||
var select = panel.querySelector('#selectCollectionToAddTo');
|
||||
const select = panel.querySelector('#selectCollectionToAddTo');
|
||||
|
||||
panel.querySelector('.newCollectionInfo').classList.add('hide');
|
||||
|
||||
var options = {
|
||||
const options = {
|
||||
|
||||
Recursive: true,
|
||||
IncludeItemTypes: 'BoxSet',
|
||||
@@ -98,16 +106,14 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
|
||||
EnableTotalRecordCount: false
|
||||
};
|
||||
|
||||
var apiClient = connectionManager.getApiClient(currentServerId);
|
||||
apiClient.getItems(apiClient.getCurrentUserId(), options).then(function (result) {
|
||||
const apiClient = connectionManager.getApiClient(currentServerId);
|
||||
apiClient.getItems(apiClient.getCurrentUserId(), options).then(result => {
|
||||
let html = '';
|
||||
|
||||
var html = '';
|
||||
html += `<option value="">${globalize.translate('OptionNew')}</option>`;
|
||||
|
||||
html += '<option value="">' + globalize.translate('OptionNew') + '</option>';
|
||||
|
||||
html += result.Items.map(function (i) {
|
||||
|
||||
return '<option value="' + i.Id + '">' + i.Name + '</option>';
|
||||
html += result.Items.map(i => {
|
||||
return `<option value="${i.Id}">${i.Name}</option>`;
|
||||
});
|
||||
|
||||
select.innerHTML = html;
|
||||
@@ -119,8 +125,7 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
|
||||
}
|
||||
|
||||
function getEditorHtml() {
|
||||
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
html += '<div class="formDialogContent smoothScrollY" style="padding-top:2em;">';
|
||||
html += '<div class="dialogContentInner dialog-content-centered">';
|
||||
@@ -134,27 +139,27 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
|
||||
html += '<br/>';
|
||||
html += '<br/>';
|
||||
html += '<div class="selectContainer">';
|
||||
html += '<select is="emby-select" label="' + globalize.translate('LabelCollection') + '" id="selectCollectionToAddTo" autofocus></select>';
|
||||
html += `<select is="emby-select" label="${globalize.translate('LabelCollection')}" id="selectCollectionToAddTo" autofocus></select>`;
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
|
||||
html += '<div class="newCollectionInfo">';
|
||||
|
||||
html += '<div class="inputContainer">';
|
||||
html += '<input is="emby-input" type="text" id="txtNewCollectionName" required="required" label="' + globalize.translate('LabelName') + '" />';
|
||||
html += '<div class="fieldDescription">' + globalize.translate('NewCollectionNameExample') + '</div>';
|
||||
html += `<input is="emby-input" type="text" id="txtNewCollectionName" required="required" label="${globalize.translate('LabelName')}" />`;
|
||||
html += `<div class="fieldDescription">${globalize.translate('NewCollectionNameExample')}</div>`;
|
||||
html += '</div>';
|
||||
|
||||
html += '<label class="checkboxContainer">';
|
||||
html += '<input is="emby-checkbox" type="checkbox" id="chkEnableInternetMetadata" />';
|
||||
html += '<span>' + globalize.translate('SearchForCollectionInternetMetadata') + '</span>';
|
||||
html += `<span>${globalize.translate('SearchForCollectionInternetMetadata')}</span>`;
|
||||
html += '</label>';
|
||||
|
||||
// newCollectionInfo
|
||||
html += '</div>';
|
||||
|
||||
html += '<div class="formDialogFooter">';
|
||||
html += '<button is="emby-button" type="submit" class="raised btnSubmit block formDialogFooterItem button-submit">' + globalize.translate('ButtonOk') + '</button>';
|
||||
html += `<button is="emby-button" type="submit" class="raised btnSubmit block formDialogFooterItem button-submit">${globalize.translate('ButtonOk')}</button>`;
|
||||
html += '</div>';
|
||||
|
||||
html += '<input type="hidden" class="fldSelectedItemIds" />';
|
||||
@@ -167,7 +172,6 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
|
||||
}
|
||||
|
||||
function initEditor(content, items) {
|
||||
|
||||
content.querySelector('#selectCollectionToAddTo').addEventListener('change', function () {
|
||||
if (this.value) {
|
||||
content.querySelector('.newCollectionInfo').classList.add('hide');
|
||||
@@ -188,7 +192,7 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
|
||||
} else {
|
||||
content.querySelector('.fldSelectCollection').classList.add('hide');
|
||||
|
||||
var selectCollectionToAddTo = content.querySelector('#selectCollectionToAddTo');
|
||||
const selectCollectionToAddTo = content.querySelector('#selectCollectionToAddTo');
|
||||
selectCollectionToAddTo.innerHTML = '';
|
||||
selectCollectionToAddTo.value = '';
|
||||
triggerChange(selectCollectionToAddTo);
|
||||
@@ -196,79 +200,70 @@ define(['dom', 'dialogHelper', 'loading', 'apphost', 'layoutManager', 'connectio
|
||||
}
|
||||
|
||||
function centerFocus(elem, horiz, on) {
|
||||
require(['scrollHelper'], function (scrollHelper) {
|
||||
var fn = on ? 'on' : 'off';
|
||||
import('scrollHelper').then(scrollHelper => {
|
||||
const fn = on ? 'on' : 'off';
|
||||
scrollHelper.centerFocus[fn](elem, horiz);
|
||||
});
|
||||
}
|
||||
|
||||
function CollectionEditor() {
|
||||
export class showEditor {
|
||||
constructor(options) {
|
||||
const items = options.items || {};
|
||||
currentServerId = options.serverId;
|
||||
|
||||
}
|
||||
|
||||
CollectionEditor.prototype.show = function (options) {
|
||||
|
||||
var items = options.items || {};
|
||||
currentServerId = options.serverId;
|
||||
|
||||
var dialogOptions = {
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
};
|
||||
|
||||
if (layoutManager.tv) {
|
||||
dialogOptions.size = 'fullscreen';
|
||||
} else {
|
||||
dialogOptions.size = 'small';
|
||||
}
|
||||
|
||||
var dlg = dialogHelper.createDialog(dialogOptions);
|
||||
|
||||
dlg.classList.add('formDialog');
|
||||
|
||||
var html = '';
|
||||
var title = items.length ? globalize.translate('HeaderAddToCollection') : globalize.translate('NewCollection');
|
||||
|
||||
html += '<div class="formDialogHeader">';
|
||||
html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
|
||||
html += '<h3 class="formDialogHeaderTitle">';
|
||||
html += title;
|
||||
html += '</h3>';
|
||||
|
||||
if (appHost.supports('externallinks')) {
|
||||
html += '<a is="emby-linkbutton" class="button-link btnHelp flex align-items-center" href="https://web.archive.org/web/20181216120305/https://github.com/MediaBrowser/Wiki/wiki/Collections" target="_blank" style="margin-left:auto;margin-right:.5em;padding:.25em;" title="' + globalize.translate('Help') + '"><span class="material-icons info"></span><span style="margin-left:.25em;">' + globalize.translate('Help') + '</span></a>';
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
|
||||
html += getEditorHtml();
|
||||
|
||||
dlg.innerHTML = html;
|
||||
|
||||
initEditor(dlg, items);
|
||||
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', function () {
|
||||
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
|
||||
if (layoutManager.tv) {
|
||||
centerFocus(dlg.querySelector('.formDialogContent'), false, true);
|
||||
}
|
||||
|
||||
return dialogHelper.open(dlg).then(function () {
|
||||
const dialogOptions = {
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
};
|
||||
|
||||
if (layoutManager.tv) {
|
||||
centerFocus(dlg.querySelector('.formDialogContent'), false, false);
|
||||
dialogOptions.size = 'fullscreen';
|
||||
} else {
|
||||
dialogOptions.size = 'small';
|
||||
}
|
||||
|
||||
if (dlg.submitted) {
|
||||
return Promise.resolve();
|
||||
const dlg = dialogHelper.createDialog(dialogOptions);
|
||||
|
||||
dlg.classList.add('formDialog');
|
||||
|
||||
let html = '';
|
||||
const title = items.length ? globalize.translate('HeaderAddToCollection') : globalize.translate('NewCollection');
|
||||
|
||||
html += '<div class="formDialogHeader">';
|
||||
html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
|
||||
html += '<h3 class="formDialogHeaderTitle">';
|
||||
html += title;
|
||||
html += '</h3>';
|
||||
|
||||
html += '</div>';
|
||||
|
||||
html += getEditorHtml();
|
||||
|
||||
dlg.innerHTML = html;
|
||||
|
||||
initEditor(dlg, items);
|
||||
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', () => {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
|
||||
if (layoutManager.tv) {
|
||||
centerFocus(dlg.querySelector('.formDialogContent'), false, true);
|
||||
}
|
||||
|
||||
return Promise.reject();
|
||||
});
|
||||
};
|
||||
return dialogHelper.open(dlg).then(() => {
|
||||
if (layoutManager.tv) {
|
||||
centerFocus(dlg.querySelector('.formDialogContent'), false, false);
|
||||
}
|
||||
|
||||
return CollectionEditor;
|
||||
});
|
||||
if (dlg.submitted) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return Promise.reject();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* eslint-enable indent */
|
||||
export default showEditor;
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize) {
|
||||
'use strict';
|
||||
import browser from 'browser';
|
||||
import dialog from 'dialog';
|
||||
import globalize from 'globalize';
|
||||
|
||||
/* eslint-disable indent */
|
||||
export default (() => {
|
||||
function replaceAll(str, find, replace) {
|
||||
return str.split(find).join(replace);
|
||||
}
|
||||
|
||||
if (browser.tv && window.confirm) {
|
||||
// Use the native confirm dialog
|
||||
return function (options) {
|
||||
return options => {
|
||||
if (typeof options === 'string') {
|
||||
options = {
|
||||
title: '',
|
||||
@@ -15,8 +18,8 @@ define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize)
|
||||
};
|
||||
}
|
||||
|
||||
var text = replaceAll(options.text || '', '<br/>', '\n');
|
||||
var result = confirm(text);
|
||||
const text = replaceAll(options.text || '', '<br/>', '\n');
|
||||
const result = confirm(text);
|
||||
|
||||
if (result) {
|
||||
return Promise.resolve();
|
||||
@@ -26,8 +29,8 @@ define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize)
|
||||
};
|
||||
} else {
|
||||
// Use our own dialog
|
||||
return function (text, title) {
|
||||
var options;
|
||||
return (text, title) => {
|
||||
let options;
|
||||
if (typeof text === 'string') {
|
||||
options = {
|
||||
title: title,
|
||||
@@ -37,7 +40,7 @@ define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize)
|
||||
options = text;
|
||||
}
|
||||
|
||||
var items = [];
|
||||
const items = [];
|
||||
|
||||
items.push({
|
||||
name: options.cancelText || globalize.translate('ButtonCancel'),
|
||||
@@ -53,7 +56,7 @@ define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize)
|
||||
|
||||
options.buttons = items;
|
||||
|
||||
return dialog(options).then(function (result) {
|
||||
return dialog.show(options).then(result => {
|
||||
if (result === 'ok') {
|
||||
return Promise.resolve();
|
||||
}
|
||||
@@ -62,4 +65,5 @@ define(['browser', 'dialog', 'globalize'], function(browser, dialog, globalize)
|
||||
});
|
||||
};
|
||||
}
|
||||
});
|
||||
})();
|
||||
/* eslint-enable indent */
|
||||
|
||||
@@ -1,20 +1,30 @@
|
||||
define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 'require', 'material-icons', 'emby-button', 'paper-icon-button-light', 'emby-input', 'formDialogStyle', 'flexStyles'], function (dialogHelper, dom, layoutManager, scrollHelper, globalize, require) {
|
||||
'use strict';
|
||||
import dialogHelper from 'dialogHelper';
|
||||
import dom from 'dom';
|
||||
import layoutManager from 'layoutManager';
|
||||
import scrollHelper from 'scrollHelper';
|
||||
import globalize from 'globalize';
|
||||
import 'material-icons';
|
||||
import 'emby-button';
|
||||
import 'paper-icon-button-light';
|
||||
import 'emby-input';
|
||||
import 'formDialogStyle';
|
||||
import 'flexStyles';
|
||||
|
||||
/* eslint-disable indent */
|
||||
|
||||
function showDialog(options, template) {
|
||||
|
||||
var dialogOptions = {
|
||||
const dialogOptions = {
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
};
|
||||
|
||||
var enableTvLayout = layoutManager.tv;
|
||||
const enableTvLayout = layoutManager.tv;
|
||||
|
||||
if (enableTvLayout) {
|
||||
dialogOptions.size = 'fullscreen';
|
||||
}
|
||||
|
||||
var dlg = dialogHelper.createDialog(dialogOptions);
|
||||
const dlg = dialogHelper.createDialog(dialogOptions);
|
||||
|
||||
dlg.classList.add('formDialog');
|
||||
|
||||
@@ -22,7 +32,7 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
|
||||
|
||||
dlg.classList.add('align-items-center');
|
||||
dlg.classList.add('justify-content-center');
|
||||
var formDialogContent = dlg.querySelector('.formDialogContent');
|
||||
const formDialogContent = dlg.querySelector('.formDialogContent');
|
||||
formDialogContent.classList.add('no-grow');
|
||||
|
||||
if (enableTvLayout) {
|
||||
@@ -30,41 +40,36 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
|
||||
formDialogContent.style['max-height'] = '60%';
|
||||
scrollHelper.centerFocus.on(formDialogContent, false);
|
||||
} else {
|
||||
formDialogContent.style.maxWidth = (Math.min((options.buttons.length * 150) + 200, dom.getWindowSize().innerWidth - 50)) + 'px';
|
||||
formDialogContent.style.maxWidth = `${Math.min((options.buttons.length * 150) + 200, dom.getWindowSize().innerWidth - 50)}px`;
|
||||
dlg.classList.add('dialog-fullscreen-lowres');
|
||||
}
|
||||
|
||||
//dlg.querySelector('.btnCancel').addEventListener('click', function (e) {
|
||||
// dialogHelper.close(dlg);
|
||||
//});
|
||||
|
||||
if (options.title) {
|
||||
dlg.querySelector('.formDialogHeaderTitle').innerHTML = options.title || '';
|
||||
} else {
|
||||
dlg.querySelector('.formDialogHeaderTitle').classList.add('hide');
|
||||
}
|
||||
|
||||
var displayText = options.html || options.text || '';
|
||||
const displayText = options.html || options.text || '';
|
||||
dlg.querySelector('.text').innerHTML = displayText;
|
||||
|
||||
if (!displayText) {
|
||||
dlg.querySelector('.dialogContentInner').classList.add('hide');
|
||||
}
|
||||
|
||||
var i;
|
||||
var length;
|
||||
var html = '';
|
||||
var hasDescriptions = false;
|
||||
let i;
|
||||
let length;
|
||||
let html = '';
|
||||
let hasDescriptions = false;
|
||||
|
||||
for (i = 0, length = options.buttons.length; i < length; i++) {
|
||||
const item = options.buttons[i];
|
||||
const autoFocus = i === 0 ? ' autofocus' : '';
|
||||
|
||||
var item = options.buttons[i];
|
||||
var autoFocus = i === 0 ? ' autofocus' : '';
|
||||
|
||||
var buttonClass = 'btnOption raised formDialogFooterItem formDialogFooterItem-autosize';
|
||||
let buttonClass = 'btnOption raised formDialogFooterItem formDialogFooterItem-autosize';
|
||||
|
||||
if (item.type) {
|
||||
buttonClass += ' button-' + item.type;
|
||||
buttonClass += ` button-${item.type}`;
|
||||
}
|
||||
|
||||
if (item.description) {
|
||||
@@ -75,10 +80,10 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
|
||||
buttonClass += ' formDialogFooterItem-vertical formDialogFooterItem-nomarginbottom';
|
||||
}
|
||||
|
||||
html += '<button is="emby-button" type="button" class="' + buttonClass + '" data-id="' + item.id + '"' + autoFocus + '>' + item.name + '</button>';
|
||||
html += `<button is="emby-button" type="button" class="${buttonClass}" data-id="${item.id}"${autoFocus}>${item.name}</button>`;
|
||||
|
||||
if (item.description) {
|
||||
html += '<div class="formDialogFooterItem formDialogFooterItem-autosize fieldDescription" style="margin-top:.25em!important;margin-bottom:1.25em!important;">' + item.description + '</div>';
|
||||
html += `<div class="formDialogFooterItem formDialogFooterItem-autosize fieldDescription" style="margin-top:.25em!important;margin-bottom:1.25em!important;">${item.description}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,19 +93,18 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
|
||||
dlg.querySelector('.formDialogFooter').classList.add('formDialogFooter-vertical');
|
||||
}
|
||||
|
||||
var dialogResult;
|
||||
let dialogResult;
|
||||
function onButtonClick() {
|
||||
dialogResult = this.getAttribute('data-id');
|
||||
dialogHelper.close(dlg);
|
||||
}
|
||||
|
||||
var buttons = dlg.querySelectorAll('.btnOption');
|
||||
const buttons = dlg.querySelectorAll('.btnOption');
|
||||
for (i = 0, length = buttons.length; i < length; i++) {
|
||||
buttons[i].addEventListener('click', onButtonClick);
|
||||
}
|
||||
|
||||
return dialogHelper.open(dlg).then(function () {
|
||||
|
||||
return dialogHelper.open(dlg).then(() => {
|
||||
if (enableTvLayout) {
|
||||
scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false);
|
||||
}
|
||||
@@ -113,9 +117,8 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
|
||||
});
|
||||
}
|
||||
|
||||
return function (text, title) {
|
||||
|
||||
var options;
|
||||
export async function show(text, title) {
|
||||
let options;
|
||||
if (typeof text === 'string') {
|
||||
options = {
|
||||
title: title,
|
||||
@@ -125,10 +128,13 @@ define(['dialogHelper', 'dom', 'layoutManager', 'scrollHelper', 'globalize', 're
|
||||
options = text;
|
||||
}
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
require(['text!./dialog.template.html'], function (template) {
|
||||
showDialog(options, template).then(resolve, reject);
|
||||
});
|
||||
const { default: template } = await import('text!./dialog.template.html');
|
||||
return new Promise((resolve, reject) => {
|
||||
showDialog(options, template).then(resolve, reject);
|
||||
});
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/* eslint-enable indent */
|
||||
export default {
|
||||
show: show
|
||||
};
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager', 'dom', 'css!./dialoghelper.css', 'scrollStyles'], function (appRouter, focusManager, browser, layoutManager, inputManager, dom) {
|
||||
'use strict';
|
||||
import appRouter from 'appRouter';
|
||||
import focusManager from 'focusManager';
|
||||
import browser from 'browser';
|
||||
import layoutManager from 'layoutManager';
|
||||
import inputManager from 'inputManager';
|
||||
import dom from 'dom';
|
||||
import 'css!./dialoghelper.css';
|
||||
import 'scrollStyles';
|
||||
|
||||
var globalOnOpenCallback;
|
||||
/* eslint-disable indent */
|
||||
|
||||
let globalOnOpenCallback;
|
||||
|
||||
function enableAnimation() {
|
||||
|
||||
// too slow
|
||||
if (browser.tv) {
|
||||
return false;
|
||||
@@ -14,7 +21,6 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
}
|
||||
|
||||
function removeCenterFocus(dlg) {
|
||||
|
||||
if (layoutManager.tv) {
|
||||
if (dlg.classList.contains('scrollX')) {
|
||||
centerFocus(dlg, true, false);
|
||||
@@ -25,9 +31,8 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
}
|
||||
|
||||
function tryRemoveElement(elem) {
|
||||
var parentNode = elem.parentNode;
|
||||
const parentNode = elem.parentNode;
|
||||
if (parentNode) {
|
||||
|
||||
// Seeing crashes in edge webview
|
||||
try {
|
||||
parentNode.removeChild(elem);
|
||||
@@ -38,15 +43,13 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
}
|
||||
|
||||
function DialogHashHandler(dlg, hash, resolve) {
|
||||
|
||||
var self = this;
|
||||
const self = this;
|
||||
self.originalUrl = window.location.href;
|
||||
var activeElement = document.activeElement;
|
||||
var removeScrollLockOnClose = false;
|
||||
const activeElement = document.activeElement;
|
||||
let removeScrollLockOnClose = false;
|
||||
|
||||
function onHashChange(e) {
|
||||
|
||||
var isBack = self.originalUrl === window.location.href;
|
||||
const isBack = self.originalUrl === window.location.href;
|
||||
|
||||
if (isBack || !isOpened(dlg)) {
|
||||
window.removeEventListener('popstate', onHashChange);
|
||||
@@ -59,7 +62,6 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
}
|
||||
|
||||
function onBackCommand(e) {
|
||||
|
||||
if (e.detail.command === 'back') {
|
||||
self.closedByBack = true;
|
||||
e.preventDefault();
|
||||
@@ -69,7 +71,6 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
}
|
||||
|
||||
function onDialogClosed() {
|
||||
|
||||
if (!isHistoryEnabled(dlg)) {
|
||||
inputManager.off(dlg, onBackCommand);
|
||||
}
|
||||
@@ -84,7 +85,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
}
|
||||
|
||||
if (!self.closedByBack && isHistoryEnabled(dlg)) {
|
||||
var state = history.state || {};
|
||||
const state = history.state || {};
|
||||
if (state.dialogId === hash) {
|
||||
history.back();
|
||||
}
|
||||
@@ -97,7 +98,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
if (dlg.getAttribute('data-removeonclose') !== 'false') {
|
||||
removeCenterFocus(dlg);
|
||||
|
||||
var dialogContainer = dlg.dialogContainer;
|
||||
const dialogContainer = dlg.dialogContainer;
|
||||
if (dialogContainer) {
|
||||
tryRemoveElement(dialogContainer);
|
||||
dlg.dialogContainer = null;
|
||||
@@ -108,7 +109,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
|
||||
//resolve();
|
||||
// if we just called history.back(), then use a timeout to allow the history events to fire first
|
||||
setTimeout(function () {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
element: dlg,
|
||||
closedByBack: self.closedByBack
|
||||
@@ -118,7 +119,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
|
||||
dlg.addEventListener('close', onDialogClosed);
|
||||
|
||||
var center = !dlg.classList.contains('dialog-fixedSize');
|
||||
const center = !dlg.classList.contains('dialog-fixedSize');
|
||||
if (center) {
|
||||
dlg.classList.add('centeredDialog');
|
||||
}
|
||||
@@ -141,7 +142,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
animateDialogOpen(dlg);
|
||||
|
||||
if (isHistoryEnabled(dlg)) {
|
||||
appRouter.pushState({ dialogId: hash }, 'Dialog', '#' + hash);
|
||||
appRouter.pushState({ dialogId: hash }, 'Dialog', `#${hash}`);
|
||||
|
||||
window.addEventListener('popstate', onHashChange);
|
||||
} else {
|
||||
@@ -150,11 +151,10 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
}
|
||||
|
||||
function addBackdropOverlay(dlg) {
|
||||
|
||||
var backdrop = document.createElement('div');
|
||||
const backdrop = document.createElement('div');
|
||||
backdrop.classList.add('dialogBackdrop');
|
||||
|
||||
var backdropParent = dlg.dialogContainer || dlg;
|
||||
const backdropParent = dlg.dialogContainer || dlg;
|
||||
backdropParent.parentNode.insertBefore(backdrop, backdropParent);
|
||||
dlg.backdrop = backdrop;
|
||||
|
||||
@@ -162,7 +162,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
void backdrop.offsetWidth;
|
||||
backdrop.classList.add('dialogBackdropOpened');
|
||||
|
||||
dom.addEventListener((dlg.dialogContainer || backdrop), 'click', function (e) {
|
||||
dom.addEventListener((dlg.dialogContainer || backdrop), 'click', e => {
|
||||
if (e.target === dlg.dialogContainer) {
|
||||
close(dlg);
|
||||
}
|
||||
@@ -170,7 +170,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
passive: true
|
||||
});
|
||||
|
||||
dom.addEventListener((dlg.dialogContainer || backdrop), 'contextmenu', function (e) {
|
||||
dom.addEventListener((dlg.dialogContainer || backdrop), 'contextmenu', e => {
|
||||
if (e.target === dlg.dialogContainer) {
|
||||
// Close the application dialog menu
|
||||
close(dlg);
|
||||
@@ -184,37 +184,33 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
return dlg.getAttribute('data-history') === 'true';
|
||||
}
|
||||
|
||||
function open(dlg) {
|
||||
|
||||
export function open(dlg) {
|
||||
if (globalOnOpenCallback) {
|
||||
globalOnOpenCallback(dlg);
|
||||
}
|
||||
|
||||
var parent = dlg.parentNode;
|
||||
const parent = dlg.parentNode;
|
||||
if (parent) {
|
||||
parent.removeChild(dlg);
|
||||
}
|
||||
|
||||
var dialogContainer = document.createElement('div');
|
||||
const dialogContainer = document.createElement('div');
|
||||
dialogContainer.classList.add('dialogContainer');
|
||||
dialogContainer.appendChild(dlg);
|
||||
dlg.dialogContainer = dialogContainer;
|
||||
document.body.appendChild(dialogContainer);
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
new DialogHashHandler(dlg, 'dlg' + new Date().getTime(), resolve);
|
||||
return new Promise((resolve, reject) => {
|
||||
new DialogHashHandler(dlg, `dlg${new Date().getTime()}`, resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function isOpened(dlg) {
|
||||
|
||||
//return dlg.opened;
|
||||
return !dlg.classList.contains('hide');
|
||||
}
|
||||
|
||||
function close(dlg) {
|
||||
|
||||
export function close(dlg) {
|
||||
if (isOpened(dlg)) {
|
||||
if (isHistoryEnabled(dlg)) {
|
||||
history.back();
|
||||
@@ -225,15 +221,13 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
}
|
||||
|
||||
function closeDialog(dlg) {
|
||||
|
||||
if (!dlg.classList.contains('hide')) {
|
||||
|
||||
dlg.dispatchEvent(new CustomEvent('closing', {
|
||||
bubbles: false,
|
||||
cancelable: false
|
||||
}));
|
||||
|
||||
var onAnimationFinish = function () {
|
||||
const onAnimationFinish = () => {
|
||||
focusManager.popScope(dlg);
|
||||
|
||||
dlg.classList.add('hide');
|
||||
@@ -248,8 +242,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
}
|
||||
|
||||
function animateDialogOpen(dlg) {
|
||||
|
||||
var onAnimationFinish = function () {
|
||||
const onAnimationFinish = () => {
|
||||
focusManager.pushScope(dlg);
|
||||
|
||||
if (dlg.getAttribute('data-autofocus') === 'true') {
|
||||
@@ -263,8 +256,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
};
|
||||
|
||||
if (enableAnimation()) {
|
||||
|
||||
var onFinish = function () {
|
||||
const onFinish = () => {
|
||||
dom.removeEventListener(dlg, dom.whichAnimationEvent(), onFinish, {
|
||||
once: true
|
||||
});
|
||||
@@ -280,27 +272,24 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
}
|
||||
|
||||
function animateDialogClose(dlg, onAnimationFinish) {
|
||||
|
||||
if (enableAnimation()) {
|
||||
|
||||
var animated = true;
|
||||
let animated = true;
|
||||
|
||||
switch (dlg.animationConfig.exit.name) {
|
||||
|
||||
case 'fadeout':
|
||||
dlg.style.animation = 'fadeout ' + dlg.animationConfig.exit.timing.duration + 'ms ease-out normal both';
|
||||
dlg.style.animation = `fadeout ${dlg.animationConfig.exit.timing.duration}ms ease-out normal both`;
|
||||
break;
|
||||
case 'scaledown':
|
||||
dlg.style.animation = 'scaledown ' + dlg.animationConfig.exit.timing.duration + 'ms ease-out normal both';
|
||||
dlg.style.animation = `scaledown ${dlg.animationConfig.exit.timing.duration}ms ease-out normal both`;
|
||||
break;
|
||||
case 'slidedown':
|
||||
dlg.style.animation = 'slidedown ' + dlg.animationConfig.exit.timing.duration + 'ms ease-out normal both';
|
||||
dlg.style.animation = `slidedown ${dlg.animationConfig.exit.timing.duration}ms ease-out normal both`;
|
||||
break;
|
||||
default:
|
||||
animated = false;
|
||||
break;
|
||||
}
|
||||
var onFinish = function () {
|
||||
const onFinish = () => {
|
||||
dom.removeEventListener(dlg, dom.whichAnimationEvent(), onFinish, {
|
||||
once: true
|
||||
});
|
||||
@@ -318,10 +307,9 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
onAnimationFinish();
|
||||
}
|
||||
|
||||
var supportsOverscrollBehavior = 'overscroll-behavior-y' in document.body.style;
|
||||
const supportsOverscrollBehavior = 'overscroll-behavior-y' in document.body.style;
|
||||
|
||||
function shouldLockDocumentScroll(options) {
|
||||
|
||||
if (supportsOverscrollBehavior && (options.size || !browser.touch)) {
|
||||
return false;
|
||||
}
|
||||
@@ -342,8 +330,7 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
}
|
||||
|
||||
function removeBackdrop(dlg) {
|
||||
|
||||
var backdrop = dlg.backdrop;
|
||||
const backdrop = dlg.backdrop;
|
||||
|
||||
if (!backdrop) {
|
||||
return;
|
||||
@@ -351,12 +338,11 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
|
||||
dlg.backdrop = null;
|
||||
|
||||
var onAnimationFinish = function () {
|
||||
const onAnimationFinish = () => {
|
||||
tryRemoveElement(backdrop);
|
||||
};
|
||||
|
||||
if (enableAnimation()) {
|
||||
|
||||
backdrop.classList.remove('dialogBackdropOpened');
|
||||
|
||||
// this is not firing animatonend
|
||||
@@ -368,20 +354,19 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
}
|
||||
|
||||
function centerFocus(elem, horiz, on) {
|
||||
require(['scrollHelper'], function (scrollHelper) {
|
||||
var fn = on ? 'on' : 'off';
|
||||
import('scrollHelper').then(scrollHelper => {
|
||||
const fn = on ? 'on' : 'off';
|
||||
scrollHelper.centerFocus[fn](elem, horiz);
|
||||
});
|
||||
}
|
||||
|
||||
function createDialog(options) {
|
||||
|
||||
export function createDialog(options) {
|
||||
options = options || {};
|
||||
|
||||
// If there's no native dialog support, use a plain div
|
||||
// Also not working well in samsung tizen browser, content inside not clickable
|
||||
// Just go ahead and always use a plain div because we're seeing issues overlaying absoltutely positioned content over a modal dialog
|
||||
var dlg = document.createElement('div');
|
||||
const dlg = document.createElement('div');
|
||||
|
||||
dlg.classList.add('focuscontainer');
|
||||
dlg.classList.add('hide');
|
||||
@@ -406,17 +391,17 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
dlg.setAttribute('data-autofocus', 'true');
|
||||
}
|
||||
|
||||
var defaultEntryAnimation;
|
||||
var defaultExitAnimation;
|
||||
let defaultEntryAnimation;
|
||||
let defaultExitAnimation;
|
||||
|
||||
defaultEntryAnimation = 'scaleup';
|
||||
defaultExitAnimation = 'scaledown';
|
||||
var entryAnimation = options.entryAnimation || defaultEntryAnimation;
|
||||
var exitAnimation = options.exitAnimation || defaultExitAnimation;
|
||||
const entryAnimation = options.entryAnimation || defaultEntryAnimation;
|
||||
const exitAnimation = options.exitAnimation || defaultExitAnimation;
|
||||
|
||||
// If it's not fullscreen then lower the default animation speed to make it open really fast
|
||||
var entryAnimationDuration = options.entryAnimationDuration || (options.size !== 'fullscreen' ? 180 : 280);
|
||||
var exitAnimationDuration = options.exitAnimationDuration || (options.size !== 'fullscreen' ? 120 : 220);
|
||||
const entryAnimationDuration = options.entryAnimationDuration || (options.size !== 'fullscreen' ? 180 : 280);
|
||||
const exitAnimationDuration = options.exitAnimationDuration || (options.size !== 'fullscreen' ? 120 : 220);
|
||||
|
||||
dlg.animationConfig = {
|
||||
// scale up
|
||||
@@ -461,24 +446,22 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
|
||||
if (options.size) {
|
||||
dlg.classList.add('dialog-fixedSize');
|
||||
dlg.classList.add('dialog-' + options.size);
|
||||
dlg.classList.add(`dialog-${options.size}`);
|
||||
}
|
||||
|
||||
if (enableAnimation()) {
|
||||
|
||||
switch (dlg.animationConfig.entry.name) {
|
||||
|
||||
case 'fadein':
|
||||
dlg.style.animation = 'fadein ' + entryAnimationDuration + 'ms ease-out normal';
|
||||
dlg.style.animation = `fadein ${entryAnimationDuration}ms ease-out normal`;
|
||||
break;
|
||||
case 'scaleup':
|
||||
dlg.style.animation = 'scaleup ' + entryAnimationDuration + 'ms ease-out normal both';
|
||||
dlg.style.animation = `scaleup ${entryAnimationDuration}ms ease-out normal both`;
|
||||
break;
|
||||
case 'slideup':
|
||||
dlg.style.animation = 'slideup ' + entryAnimationDuration + 'ms ease-out normal';
|
||||
dlg.style.animation = `slideup ${entryAnimationDuration}ms ease-out normal`;
|
||||
break;
|
||||
case 'slidedown':
|
||||
dlg.style.animation = 'slidedown ' + entryAnimationDuration + 'ms ease-out normal';
|
||||
dlg.style.animation = `slidedown ${entryAnimationDuration}ms ease-out normal`;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -488,12 +471,15 @@ define(['appRouter', 'focusManager', 'browser', 'layoutManager', 'inputManager',
|
||||
return dlg;
|
||||
}
|
||||
|
||||
return {
|
||||
open: open,
|
||||
close: close,
|
||||
createDialog: createDialog,
|
||||
setOnOpen: function (val) {
|
||||
globalOnOpenCallback = val;
|
||||
}
|
||||
};
|
||||
});
|
||||
export function setOnOpen(val) {
|
||||
globalOnOpenCallback = val;
|
||||
}
|
||||
|
||||
/* eslint-enable indent */
|
||||
|
||||
export default {
|
||||
open: open,
|
||||
close: close,
|
||||
createDialog: createDialog,
|
||||
setOnOpen: setOnOpen
|
||||
};
|
||||
|
||||
@@ -1,9 +1,19 @@
|
||||
define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-input', 'paper-icon-button-light', 'css!./directorybrowser', 'formDialogStyle', 'emby-button'], function(loading, dialogHelper, dom, globalize) {
|
||||
'use strict';
|
||||
import loading from 'loading';
|
||||
import dialogHelper from 'dialogHelper';
|
||||
import dom from 'dom';
|
||||
import globalize from 'globalize';
|
||||
import 'listViewStyle';
|
||||
import 'emby-input';
|
||||
import 'paper-icon-button-light';
|
||||
import 'css!./directorybrowser';
|
||||
import 'formDialogStyle';
|
||||
import 'emby-button';
|
||||
|
||||
/* eslint-disable indent */
|
||||
|
||||
function getSystemInfo() {
|
||||
return systemInfo ? Promise.resolve(systemInfo) : ApiClient.getPublicSystemInfo().then(
|
||||
function(info) {
|
||||
info => {
|
||||
systemInfo = info;
|
||||
return info;
|
||||
}
|
||||
@@ -21,9 +31,9 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
|
||||
|
||||
loading.show();
|
||||
|
||||
var promises = [];
|
||||
const promises = [];
|
||||
|
||||
if ('Network' === path) {
|
||||
if (path === 'Network') {
|
||||
promises.push(ApiClient.getNetworkDevices());
|
||||
} else {
|
||||
if (path) {
|
||||
@@ -35,10 +45,10 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
|
||||
}
|
||||
|
||||
Promise.all(promises).then(
|
||||
function(responses) {
|
||||
var folders = responses[0];
|
||||
var parentPath = responses[1] || '';
|
||||
var html = '';
|
||||
responses => {
|
||||
const folders = responses[0];
|
||||
const parentPath = responses[1] || '';
|
||||
let html = '';
|
||||
|
||||
page.querySelector('.results').scrollTop = 0;
|
||||
page.querySelector('#txtDirectoryPickerPath').value = path || '';
|
||||
@@ -46,9 +56,9 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
|
||||
if (path) {
|
||||
html += getItem('lnkPath lnkDirectory', '', parentPath, '...');
|
||||
}
|
||||
for (var i = 0, length = folders.length; i < length; i++) {
|
||||
var folder = folders[i];
|
||||
var cssClass = 'File' === folder.Type ? 'lnkPath lnkFile' : 'lnkPath lnkDirectory';
|
||||
for (let i = 0, length = folders.length; i < length; i++) {
|
||||
const folder = folders[i];
|
||||
const cssClass = folder.Type === 'File' ? 'lnkPath lnkFile' : 'lnkPath lnkDirectory';
|
||||
html += getItem(cssClass, folder.Type, folder.Path, folder.Name);
|
||||
}
|
||||
|
||||
@@ -58,7 +68,7 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
|
||||
|
||||
page.querySelector('.results').innerHTML = html;
|
||||
loading.hide();
|
||||
}, function() {
|
||||
}, () => {
|
||||
if (updatePathOnError) {
|
||||
page.querySelector('#txtDirectoryPickerPath').value = '';
|
||||
page.querySelector('.results').innerHTML = '';
|
||||
@@ -69,8 +79,8 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
|
||||
}
|
||||
|
||||
function getItem(cssClass, type, path, name) {
|
||||
var html = '';
|
||||
html += '<div class="listItem listItem-border ' + cssClass + '" data-type="' + type + '" data-path="' + path + '">';
|
||||
let html = '';
|
||||
html += `<div class="listItem listItem-border ${cssClass}" data-type="${type}" data-path="${path}">`;
|
||||
html += '<div class="listItemBody" style="padding-left:0;padding-top:.5em;padding-bottom:.5em;">';
|
||||
html += '<div class="listItemBodyText">';
|
||||
html += name;
|
||||
@@ -82,19 +92,19 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
|
||||
}
|
||||
|
||||
function getEditorHtml(options, systemInfo) {
|
||||
var html = '';
|
||||
let html = '';
|
||||
html += '<div class="formDialogContent scrollY">';
|
||||
html += '<div class="dialogContentInner dialog-content-centered" style="padding-top:2em;">';
|
||||
if (!options.pathReadOnly) {
|
||||
var instruction = options.instruction ? options.instruction + '<br/><br/>' : '';
|
||||
const instruction = options.instruction ? `${options.instruction}<br/><br/>` : '';
|
||||
html += '<div class="infoBanner" style="margin-bottom:1.5em;">';
|
||||
html += instruction;
|
||||
if ('bsd' === systemInfo.OperatingSystem.toLowerCase()) {
|
||||
if (systemInfo.OperatingSystem.toLowerCase() === 'bsd') {
|
||||
html += '<br/>';
|
||||
html += '<br/>';
|
||||
html += globalize.translate('MessageDirectoryPickerBSDInstruction');
|
||||
html += '<br/>';
|
||||
} else if ('linux' === systemInfo.OperatingSystem.toLowerCase()) {
|
||||
} else if (systemInfo.OperatingSystem.toLowerCase() === 'linux') {
|
||||
html += '<br/>';
|
||||
html += '<br/>';
|
||||
html += globalize.translate('MessageDirectoryPickerLinuxInstruction');
|
||||
@@ -105,17 +115,17 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
|
||||
html += '<form style="margin:auto;">';
|
||||
html += '<div class="inputContainer" style="display: flex; align-items: center;">';
|
||||
html += '<div style="flex-grow:1;">';
|
||||
var labelKey;
|
||||
let labelKey;
|
||||
if (options.includeFiles !== true) {
|
||||
labelKey = 'LabelFolder';
|
||||
} else {
|
||||
labelKey = 'LabelPath';
|
||||
}
|
||||
var readOnlyAttribute = options.pathReadOnly ? ' readonly' : '';
|
||||
html += '<input is="emby-input" id="txtDirectoryPickerPath" type="text" required="required" ' + readOnlyAttribute + ' label="' + globalize.translate(labelKey) + '"/>';
|
||||
const readOnlyAttribute = options.pathReadOnly ? ' readonly' : '';
|
||||
html += `<input is="emby-input" id="txtDirectoryPickerPath" type="text" required="required" ${readOnlyAttribute} label="${globalize.translate(labelKey)}"/>`;
|
||||
html += '</div>';
|
||||
if (!readOnlyAttribute) {
|
||||
html += '<button type="button" is="paper-icon-button-light" class="btnRefreshDirectories emby-input-iconbutton" title="' + globalize.translate('ButtonRefresh') + '"><span class="material-icons search"></span></button>';
|
||||
html += `<button type="button" is="paper-icon-button-light" class="btnRefreshDirectories emby-input-iconbutton" title="${globalize.translate('ButtonRefresh')}"><span class="material-icons search"></span></button>`;
|
||||
}
|
||||
html += '</div>';
|
||||
if (!readOnlyAttribute) {
|
||||
@@ -123,14 +133,14 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
|
||||
}
|
||||
if (options.enableNetworkSharePath) {
|
||||
html += '<div class="inputContainer" style="margin-top:2em;">';
|
||||
html += '<input is="emby-input" id="txtNetworkPath" type="text" label="' + globalize.translate('LabelOptionalNetworkPath') + '"/>';
|
||||
html += `<input is="emby-input" id="txtNetworkPath" type="text" label="${globalize.translate('LabelOptionalNetworkPath')}"/>`;
|
||||
html += '<div class="fieldDescription">';
|
||||
html += globalize.translate('LabelOptionalNetworkPathHelp', '<b>\\\\server</b>', '<b>\\\\192.168.1.101</b>');
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
}
|
||||
html += '<div class="formDialogFooter">';
|
||||
html += '<button is="emby-button" type="submit" class="raised button-submit block formDialogFooterItem">' + globalize.translate('ButtonOk') + '</button>';
|
||||
html += `<button is="emby-button" type="submit" class="raised button-submit block formDialogFooterItem">${globalize.translate('ButtonOk')}</button>`;
|
||||
html += '</div>';
|
||||
html += '</form>';
|
||||
html += '</div>';
|
||||
@@ -147,7 +157,7 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
|
||||
}
|
||||
|
||||
function alertTextWithOptions(options) {
|
||||
require(['alert'], function(alert) {
|
||||
import('alert').then(({default: alert}) => {
|
||||
alert(options);
|
||||
});
|
||||
}
|
||||
@@ -160,7 +170,7 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
|
||||
ValidateWriteable: validateWriteable,
|
||||
Path: path
|
||||
}
|
||||
}).catch(function(response) {
|
||||
}).catch(response => {
|
||||
if (response) {
|
||||
if (response.status === 404) {
|
||||
alertText(globalize.translate('PathNotFound'));
|
||||
@@ -180,10 +190,10 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
|
||||
}
|
||||
|
||||
function initEditor(content, options, fileOptions) {
|
||||
content.addEventListener('click', function(e) {
|
||||
var lnkPath = dom.parentWithClass(e.target, 'lnkPath');
|
||||
content.addEventListener('click', e => {
|
||||
const lnkPath = dom.parentWithClass(e.target, 'lnkPath');
|
||||
if (lnkPath) {
|
||||
var path = lnkPath.getAttribute('data-path');
|
||||
const path = lnkPath.getAttribute('data-path');
|
||||
if (lnkPath.classList.contains('lnkFile')) {
|
||||
content.querySelector('#txtDirectoryPickerPath').value = path;
|
||||
} else {
|
||||
@@ -192,25 +202,25 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
|
||||
}
|
||||
});
|
||||
|
||||
content.addEventListener('click', function(e) {
|
||||
content.addEventListener('click', e => {
|
||||
if (dom.parentWithClass(e.target, 'btnRefreshDirectories')) {
|
||||
var path = content.querySelector('#txtDirectoryPickerPath').value;
|
||||
const path = content.querySelector('#txtDirectoryPickerPath').value;
|
||||
refreshDirectoryBrowser(content, path, fileOptions);
|
||||
}
|
||||
});
|
||||
|
||||
content.addEventListener('change', function(e) {
|
||||
var txtDirectoryPickerPath = dom.parentWithTag(e.target, 'INPUT');
|
||||
if (txtDirectoryPickerPath && 'txtDirectoryPickerPath' === txtDirectoryPickerPath.id) {
|
||||
content.addEventListener('change', e => {
|
||||
const txtDirectoryPickerPath = dom.parentWithTag(e.target, 'INPUT');
|
||||
if (txtDirectoryPickerPath && txtDirectoryPickerPath.id === 'txtDirectoryPickerPath') {
|
||||
refreshDirectoryBrowser(content, txtDirectoryPickerPath.value, fileOptions);
|
||||
}
|
||||
});
|
||||
|
||||
content.querySelector('form').addEventListener('submit', function(e) {
|
||||
if (options.callback) {
|
||||
var networkSharePath = this.querySelector('#txtNetworkPath');
|
||||
let networkSharePath = this.querySelector('#txtNetworkPath');
|
||||
networkSharePath = networkSharePath ? networkSharePath.value : null;
|
||||
var path = this.querySelector('#txtDirectoryPickerPath').value;
|
||||
const path = this.querySelector('#txtDirectoryPickerPath').value;
|
||||
validatePath(path, options.validateWriteable, ApiClient).then(options.callback(path, networkSharePath));
|
||||
}
|
||||
e.preventDefault();
|
||||
@@ -224,77 +234,79 @@ define(['loading', 'dialogHelper', 'dom', 'globalize', 'listViewStyle', 'emby-in
|
||||
return Promise.resolve(options.path);
|
||||
} else {
|
||||
return ApiClient.getJSON(ApiClient.getUrl('Environment/DefaultDirectoryBrowser')).then(
|
||||
function(result) {
|
||||
result => {
|
||||
return result.Path || '';
|
||||
}, function() {
|
||||
}, () => {
|
||||
return '';
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function directoryBrowser() {
|
||||
var currentDialog;
|
||||
var self = this;
|
||||
self.show = function(options) {
|
||||
options = options || {};
|
||||
var fileOptions = {
|
||||
includeDirectories: true
|
||||
};
|
||||
if (options.includeDirectories != null) {
|
||||
fileOptions.includeDirectories = options.includeDirectories;
|
||||
}
|
||||
if (options.includeFiles != null) {
|
||||
fileOptions.includeFiles = options.includeFiles;
|
||||
}
|
||||
Promise.all([getSystemInfo(), getDefaultPath(options)]).then(
|
||||
function(responses) {
|
||||
var systemInfo = responses[0];
|
||||
var initialPath = responses[1];
|
||||
var dlg = dialogHelper.createDialog({
|
||||
size: 'small',
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
});
|
||||
dlg.classList.add('ui-body-a');
|
||||
dlg.classList.add('background-theme-a');
|
||||
dlg.classList.add('directoryPicker');
|
||||
dlg.classList.add('formDialog');
|
||||
|
||||
var html = '';
|
||||
html += '<div class="formDialogHeader">';
|
||||
html += '<button is="paper-icon-button-light" class="btnCloseDialog autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
|
||||
html += '<h3 class="formDialogHeaderTitle">';
|
||||
html += options.header || globalize.translate('HeaderSelectPath');
|
||||
html += '</h3>';
|
||||
html += '</div>';
|
||||
html += getEditorHtml(options, systemInfo);
|
||||
dlg.innerHTML = html;
|
||||
initEditor(dlg, options, fileOptions);
|
||||
dlg.addEventListener('close', onDialogClosed);
|
||||
dialogHelper.open(dlg);
|
||||
dlg.querySelector('.btnCloseDialog').addEventListener('click', function() {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
currentDialog = dlg;
|
||||
dlg.querySelector('#txtDirectoryPickerPath').value = initialPath;
|
||||
var txtNetworkPath = dlg.querySelector('#txtNetworkPath');
|
||||
if (txtNetworkPath) {
|
||||
txtNetworkPath.value = options.networkSharePath || '';
|
||||
}
|
||||
if (!options.pathReadOnly) {
|
||||
refreshDirectoryBrowser(dlg, initialPath, fileOptions, true);
|
||||
}
|
||||
class directoryBrowser {
|
||||
constructor() {
|
||||
let currentDialog;
|
||||
this.show = options => {
|
||||
options = options || {};
|
||||
const fileOptions = {
|
||||
includeDirectories: true
|
||||
};
|
||||
if (options.includeDirectories != null) {
|
||||
fileOptions.includeDirectories = options.includeDirectories;
|
||||
}
|
||||
);
|
||||
};
|
||||
self.close = function() {
|
||||
if (currentDialog) {
|
||||
dialogHelper.close(currentDialog);
|
||||
}
|
||||
};
|
||||
if (options.includeFiles != null) {
|
||||
fileOptions.includeFiles = options.includeFiles;
|
||||
}
|
||||
Promise.all([getSystemInfo(), getDefaultPath(options)]).then(
|
||||
responses => {
|
||||
const systemInfo = responses[0];
|
||||
const initialPath = responses[1];
|
||||
const dlg = dialogHelper.createDialog({
|
||||
size: 'small',
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
});
|
||||
dlg.classList.add('ui-body-a');
|
||||
dlg.classList.add('background-theme-a');
|
||||
dlg.classList.add('directoryPicker');
|
||||
dlg.classList.add('formDialog');
|
||||
|
||||
let html = '';
|
||||
html += '<div class="formDialogHeader">';
|
||||
html += '<button is="paper-icon-button-light" class="btnCloseDialog autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
|
||||
html += '<h3 class="formDialogHeaderTitle">';
|
||||
html += options.header || globalize.translate('HeaderSelectPath');
|
||||
html += '</h3>';
|
||||
html += '</div>';
|
||||
html += getEditorHtml(options, systemInfo);
|
||||
dlg.innerHTML = html;
|
||||
initEditor(dlg, options, fileOptions);
|
||||
dlg.addEventListener('close', onDialogClosed);
|
||||
dialogHelper.open(dlg);
|
||||
dlg.querySelector('.btnCloseDialog').addEventListener('click', () => {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
currentDialog = dlg;
|
||||
dlg.querySelector('#txtDirectoryPickerPath').value = initialPath;
|
||||
const txtNetworkPath = dlg.querySelector('#txtNetworkPath');
|
||||
if (txtNetworkPath) {
|
||||
txtNetworkPath.value = options.networkSharePath || '';
|
||||
}
|
||||
if (!options.pathReadOnly) {
|
||||
refreshDirectoryBrowser(dlg, initialPath, fileOptions, true);
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
this.close = () => {
|
||||
if (currentDialog) {
|
||||
dialogHelper.close(currentDialog);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
var systemInfo;
|
||||
return directoryBrowser;
|
||||
});
|
||||
let systemInfo;
|
||||
|
||||
/* eslint-enable indent */
|
||||
export default directoryBrowser;
|
||||
|
||||
@@ -1,22 +1,37 @@
|
||||
define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', 'apphost', 'focusManager', 'datetime', 'globalize', 'loading', 'connectionManager', 'skinManager', 'dom', 'events', 'emby-select', 'emby-checkbox', 'emby-button'], function (require, browser, layoutManager, appSettings, pluginManager, appHost, focusManager, datetime, globalize, loading, connectionManager, skinManager, dom, events) {
|
||||
'use strict';
|
||||
import browser from 'browser';
|
||||
import layoutManager from 'layoutManager';
|
||||
import appSettings from 'appSettings';
|
||||
import pluginManager from 'pluginManager';
|
||||
import appHost from 'apphost';
|
||||
import focusManager from 'focusManager';
|
||||
import datetime from 'datetime';
|
||||
import globalize from 'globalize';
|
||||
import loading from 'loading';
|
||||
import connectionManager from 'connectionManager';
|
||||
import skinManager from 'skinManager';
|
||||
import events from 'events';
|
||||
import 'emby-select';
|
||||
import 'emby-checkbox';
|
||||
import 'emby-button';
|
||||
|
||||
/* eslint-disable indent */
|
||||
|
||||
function fillThemes(select, isDashboard) {
|
||||
select.innerHTML = skinManager.getThemes().map(function (t) {
|
||||
var value = t.id;
|
||||
select.innerHTML = skinManager.getThemes().map(t => {
|
||||
let value = t.id;
|
||||
if (t.isDefault && !isDashboard) {
|
||||
value = '';
|
||||
} else if (t.isDefaultServerDashboard && isDashboard) {
|
||||
value = '';
|
||||
}
|
||||
|
||||
return '<option value="' + value + '">' + t.name + '</option>';
|
||||
return `<option value="${value}">${t.name}</option>`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function loadScreensavers(context, userSettings) {
|
||||
var selectScreensaver = context.querySelector('.selectScreensaver');
|
||||
var options = pluginManager.ofType('screensaver').map(function (plugin) {
|
||||
const selectScreensaver = context.querySelector('.selectScreensaver');
|
||||
const options = pluginManager.ofType('screensaver').map(plugin => {
|
||||
return {
|
||||
name: plugin.name,
|
||||
value: plugin.id
|
||||
@@ -28,8 +43,8 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
|
||||
value: 'none'
|
||||
});
|
||||
|
||||
selectScreensaver.innerHTML = options.map(function (o) {
|
||||
return '<option value="' + o.value + '">' + o.name + '</option>';
|
||||
selectScreensaver.innerHTML = options.map(o => {
|
||||
return `<option value="${o.value}">${o.name}</option>`;
|
||||
}).join('');
|
||||
selectScreensaver.value = userSettings.screensaver();
|
||||
|
||||
@@ -40,9 +55,8 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
|
||||
}
|
||||
|
||||
function loadSoundEffects(context, userSettings) {
|
||||
|
||||
var selectSoundEffects = context.querySelector('.selectSoundEffects');
|
||||
var options = pluginManager.ofType('soundeffects').map(function (plugin) {
|
||||
const selectSoundEffects = context.querySelector('.selectSoundEffects');
|
||||
const options = pluginManager.ofType('soundeffects').map(plugin => {
|
||||
return {
|
||||
name: plugin.name,
|
||||
value: plugin.id
|
||||
@@ -54,8 +68,8 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
|
||||
value: 'none'
|
||||
});
|
||||
|
||||
selectSoundEffects.innerHTML = options.map(function (o) {
|
||||
return '<option value="' + o.value + '">' + o.name + '</option>';
|
||||
selectSoundEffects.innerHTML = options.map(o => {
|
||||
return `<option value="${o.value}">${o.name}</option>`;
|
||||
}).join('');
|
||||
selectSoundEffects.value = userSettings.soundEffects();
|
||||
|
||||
@@ -66,18 +80,17 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
|
||||
}
|
||||
|
||||
function loadSkins(context, userSettings) {
|
||||
const selectSkin = context.querySelector('.selectSkin');
|
||||
|
||||
var selectSkin = context.querySelector('.selectSkin');
|
||||
|
||||
var options = pluginManager.ofType('skin').map(function (plugin) {
|
||||
const options = pluginManager.ofType('skin').map(plugin => {
|
||||
return {
|
||||
name: plugin.name,
|
||||
value: plugin.id
|
||||
};
|
||||
});
|
||||
|
||||
selectSkin.innerHTML = options.map(function (o) {
|
||||
return '<option value="' + o.value + '">' + o.name + '</option>';
|
||||
selectSkin.innerHTML = options.map(o => {
|
||||
return `<option value="${o.value}">${o.name}</option>`;
|
||||
}).join('');
|
||||
selectSkin.value = userSettings.skin();
|
||||
|
||||
@@ -92,8 +105,7 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
|
||||
}
|
||||
}
|
||||
|
||||
function showOrHideMissingEpisodesField(context, user, apiClient) {
|
||||
|
||||
function showOrHideMissingEpisodesField(context) {
|
||||
if (browser.tizen || browser.web0s) {
|
||||
context.querySelector('.fldDisplayMissingEpisodes').classList.add('hide');
|
||||
return;
|
||||
@@ -102,11 +114,7 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
|
||||
context.querySelector('.fldDisplayMissingEpisodes').classList.remove('hide');
|
||||
}
|
||||
|
||||
function loadForm(context, user, userSettings, apiClient) {
|
||||
|
||||
var loggedInUserId = apiClient.getCurrentUserId();
|
||||
var userId = user.Id;
|
||||
|
||||
function loadForm(context, user, userSettings) {
|
||||
if (user.Policy.IsAdministrator) {
|
||||
context.querySelector('.selectDashboardThemeContainer').classList.remove('hide');
|
||||
} else {
|
||||
@@ -167,8 +175,8 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
|
||||
|
||||
context.querySelector('.chkRunAtStartup').checked = appSettings.runAtStartup();
|
||||
|
||||
var selectTheme = context.querySelector('#selectTheme');
|
||||
var selectDashboardTheme = context.querySelector('#selectDashboardTheme');
|
||||
const selectTheme = context.querySelector('#selectTheme');
|
||||
const selectDashboardTheme = context.querySelector('#selectDashboardTheme');
|
||||
|
||||
fillThemes(selectTheme);
|
||||
fillThemes(selectDashboardTheme, true);
|
||||
@@ -195,13 +203,12 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
|
||||
|
||||
context.querySelector('.selectLayout').value = layoutManager.getSavedLayout() || '';
|
||||
|
||||
showOrHideMissingEpisodesField(context, user, apiClient);
|
||||
showOrHideMissingEpisodesField(context);
|
||||
|
||||
loading.hide();
|
||||
}
|
||||
|
||||
function saveUser(context, user, userSettingsInstance, apiClient) {
|
||||
|
||||
appSettings.runAtStartup(context.querySelector('.chkRunAtStartup').checked);
|
||||
|
||||
user.Configuration.DisplayMissingEpisodes = context.querySelector('.chkDisplayMissingEpisodes').checked;
|
||||
@@ -239,29 +246,29 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
|
||||
function save(instance, context, userId, userSettings, apiClient, enableSaveConfirmation) {
|
||||
loading.show();
|
||||
|
||||
apiClient.getUser(userId).then(function (user) {
|
||||
saveUser(context, user, userSettings, apiClient).then(function () {
|
||||
apiClient.getUser(userId).then(user => {
|
||||
saveUser(context, user, userSettings, apiClient).then(() => {
|
||||
loading.hide();
|
||||
if (enableSaveConfirmation) {
|
||||
require(['toast'], function (toast) {
|
||||
import('toast').then(({default: toast}) => {
|
||||
toast(globalize.translate('SettingsSaved'));
|
||||
});
|
||||
}
|
||||
events.trigger(instance, 'saved');
|
||||
}, function () {
|
||||
}, () => {
|
||||
loading.hide();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function onSubmit(e) {
|
||||
var self = this;
|
||||
var apiClient = connectionManager.getApiClient(self.options.serverId);
|
||||
var userId = self.options.userId;
|
||||
var userSettings = self.options.userSettings;
|
||||
const self = this;
|
||||
const apiClient = connectionManager.getApiClient(self.options.serverId);
|
||||
const userId = self.options.userId;
|
||||
const userSettings = self.options.userSettings;
|
||||
|
||||
userSettings.setUserInfo(userId, apiClient).then(function () {
|
||||
var enableSaveConfirmation = self.options.enableSaveConfirmation;
|
||||
userSettings.setUserInfo(userId, apiClient).then(() => {
|
||||
const enableSaveConfirmation = self.options.enableSaveConfirmation;
|
||||
save(self, self.options.element, userId, userSettings, apiClient, enableSaveConfirmation);
|
||||
});
|
||||
|
||||
@@ -272,50 +279,51 @@ define(['require', 'browser', 'layoutManager', 'appSettings', 'pluginManager', '
|
||||
return false;
|
||||
}
|
||||
|
||||
function embed(options, self) {
|
||||
require(['text!./displaySettings.template.html'], function (template) {
|
||||
options.element.innerHTML = globalize.translateDocument(template, 'core');
|
||||
options.element.querySelector('form').addEventListener('submit', onSubmit.bind(self));
|
||||
if (options.enableSaveButton) {
|
||||
options.element.querySelector('.btnSave').classList.remove('hide');
|
||||
}
|
||||
self.loadData(options.autoFocus);
|
||||
});
|
||||
async function embed(options, self) {
|
||||
const { default: template } = await import('text!./displaySettings.template.html');
|
||||
options.element.innerHTML = globalize.translateHtml(template, 'core');
|
||||
options.element.querySelector('form').addEventListener('submit', onSubmit.bind(self));
|
||||
if (options.enableSaveButton) {
|
||||
options.element.querySelector('.btnSave').classList.remove('hide');
|
||||
}
|
||||
self.loadData(options.autoFocus);
|
||||
}
|
||||
|
||||
function DisplaySettings(options) {
|
||||
this.options = options;
|
||||
embed(options, this);
|
||||
}
|
||||
class DisplaySettings {
|
||||
constructor(options) {
|
||||
this.options = options;
|
||||
embed(options, this);
|
||||
}
|
||||
|
||||
DisplaySettings.prototype.loadData = function (autoFocus) {
|
||||
var self = this;
|
||||
var context = self.options.element;
|
||||
loadData(autoFocus) {
|
||||
const self = this;
|
||||
const context = self.options.element;
|
||||
|
||||
loading.show();
|
||||
loading.show();
|
||||
|
||||
var userId = self.options.userId;
|
||||
var apiClient = connectionManager.getApiClient(self.options.serverId);
|
||||
var userSettings = self.options.userSettings;
|
||||
const userId = self.options.userId;
|
||||
const apiClient = connectionManager.getApiClient(self.options.serverId);
|
||||
const userSettings = self.options.userSettings;
|
||||
|
||||
return apiClient.getUser(userId).then(function (user) {
|
||||
return userSettings.setUserInfo(userId, apiClient).then(function () {
|
||||
self.dataLoaded = true;
|
||||
loadForm(context, user, userSettings, apiClient);
|
||||
if (autoFocus) {
|
||||
focusManager.autoFocus(context);
|
||||
}
|
||||
return apiClient.getUser(userId).then(user => {
|
||||
return userSettings.setUserInfo(userId, apiClient).then(() => {
|
||||
self.dataLoaded = true;
|
||||
loadForm(context, user, userSettings);
|
||||
if (autoFocus) {
|
||||
focusManager.autoFocus(context);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
DisplaySettings.prototype.submit = function () {
|
||||
onSubmit.call(this);
|
||||
};
|
||||
submit() {
|
||||
onSubmit.call(this);
|
||||
}
|
||||
|
||||
DisplaySettings.prototype.destroy = function () {
|
||||
this.options = null;
|
||||
};
|
||||
destroy() {
|
||||
this.options = null;
|
||||
}
|
||||
}
|
||||
|
||||
return DisplaySettings;
|
||||
});
|
||||
/* eslint-enable indent */
|
||||
export default DisplaySettings;
|
||||
|
||||
@@ -154,8 +154,7 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
|
||||
html += '<div is="emby-itemscontainer" class="itemsContainer vertical-wrap padded-left padded-right">';
|
||||
}
|
||||
|
||||
var supportsImageAnalysis = appHost.supports('imageanalysis');
|
||||
var cardLayout = (appHost.preferVisualCards || supportsImageAnalysis) && section.autoCardLayout && section.showTitle;
|
||||
var cardLayout = appHost.preferVisualCards && section.autoCardLayout && section.showTitle;
|
||||
cardLayout = false;
|
||||
html += cardBuilder.getCardsHtml(result.Items, {
|
||||
preferThumb: section.preferThumb,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* eslint-disable indent */
|
||||
export function getFetchPromise(request) {
|
||||
|
||||
const headers = request.headers || {};
|
||||
|
||||
if (request.dataType === 'json') {
|
||||
@@ -16,7 +15,6 @@
|
||||
let contentType = request.contentType;
|
||||
|
||||
if (request.data) {
|
||||
|
||||
if (typeof request.data === 'string') {
|
||||
fetchRequest.body = request.data;
|
||||
} else {
|
||||
@@ -27,7 +25,6 @@
|
||||
}
|
||||
|
||||
if (contentType) {
|
||||
|
||||
headers['Content-Type'] = contentType;
|
||||
}
|
||||
|
||||
@@ -48,11 +45,9 @@
|
||||
}
|
||||
|
||||
function fetchWithTimeout(url, options, timeoutMs) {
|
||||
|
||||
console.debug(`fetchWithTimeout: timeoutMs: ${timeoutMs}, url: ${url}`);
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
const timeout = setTimeout(reject, timeoutMs);
|
||||
|
||||
options = options || {};
|
||||
@@ -65,7 +60,6 @@
|
||||
|
||||
resolve(response);
|
||||
}, function (error) {
|
||||
|
||||
clearTimeout(timeout);
|
||||
|
||||
console.debug(`fetchWithTimeout: timed out connecting to url: ${url}`);
|
||||
|
||||
@@ -412,7 +412,7 @@ import 'css!./style.css';
|
||||
dlg.classList.add('background-theme-a');
|
||||
dlg.classList.add('formDialog');
|
||||
dlg.classList.add('filterDialog');
|
||||
dlg.innerHTML = globalize.translateDocument(template);
|
||||
dlg.innerHTML = globalize.translateHtml(template);
|
||||
setVisibility(dlg, this.options);
|
||||
dialogHelper.open(dlg);
|
||||
dlg.addEventListener('close', resolve);
|
||||
|
||||
@@ -2,19 +2,15 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||
'use strict';
|
||||
|
||||
function onSubmit(e) {
|
||||
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
function renderOptions(context, selector, cssClass, items, isCheckedFn) {
|
||||
|
||||
var elem = context.querySelector(selector);
|
||||
|
||||
if (items.length) {
|
||||
|
||||
elem.classList.remove('hide');
|
||||
|
||||
} else {
|
||||
elem.classList.add('hide');
|
||||
}
|
||||
@@ -22,7 +18,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||
var html = '';
|
||||
|
||||
html += items.map(function (filter) {
|
||||
|
||||
var itemHtml = '';
|
||||
|
||||
var checkedHtml = isCheckedFn(filter) ? ' checked' : '';
|
||||
@@ -32,45 +27,20 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||
itemHtml += '</label>';
|
||||
|
||||
return itemHtml;
|
||||
|
||||
}).join('');
|
||||
|
||||
elem.querySelector('.filterOptions').innerHTML = html;
|
||||
}
|
||||
|
||||
function renderDynamicFilters(context, result, options) {
|
||||
|
||||
// If there's a huge number of these they will be really show to render
|
||||
//if (result.Tags) {
|
||||
// result.Tags.length = Math.min(result.Tags.length, 50);
|
||||
//}
|
||||
|
||||
renderOptions(context, '.genreFilters', 'chkGenreFilter', result.Genres, function (i) {
|
||||
|
||||
// Switching from | to ,
|
||||
var delimeter = (options.settings.GenreIds || '').indexOf('|') === -1 ? ',' : '|';
|
||||
return (delimeter + (options.settings.GenreIds || '') + delimeter).indexOf(delimeter + i.Id + delimeter) !== -1;
|
||||
});
|
||||
|
||||
//renderOptions(context, '.officialRatingFilters', 'chkOfficialRatingFilter', result.OfficialRatings, function (i) {
|
||||
// var delimeter = '|';
|
||||
// return (delimeter + (query.OfficialRatings || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
|
||||
//});
|
||||
|
||||
//renderOptions(context, '.tagFilters', 'chkTagFilter', result.Tags, function (i) {
|
||||
// var delimeter = '|';
|
||||
// return (delimeter + (query.Tags || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
|
||||
//});
|
||||
|
||||
//renderOptions(context, '.yearFilters', 'chkYearFilter', result.Years, function (i) {
|
||||
|
||||
// var delimeter = ',';
|
||||
// return (delimeter + (query.Years || '') + delimeter).indexOf(delimeter + i + delimeter) != -1;
|
||||
//});
|
||||
}
|
||||
|
||||
function loadDynamicFilters(context, options) {
|
||||
|
||||
var apiClient = connectionManager.getApiClient(options.serverId);
|
||||
|
||||
var filterMenuOptions = Object.assign(options.filterMenuOptions, {
|
||||
@@ -81,16 +51,11 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||
});
|
||||
|
||||
apiClient.getFilters(filterMenuOptions).then(function (result) {
|
||||
|
||||
renderDynamicFilters(context, result, options);
|
||||
}, function () {
|
||||
|
||||
// older server
|
||||
});
|
||||
}
|
||||
|
||||
function initEditor(context, settings) {
|
||||
|
||||
context.querySelector('form').addEventListener('submit', onSubmit);
|
||||
|
||||
var elems = context.querySelectorAll('.simpleFilter');
|
||||
@@ -98,7 +63,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||
var length;
|
||||
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
|
||||
if (elems[i].tagName === 'INPUT') {
|
||||
elems[i].checked = settings[elems[i].getAttribute('data-settingname')] || false;
|
||||
} else {
|
||||
@@ -110,7 +74,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||
elems = context.querySelectorAll('.chkVideoTypeFilter');
|
||||
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
|
||||
elems[i].checked = videoTypes.indexOf(elems[i].getAttribute('data-filter')) !== -1;
|
||||
}
|
||||
|
||||
@@ -118,7 +81,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||
elems = context.querySelectorAll('.chkSeriesStatus');
|
||||
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
|
||||
elems[i].checked = seriesStatuses.indexOf(elems[i].getAttribute('data-filter')) !== -1;
|
||||
}
|
||||
|
||||
@@ -136,12 +98,10 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||
}
|
||||
|
||||
function saveValues(context, settings, settingsKey) {
|
||||
|
||||
var elems = context.querySelectorAll('.simpleFilter');
|
||||
var i;
|
||||
var length;
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
|
||||
if (elems[i].tagName === 'INPUT') {
|
||||
setBasicFilter(context, settingsKey + '-filter-' + elems[i].getAttribute('data-settingname'), elems[i]);
|
||||
} else {
|
||||
@@ -154,7 +114,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||
elems = context.querySelectorAll('.chkVideoTypeFilter');
|
||||
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
|
||||
if (elems[i].checked) {
|
||||
videoTypes.push(elems[i].getAttribute('data-filter'));
|
||||
}
|
||||
@@ -166,7 +125,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||
elems = context.querySelectorAll('.chkSeriesStatus');
|
||||
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
|
||||
if (elems[i].checked) {
|
||||
seriesStatuses.push(elems[i].getAttribute('data-filter'));
|
||||
}
|
||||
@@ -177,7 +135,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||
elems = context.querySelectorAll('.chkGenreFilter');
|
||||
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
|
||||
if (elems[i].checked) {
|
||||
genres.push(elems[i].getAttribute('data-filter'));
|
||||
}
|
||||
@@ -186,7 +143,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||
}
|
||||
|
||||
function setBasicFilter(context, key, elem) {
|
||||
|
||||
var value = elem.checked;
|
||||
value = value ? value : null;
|
||||
userSettings.setFilter(key, value);
|
||||
@@ -200,7 +156,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||
}
|
||||
|
||||
function moveCheckboxFocus(elem, offset) {
|
||||
|
||||
var parent = dom.parentWithClass(elem, 'checkboxList-verticalwrap');
|
||||
var elems = focusManager.getFocusableElements(parent);
|
||||
|
||||
@@ -225,7 +180,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||
|
||||
function onInputCommand(e) {
|
||||
switch (e.detail.command) {
|
||||
|
||||
case 'left':
|
||||
moveCheckboxFocus(e.target, -1);
|
||||
e.preventDefault();
|
||||
@@ -244,7 +198,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||
}
|
||||
|
||||
function bindCheckboxInput(context, on) {
|
||||
|
||||
var elems = context.querySelectorAll('.checkboxList-verticalwrap');
|
||||
for (var i = 0, length = elems.length; i < length; i++) {
|
||||
if (on) {
|
||||
@@ -256,11 +209,8 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||
}
|
||||
|
||||
FilterMenu.prototype.show = function (options) {
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
require(['text!./filtermenu.template.html'], function (template) {
|
||||
|
||||
var dialogOptions = {
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
@@ -286,7 +236,7 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||
|
||||
html += template;
|
||||
|
||||
dlg.innerHTML = globalize.translateDocument(html, 'core');
|
||||
dlg.innerHTML = globalize.translateHtml(html, 'core');
|
||||
|
||||
var settingElements = dlg.querySelectorAll('.viewSetting');
|
||||
for (var i = 0, length = settingElements.length; i < length; i++) {
|
||||
@@ -303,7 +253,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||
bindCheckboxInput(dlg, true);
|
||||
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', function () {
|
||||
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
|
||||
@@ -314,17 +263,10 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||
var submitted;
|
||||
|
||||
dlg.querySelector('form').addEventListener('change', function () {
|
||||
|
||||
submitted = true;
|
||||
//if (options.onChange) {
|
||||
// saveValues(dlg, options.settings, options.settingsKey);
|
||||
// options.onChange();
|
||||
//}
|
||||
|
||||
}, true);
|
||||
|
||||
dialogHelper.open(dlg).then(function () {
|
||||
|
||||
bindCheckboxInput(dlg, false);
|
||||
|
||||
if (layoutManager.tv) {
|
||||
@@ -332,7 +274,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
|
||||
}
|
||||
|
||||
if (submitted) {
|
||||
|
||||
//if (!options.onChange) {
|
||||
saveValues(dlg, options.settings, options.settingsKey);
|
||||
resolve();
|
||||
|
||||
@@ -7,14 +7,12 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
}
|
||||
|
||||
function popScope(elem) {
|
||||
|
||||
if (scopes.length) {
|
||||
scopes.length -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
function autoFocus(view, defaultToFirst, findAutoFocusElement) {
|
||||
|
||||
var element;
|
||||
if (findAutoFocusElement !== false) {
|
||||
element = view.querySelector('*[autofocus]');
|
||||
@@ -37,7 +35,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
}
|
||||
|
||||
function focus(element) {
|
||||
|
||||
try {
|
||||
element.focus({
|
||||
preventScroll: scrollManager.isEnabled()
|
||||
@@ -50,16 +47,13 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
var focusableTagNames = ['INPUT', 'TEXTAREA', 'SELECT', 'BUTTON', 'A'];
|
||||
var focusableContainerTagNames = ['BODY', 'DIALOG'];
|
||||
var focusableQuery = focusableTagNames.map(function (t) {
|
||||
|
||||
if (t === 'INPUT') {
|
||||
t += ':not([type="range"]):not([type="file"])';
|
||||
}
|
||||
return t + ':not([tabindex="-1"]):not(:disabled)';
|
||||
|
||||
}).join(',') + ',.focusable';
|
||||
|
||||
function isFocusable(elem) {
|
||||
|
||||
if (focusableTagNames.indexOf(elem.tagName) !== -1) {
|
||||
return true;
|
||||
}
|
||||
@@ -83,7 +77,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
}
|
||||
|
||||
function focusableParent(elem) {
|
||||
|
||||
var originalElement = elem;
|
||||
|
||||
while (!isFocusable(elem)) {
|
||||
@@ -101,7 +94,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
|
||||
// Determines if a focusable element can be focused at a given point in time
|
||||
function isCurrentlyFocusableInternal(elem) {
|
||||
|
||||
// http://stackoverflow.com/questions/19669786/check-if-element-is-visible-in-dom
|
||||
if (elem.offsetParent === null) {
|
||||
return false;
|
||||
@@ -112,7 +104,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
|
||||
// Determines if a focusable element can be focused at a given point in time
|
||||
function isCurrentlyFocusable(elem) {
|
||||
|
||||
if (elem.disabled) {
|
||||
return false;
|
||||
}
|
||||
@@ -143,7 +134,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
var focusableElements = [];
|
||||
|
||||
for (var i = 0, length = elems.length; i < length; i++) {
|
||||
|
||||
var elem = elems[i];
|
||||
|
||||
if (excludeClass && elem.classList.contains(excludeClass)) {
|
||||
@@ -163,7 +153,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
}
|
||||
|
||||
function isFocusContainer(elem, direction) {
|
||||
|
||||
if (focusableContainerTagNames.indexOf(elem.tagName) !== -1) {
|
||||
return true;
|
||||
}
|
||||
@@ -217,7 +206,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
}
|
||||
|
||||
function getOffset(elem) {
|
||||
|
||||
var box;
|
||||
|
||||
// Support: BlackBerry 5, iOS 3 (original iPhone)
|
||||
@@ -234,7 +222,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
}
|
||||
|
||||
if (box.right === null) {
|
||||
|
||||
// Create a new object because some browsers will throw an error when trying to set data onto the Rect object
|
||||
var newBox = {
|
||||
top: box.top,
|
||||
@@ -253,7 +240,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
}
|
||||
|
||||
function nav(activeElement, direction, container, focusableElements) {
|
||||
|
||||
activeElement = activeElement || document.activeElement;
|
||||
|
||||
if (activeElement) {
|
||||
@@ -272,14 +258,10 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
var rect = getOffset(activeElement);
|
||||
|
||||
// Get elements and work out x/y points
|
||||
var cache = [];
|
||||
var point1x = parseFloat(rect.left) || 0;
|
||||
var point1y = parseFloat(rect.top) || 0;
|
||||
var point2x = parseFloat(point1x + rect.width - 1) || point1x;
|
||||
var point2y = parseFloat(point1y + rect.height - 1) || point1y;
|
||||
// Shortcuts to help with compression
|
||||
var min = Math.min;
|
||||
var max = Math.max;
|
||||
|
||||
var sourceMidX = rect.left + (rect.width / 2);
|
||||
var sourceMidY = rect.top + (rect.height / 2);
|
||||
@@ -301,10 +283,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//if (!isCurrentlyFocusableInternal(curr)) {
|
||||
// continue;
|
||||
//}
|
||||
|
||||
var elementRect = getOffset(curr);
|
||||
|
||||
// not currently visible
|
||||
@@ -313,7 +291,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
}
|
||||
|
||||
switch (direction) {
|
||||
|
||||
case 0:
|
||||
// left
|
||||
if (elementRect.left >= rect.left) {
|
||||
@@ -369,7 +346,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
var distY;
|
||||
|
||||
switch (direction) {
|
||||
|
||||
case 0:
|
||||
// left
|
||||
distX = Math.abs(point1x - Math.min(point1x, x2));
|
||||
@@ -403,7 +379,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
}
|
||||
|
||||
if (nearestElement) {
|
||||
|
||||
// See if there's a focusable container, and if so, send the focus command to that
|
||||
if (activeElement) {
|
||||
var nearestElementFocusableParent = dom.parentWithClass(nearestElement, 'focusable');
|
||||
@@ -418,12 +393,10 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
}
|
||||
|
||||
function intersectsInternal(a1, a2, b1, b2) {
|
||||
|
||||
return (b1 >= a1 && b1 <= a2) || (b2 >= a1 && b2 <= a2);
|
||||
}
|
||||
|
||||
function intersects(a1, a2, b1, b2) {
|
||||
|
||||
return intersectsInternal(a1, a2, b1, b2) || intersectsInternal(b1, b2, a1, a2);
|
||||
}
|
||||
|
||||
@@ -434,11 +407,9 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
}
|
||||
|
||||
function focusFirst(container, focusableSelector) {
|
||||
|
||||
var elems = container.querySelectorAll(focusableSelector);
|
||||
|
||||
for (var i = 0, length = elems.length; i < length; i++) {
|
||||
|
||||
var elem = elems[i];
|
||||
|
||||
if (isCurrentlyFocusableInternal(elem)) {
|
||||
@@ -449,11 +420,9 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
}
|
||||
|
||||
function focusLast(container, focusableSelector) {
|
||||
|
||||
var elems = [].slice.call(container.querySelectorAll(focusableSelector), 0).reverse();
|
||||
|
||||
for (var i = 0, length = elems.length; i < length; i++) {
|
||||
|
||||
var elem = elems[i];
|
||||
|
||||
if (isCurrentlyFocusableInternal(elem)) {
|
||||
@@ -464,7 +433,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
}
|
||||
|
||||
function moveFocus(sourceElement, container, focusableSelector, offset) {
|
||||
|
||||
var elems = container.querySelectorAll(focusableSelector);
|
||||
var list = [];
|
||||
var i;
|
||||
@@ -472,7 +440,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
var elem;
|
||||
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
|
||||
elem = elems[i];
|
||||
|
||||
if (isCurrentlyFocusableInternal(elem)) {
|
||||
@@ -483,7 +450,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
|
||||
var currentIndex = -1;
|
||||
|
||||
for (i = 0, length = list.length; i < length; i++) {
|
||||
|
||||
elem = list[i];
|
||||
|
||||
if (sourceElement === elem || elem.contains(sourceElement)) {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
define(['dom', 'appRouter', 'connectionManager'], function (dom, appRouter, connectionManager) {
|
||||
'use strict';
|
||||
/* eslint-disable indent */
|
||||
|
||||
import dom from 'dom';
|
||||
import appRouter from 'appRouter';
|
||||
import connectionManager from 'connectionManager';
|
||||
|
||||
function onGroupedCardClick(e, card) {
|
||||
var itemId = card.getAttribute('data-id');
|
||||
@@ -31,7 +34,7 @@ define(['dom', 'appRouter', 'connectionManager'], function (dom, appRouter, conn
|
||||
}
|
||||
}
|
||||
|
||||
function onItemsContainerClick(e) {
|
||||
export default function onItemsContainerClick(e) {
|
||||
var groupedCard = dom.parentWithClass(e.target, 'groupedCard');
|
||||
|
||||
if (groupedCard) {
|
||||
@@ -39,7 +42,4 @@ define(['dom', 'appRouter', 'connectionManager'], function (dom, appRouter, conn
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
onItemsContainerClick: onItemsContainerClick
|
||||
};
|
||||
});
|
||||
/* eslint-enable indent */
|
||||
|
||||
@@ -2,12 +2,10 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio
|
||||
'use strict';
|
||||
|
||||
function saveCategories(context, options) {
|
||||
|
||||
var categories = [];
|
||||
|
||||
var chkCategorys = context.querySelectorAll('.chkCategory');
|
||||
for (var i = 0, length = chkCategorys.length; i < length; i++) {
|
||||
|
||||
var type = chkCategorys[i].getAttribute('data-type');
|
||||
|
||||
if (chkCategorys[i].checked) {
|
||||
@@ -25,12 +23,10 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio
|
||||
}
|
||||
|
||||
function loadCategories(context, options) {
|
||||
|
||||
var selectedCategories = options.categories || [];
|
||||
|
||||
var chkCategorys = context.querySelectorAll('.chkCategory');
|
||||
for (var i = 0, length = chkCategorys.length; i < length; i++) {
|
||||
|
||||
var type = chkCategorys[i].getAttribute('data-type');
|
||||
|
||||
chkCategorys[i].checked = !selectedCategories.length || selectedCategories.indexOf(type) !== -1;
|
||||
@@ -38,13 +34,11 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio
|
||||
}
|
||||
|
||||
function save(context) {
|
||||
|
||||
var i;
|
||||
var length;
|
||||
|
||||
var chkIndicators = context.querySelectorAll('.chkIndicator');
|
||||
for (i = 0, length = chkIndicators.length; i < length; i++) {
|
||||
|
||||
var type = chkIndicators[i].getAttribute('data-type');
|
||||
userSettings.set('guide-indicator-' + type, chkIndicators[i].checked);
|
||||
}
|
||||
@@ -62,13 +56,11 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio
|
||||
}
|
||||
|
||||
function load(context) {
|
||||
|
||||
var i;
|
||||
var length;
|
||||
|
||||
var chkIndicators = context.querySelectorAll('.chkIndicator');
|
||||
for (i = 0, length = chkIndicators.length; i < length; i++) {
|
||||
|
||||
var type = chkIndicators[i].getAttribute('data-type');
|
||||
|
||||
if (chkIndicators[i].getAttribute('data-default') === 'true') {
|
||||
@@ -90,13 +82,10 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio
|
||||
}
|
||||
|
||||
function showEditor(options) {
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
var settingsChanged = false;
|
||||
|
||||
require(['text!./guide-settings.template.html'], function (template) {
|
||||
|
||||
var dialogOptions = {
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
@@ -114,17 +103,15 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio
|
||||
|
||||
var html = '';
|
||||
|
||||
html += globalize.translateDocument(template, 'core');
|
||||
html += globalize.translateHtml(template, 'core');
|
||||
|
||||
dlg.innerHTML = html;
|
||||
|
||||
dlg.addEventListener('change', function () {
|
||||
|
||||
settingsChanged = true;
|
||||
});
|
||||
|
||||
dlg.addEventListener('close', function () {
|
||||
|
||||
if (layoutManager.tv) {
|
||||
scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
'use strict';
|
||||
|
||||
function showViewSettings(instance) {
|
||||
|
||||
require(['guide-settings-dialog'], function (guideSettingsDialog) {
|
||||
guideSettingsDialog.show(instance.categoryOptions).then(function () {
|
||||
instance.refresh();
|
||||
@@ -11,7 +10,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function updateProgramCellOnScroll(cell, scrollPct) {
|
||||
|
||||
var left = cell.posLeft;
|
||||
if (!left) {
|
||||
left = parseFloat(cell.style.left.replace('%', ''));
|
||||
@@ -43,11 +41,9 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
|
||||
if (guideProgramName) {
|
||||
if (pctOfWidth > 0 && pctOfWidth <= 100) {
|
||||
//guideProgramName.style.marginLeft = pctOfWidth + '%';
|
||||
guideProgramName.style.transform = 'translateX(' + pctOfWidth + '%)';
|
||||
caret.classList.remove('hide');
|
||||
} else {
|
||||
//guideProgramName.style.marginLeft = '0';
|
||||
guideProgramName.style.transform = 'none';
|
||||
caret.classList.add('hide');
|
||||
}
|
||||
@@ -56,7 +52,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
|
||||
var isUpdatingProgramCellScroll = false;
|
||||
function updateProgramCellsOnScroll(programGrid, programCells) {
|
||||
|
||||
if (isUpdatingProgramCellScroll) {
|
||||
return;
|
||||
}
|
||||
@@ -64,13 +59,11 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
isUpdatingProgramCellScroll = true;
|
||||
|
||||
requestAnimationFrame(function () {
|
||||
|
||||
var scrollLeft = programGrid.scrollLeft;
|
||||
|
||||
var scrollPct = scrollLeft ? (scrollLeft / programGrid.scrollWidth) * 100 : 0;
|
||||
|
||||
for (var i = 0, length = programCells.length; i < length; i++) {
|
||||
|
||||
updateProgramCellOnScroll(programCells[i], scrollPct);
|
||||
}
|
||||
|
||||
@@ -79,14 +72,12 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function onProgramGridClick(e) {
|
||||
|
||||
if (!layoutManager.tv) {
|
||||
return;
|
||||
}
|
||||
|
||||
var programCell = dom.parentWithClass(e.target, 'programCell');
|
||||
if (programCell) {
|
||||
|
||||
var startDate = programCell.getAttribute('data-startdate');
|
||||
var endDate = programCell.getAttribute('data-enddate');
|
||||
startDate = datetime.parseISO8601Date(startDate, { toLocal: true }).getTime();
|
||||
@@ -94,7 +85,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
|
||||
var now = new Date().getTime();
|
||||
if (now >= startDate && now < endDate) {
|
||||
|
||||
var channelId = programCell.getAttribute('data-channelid');
|
||||
var serverId = programCell.getAttribute('data-serverid');
|
||||
|
||||
@@ -110,7 +100,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function Guide(options) {
|
||||
|
||||
var self = this;
|
||||
var items = {};
|
||||
|
||||
@@ -121,7 +110,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
var cellCurationMinutes = 30;
|
||||
var cellDurationMs = cellCurationMinutes * 60 * 1000;
|
||||
var msPerDay = 86400000;
|
||||
var totalRendererdMs = msPerDay;
|
||||
|
||||
var currentDate;
|
||||
var currentStartIndex = 0;
|
||||
@@ -132,7 +120,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
var programGrid;
|
||||
|
||||
self.refresh = function () {
|
||||
|
||||
currentDate = null;
|
||||
reloadPage(options.element);
|
||||
restartAutoRefresh();
|
||||
@@ -151,7 +138,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
};
|
||||
|
||||
self.destroy = function () {
|
||||
|
||||
stopAutoRefresh();
|
||||
|
||||
events.off(serverNotifications, 'TimerCreated', onTimerCreated);
|
||||
@@ -165,7 +151,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
};
|
||||
|
||||
function restartAutoRefresh() {
|
||||
|
||||
stopAutoRefresh();
|
||||
|
||||
var intervalMs = 60000 * 15; // (minutes)
|
||||
@@ -183,15 +168,11 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function normalizeDateToTimeslot(date) {
|
||||
|
||||
var minutesOffset = date.getMinutes() - cellCurationMinutes;
|
||||
|
||||
if (minutesOffset >= 0) {
|
||||
|
||||
date.setHours(date.getHours(), cellCurationMinutes, 0, 0);
|
||||
|
||||
} else {
|
||||
|
||||
date.setHours(date.getHours(), 0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -207,7 +188,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function reloadGuide(context, newStartDate, scrollToTimeMs, focusToTimeMs, startTimeOfDayMs, focusProgramOnRender) {
|
||||
|
||||
var apiClient = connectionManager.getApiClient(options.serverId);
|
||||
|
||||
var channelQuery = {
|
||||
@@ -290,12 +270,10 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
};
|
||||
|
||||
apiClient.getLiveTvChannels(channelQuery).then(function (channelsResult) {
|
||||
|
||||
var btnPreviousPage = context.querySelector('.btnPreviousPage');
|
||||
var btnNextPage = context.querySelector('.btnNextPage');
|
||||
|
||||
if (channelsResult.TotalRecordCount > channelLimit) {
|
||||
|
||||
context.querySelector('.guideOptions').classList.remove('hide');
|
||||
|
||||
btnPreviousPage.classList.remove('hide');
|
||||
@@ -312,7 +290,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
} else {
|
||||
btnNextPage.disabled = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
context.querySelector('.guideOptions').classList.add('hide');
|
||||
}
|
||||
@@ -343,22 +320,17 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
apiClient.getLiveTvPrograms(programQuery).then(function (programsResult) {
|
||||
|
||||
renderGuide(context, date, channelsResult.Items, programsResult.Items, renderOptions, apiClient, scrollToTimeMs, focusToTimeMs, startTimeOfDayMs, focusProgramOnRender);
|
||||
|
||||
hideLoading();
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getDisplayTime(date) {
|
||||
|
||||
if ((typeof date).toString().toLowerCase() === 'string') {
|
||||
try {
|
||||
|
||||
date = datetime.parseISO8601Date(date, { toLocal: true });
|
||||
|
||||
} catch (err) {
|
||||
return date;
|
||||
}
|
||||
@@ -368,7 +340,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function getTimeslotHeadersHtml(startDate, endDateTime) {
|
||||
|
||||
var html = '';
|
||||
|
||||
// clone
|
||||
@@ -377,7 +348,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
html += '<div class="timeslotHeadersInner">';
|
||||
|
||||
while (startDate.getTime() < endDateTime) {
|
||||
|
||||
html += '<div class="timeslotHeader">';
|
||||
|
||||
html += getDisplayTime(startDate);
|
||||
@@ -411,23 +381,19 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function getTimerIndicator(item) {
|
||||
|
||||
var status;
|
||||
|
||||
if (item.Type === 'SeriesTimer') {
|
||||
return '<span class="material-icons programIcon seriesTimerIcon fiber_smart_record"></span>';
|
||||
} else if (item.TimerId || item.SeriesTimerId) {
|
||||
|
||||
status = item.Status || 'Cancelled';
|
||||
} else if (item.Type === 'Timer') {
|
||||
|
||||
status = item.Status;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (item.SeriesTimerId) {
|
||||
|
||||
if (status !== 'Cancelled') {
|
||||
return '<span class="material-icons programIcon seriesTimerIcon fiber_smart_record"></span>';
|
||||
}
|
||||
@@ -439,7 +405,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function getChannelProgramsHtml(context, date, channel, programs, options, listInfo) {
|
||||
|
||||
var html = '';
|
||||
|
||||
var startMs = date.getTime();
|
||||
@@ -463,11 +428,9 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
var now = new Date().getTime();
|
||||
|
||||
for (var i = listInfo.startIndex, length = programs.length; i < length; i++) {
|
||||
|
||||
var program = programs[i];
|
||||
|
||||
if (program.ChannelId !== channel.Id) {
|
||||
|
||||
if (programsFound) {
|
||||
break;
|
||||
}
|
||||
@@ -577,7 +540,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
html += '</div>';
|
||||
|
||||
if (program.IsHD && options.showHdIcon) {
|
||||
//html += '<span class="guideHdIcon material-icons programIcon hd"></span>';
|
||||
if (layoutManager.tv) {
|
||||
html += '<div class="programIcon guide-programTextIcon guide-programTextIcon-tv">HD</div>';
|
||||
} else {
|
||||
@@ -599,11 +561,9 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function renderChannelHeaders(context, channels, apiClient) {
|
||||
|
||||
var html = '';
|
||||
|
||||
for (var i = 0, length = channels.length; i < length; i++) {
|
||||
|
||||
var channel = channels[i];
|
||||
var hasChannelImage = channel.ImageTags.Primary;
|
||||
|
||||
@@ -615,18 +575,15 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
|
||||
var title = [];
|
||||
if (channel.ChannelNumber) {
|
||||
|
||||
title.push(channel.ChannelNumber);
|
||||
}
|
||||
if (channel.Name) {
|
||||
|
||||
title.push(channel.Name);
|
||||
}
|
||||
|
||||
html += '<button title="' + title.join(' ') + '" type="button" class="' + cssClass + '"' + ' data-action="link" data-isfolder="' + channel.IsFolder + '" data-id="' + channel.Id + '" data-serverid="' + channel.ServerId + '" data-type="' + channel.Type + '">';
|
||||
|
||||
if (hasChannelImage) {
|
||||
|
||||
var url = apiClient.getScaledImageUrl(channel.Id, {
|
||||
maxHeight: 220,
|
||||
tag: channel.ImageTags.Primary,
|
||||
@@ -637,7 +594,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
if (channel.ChannelNumber) {
|
||||
|
||||
html += '<h3 class="guideChannelNumber">' + channel.ChannelNumber + '</h3>';
|
||||
}
|
||||
|
||||
@@ -654,7 +610,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function renderPrograms(context, date, channels, programs, options) {
|
||||
|
||||
var listInfo = {
|
||||
startIndex: 0
|
||||
};
|
||||
@@ -662,7 +617,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
var html = [];
|
||||
|
||||
for (var i = 0, length = channels.length; i < length; i++) {
|
||||
|
||||
html.push(getChannelProgramsHtml(context, date, channels[i], programs, options, listInfo));
|
||||
}
|
||||
|
||||
@@ -674,7 +628,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function getProgramSortOrder(program, channels) {
|
||||
|
||||
var channelId = program.ChannelId;
|
||||
var channelIndex = -1;
|
||||
|
||||
@@ -691,7 +644,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function renderGuide(context, date, channels, programs, renderOptions, apiClient, scrollToTimeMs, focusToTimeMs, startTimeOfDayMs, focusProgramOnRender) {
|
||||
|
||||
programs.sort(function (a, b) {
|
||||
return getProgramSortOrder(a, channels) - getProgramSortOrder(b, channels);
|
||||
});
|
||||
@@ -721,7 +673,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function scrollProgramGridToTimeMs(context, scrollToTimeMs, startTimeOfDayMs) {
|
||||
|
||||
scrollToTimeMs -= startTimeOfDayMs;
|
||||
|
||||
var pct = scrollToTimeMs / msPerDay;
|
||||
@@ -734,7 +685,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function focusProgram(context, itemId, channelRowId, focusToTimeMs, startTimeOfDayMs) {
|
||||
|
||||
var focusElem;
|
||||
if (itemId) {
|
||||
focusElem = context.querySelector('[data-id="' + itemId + '"]');
|
||||
@@ -743,7 +693,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
if (focusElem) {
|
||||
focusManager.focus(focusElem);
|
||||
} else {
|
||||
|
||||
var autoFocusParent;
|
||||
|
||||
if (channelRowId) {
|
||||
@@ -761,7 +710,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
var programCell = autoFocusParent.querySelector('.programCell');
|
||||
|
||||
while (programCell) {
|
||||
|
||||
var left = (programCell.style.left || '').replace('%', '');
|
||||
left = left ? parseFloat(left) : 0;
|
||||
var width = (programCell.style.width || '').replace('%', '');
|
||||
@@ -782,7 +730,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function nativeScrollTo(container, pos, horizontal) {
|
||||
|
||||
if (container.scrollTo) {
|
||||
if (horizontal) {
|
||||
container.scrollTo(pos, 0);
|
||||
@@ -802,7 +749,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
var lastHeaderScroll = 0;
|
||||
var scrollXPct = 0;
|
||||
function onProgramGridScroll(context, elem, timeslotHeaders) {
|
||||
|
||||
if ((new Date().getTime() - lastHeaderScroll) >= 1000) {
|
||||
lastGridScroll = new Date().getTime();
|
||||
|
||||
@@ -815,7 +761,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function onTimeslotHeadersScroll(context, elem) {
|
||||
|
||||
if ((new Date().getTime() - lastGridScroll) >= 1000) {
|
||||
lastHeaderScroll = new Date().getTime();
|
||||
nativeScrollTo(programGrid, elem.scrollLeft, true);
|
||||
@@ -823,7 +768,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function changeDate(page, date, scrollToTimeMs, focusToTimeMs, startTimeOfDayMs, focusProgramOnRender) {
|
||||
|
||||
var newStartDate = normalizeDateToTimeslot(date);
|
||||
currentDate = newStartDate;
|
||||
|
||||
@@ -831,7 +775,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function getDateTabText(date, isActive, tabIndex) {
|
||||
|
||||
var cssClass = isActive ? 'emby-tab-button guide-date-tab-button emby-tab-button-active' : 'emby-tab-button guide-date-tab-button';
|
||||
|
||||
var html = '<button is="emby-button" class="' + cssClass + '" data-index="' + tabIndex + '" data-date="' + date.getTime() + '">';
|
||||
@@ -846,7 +789,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function setDateRange(page, guideInfo) {
|
||||
|
||||
var today = new Date();
|
||||
var nowHours = today.getHours();
|
||||
today.setHours(nowHours, 0, 0, 0);
|
||||
@@ -866,6 +808,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
var dateTabsHtml = '';
|
||||
var tabIndex = 0;
|
||||
|
||||
// TODO: Use date-fns
|
||||
var date = new Date();
|
||||
|
||||
if (currentDate) {
|
||||
@@ -873,13 +816,11 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
date.setHours(nowHours, 0, 0, 0);
|
||||
//start.setHours(0, 0, 0, 0);
|
||||
|
||||
var startTimeOfDayMs = (start.getHours() * 60 * 60 * 1000);
|
||||
startTimeOfDayMs += start.getMinutes() * 60 * 1000;
|
||||
|
||||
while (start <= end) {
|
||||
|
||||
var isActive = date.getDate() === start.getDate() && date.getMonth() === start.getMonth() && date.getFullYear() === start.getFullYear();
|
||||
|
||||
dateTabsHtml += getDateTabText(start, isActive, tabIndex);
|
||||
@@ -906,19 +847,16 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function reloadPage(page) {
|
||||
|
||||
showLoading();
|
||||
|
||||
var apiClient = connectionManager.getApiClient(options.serverId);
|
||||
|
||||
apiClient.getLiveTvGuideInfo().then(function (guideInfo) {
|
||||
|
||||
setDateRange(page, guideInfo);
|
||||
});
|
||||
}
|
||||
|
||||
function getChannelProgramsFocusableElements(container) {
|
||||
|
||||
var elements = container.querySelectorAll('.programCell');
|
||||
|
||||
var list = [];
|
||||
@@ -926,7 +864,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
var currentScrollXPct = scrollXPct + 1;
|
||||
|
||||
for (var i = 0, length = elements.length; i < length; i++) {
|
||||
|
||||
var elem = elements[i];
|
||||
|
||||
var left = (elem.style.left || '').replace('%', '');
|
||||
@@ -943,7 +880,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function onInputCommand(e) {
|
||||
|
||||
var target = e.target;
|
||||
var programCell = dom.parentWithClass(target, 'programCell');
|
||||
var container;
|
||||
@@ -951,10 +887,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
var focusableElements;
|
||||
var newRow;
|
||||
|
||||
var scrollX = false;
|
||||
|
||||
switch (e.detail.command) {
|
||||
|
||||
case 'up':
|
||||
if (programCell) {
|
||||
container = programGrid;
|
||||
@@ -1018,7 +951,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
focusManager.moveLeft(target, {
|
||||
container: container
|
||||
});
|
||||
scrollX = true;
|
||||
break;
|
||||
case 'right':
|
||||
container = programCell ? dom.parentWithClass(programCell, 'channelPrograms') : null;
|
||||
@@ -1027,7 +959,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
focusManager.moveRight(target, {
|
||||
container: container
|
||||
});
|
||||
scrollX = true;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
@@ -1038,7 +969,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function onScrollerFocus(e) {
|
||||
|
||||
var target = e.target;
|
||||
var programCell = dom.parentWithClass(target, 'programCell');
|
||||
|
||||
@@ -1057,22 +987,16 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
if (lastFocusDirection === 'left') {
|
||||
|
||||
if (programCell) {
|
||||
|
||||
scrollHelper.toStart(programGrid, programCell, true, true);
|
||||
}
|
||||
} else if (lastFocusDirection === 'right') {
|
||||
|
||||
if (programCell) {
|
||||
|
||||
scrollHelper.toCenter(programGrid, programCell, true, true);
|
||||
}
|
||||
} else if (lastFocusDirection === 'up' || lastFocusDirection === 'down') {
|
||||
|
||||
var verticalScroller = dom.parentWithClass(target, 'guideVerticalScroller');
|
||||
if (verticalScroller) {
|
||||
|
||||
var focusedElement = programCell || dom.parentWithTag(target, 'BUTTON');
|
||||
verticalScroller.toCenter(focusedElement, true);
|
||||
}
|
||||
@@ -1080,7 +1004,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function setScrollEvents(view, enabled) {
|
||||
|
||||
if (layoutManager.tv) {
|
||||
var guideVerticalScroller = view.querySelector('.guideVerticalScroller');
|
||||
|
||||
@@ -1093,7 +1016,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
function onTimerCreated(e, apiClient, data) {
|
||||
|
||||
var programId = data.ProgramId;
|
||||
// This could be null, not supported by all tv providers
|
||||
var newTimerId = data.Id;
|
||||
@@ -1146,12 +1068,11 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
require(['text!./tvguide.template.html'], function (template) {
|
||||
|
||||
var context = options.element;
|
||||
|
||||
context.classList.add('tvguide');
|
||||
|
||||
context.innerHTML = globalize.translateDocument(template, 'core');
|
||||
context.innerHTML = globalize.translateHtml(template, 'core');
|
||||
|
||||
programGrid = context.querySelector('.programGrid');
|
||||
var timeslotHeaders = context.querySelector('.timeslotHeaders');
|
||||
@@ -1203,12 +1124,10 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
});
|
||||
|
||||
context.querySelector('.guideDateTabs').addEventListener('tabchange', function (e) {
|
||||
|
||||
var allTabButtons = e.target.querySelectorAll('.guide-date-tab-button');
|
||||
|
||||
var tabButton = allTabButtons[parseInt(e.detail.selectedTabIndex)];
|
||||
if (tabButton) {
|
||||
|
||||
var previousButton = e.detail.previousIndex == null ? null : allTabButtons[parseInt(e.detail.previousIndex)];
|
||||
|
||||
var date = new Date();
|
||||
@@ -1223,7 +1142,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
|
||||
}
|
||||
|
||||
if (previousButton) {
|
||||
|
||||
var previousDate = new Date();
|
||||
previousDate.setTime(parseInt(previousButton.getAttribute('data-date')));
|
||||
|
||||
|
||||
@@ -1,30 +1,38 @@
|
||||
define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loading', 'connectionManager', 'homeSections', 'dom', 'events', 'listViewStyle', 'emby-select', 'emby-checkbox'], function (require, appHost, layoutManager, focusManager, globalize, loading, connectionManager, homeSections, dom, events) {
|
||||
'use strict';
|
||||
import layoutManager from 'layoutManager';
|
||||
import focusManager from 'focusManager';
|
||||
import globalize from 'globalize';
|
||||
import loading from 'loading';
|
||||
import connectionManager from 'connectionManager';
|
||||
import homeSections from 'homeSections';
|
||||
import dom from 'dom';
|
||||
import events from 'events';
|
||||
import 'listViewStyle';
|
||||
import 'emby-select';
|
||||
import 'emby-checkbox';
|
||||
|
||||
var numConfigurableSections = 7;
|
||||
/* eslint-disable indent */
|
||||
|
||||
const numConfigurableSections = 7;
|
||||
|
||||
function renderViews(page, user, result) {
|
||||
|
||||
var folderHtml = '';
|
||||
let folderHtml = '';
|
||||
|
||||
folderHtml += '<div class="checkboxList">';
|
||||
folderHtml += result.map(function (i) {
|
||||
folderHtml += result.map(i => {
|
||||
let currentHtml = '';
|
||||
|
||||
var currentHtml = '';
|
||||
const id = `chkGroupFolder${i.Id}`;
|
||||
|
||||
var id = 'chkGroupFolder' + i.Id;
|
||||
const isChecked = user.Configuration.GroupedFolders.includes(i.Id);
|
||||
|
||||
var isChecked = user.Configuration.GroupedFolders.indexOf(i.Id) !== -1;
|
||||
|
||||
var checkedHtml = isChecked ? ' checked="checked"' : '';
|
||||
const checkedHtml = isChecked ? ' checked="checked"' : '';
|
||||
|
||||
currentHtml += '<label>';
|
||||
currentHtml += '<input type="checkbox" is="emby-checkbox" class="chkGroupFolder" data-folderid="' + i.Id + '" id="' + id + '"' + checkedHtml + '/>';
|
||||
currentHtml += '<span>' + i.Name + '</span>';
|
||||
currentHtml += `<input type="checkbox" is="emby-checkbox" class="chkGroupFolder" data-folderid="${i.Id}" id="${id}"${checkedHtml}/>`;
|
||||
currentHtml += `<span>${i.Name}</span>`;
|
||||
currentHtml += '</label>';
|
||||
|
||||
return currentHtml;
|
||||
|
||||
}).join('');
|
||||
|
||||
folderHtml += '</div>';
|
||||
@@ -33,8 +41,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||
}
|
||||
|
||||
function getLandingScreenOptions(type) {
|
||||
|
||||
var list = [];
|
||||
const list = [];
|
||||
|
||||
if (type === 'movies') {
|
||||
list.push({
|
||||
@@ -122,28 +129,22 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||
}
|
||||
|
||||
function getLandingScreenOptionsHtml(type, userValue) {
|
||||
return getLandingScreenOptions(type).map(o => {
|
||||
const selected = userValue === o.value || (o.isDefault && !userValue);
|
||||
const selectedHtml = selected ? ' selected' : '';
|
||||
const optionValue = o.isDefault ? '' : o.value;
|
||||
|
||||
return getLandingScreenOptions(type).map(function (o) {
|
||||
|
||||
var selected = userValue === o.value || (o.isDefault && !userValue);
|
||||
var selectedHtml = selected ? ' selected' : '';
|
||||
var optionValue = o.isDefault ? '' : o.value;
|
||||
|
||||
return '<option value="' + optionValue + '"' + selectedHtml + '>' + o.name + '</option>';
|
||||
return `<option value="${optionValue}"${selectedHtml}>${o.name}</option>`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function renderViewOrder(context, user, result) {
|
||||
let html = '';
|
||||
|
||||
var html = '';
|
||||
html += result.Items.map((view) => {
|
||||
let currentHtml = '';
|
||||
|
||||
var index = 0;
|
||||
|
||||
html += result.Items.map(function (view) {
|
||||
|
||||
var currentHtml = '';
|
||||
|
||||
currentHtml += '<div class="listItem viewItem" data-viewid="' + view.Id + '">';
|
||||
currentHtml += `<div class="listItem viewItem" data-viewid="${view.Id}">`;
|
||||
|
||||
currentHtml += '<span class="material-icons listItemIcon folder_open"></span>';
|
||||
|
||||
@@ -155,29 +156,25 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||
|
||||
currentHtml += '</div>';
|
||||
|
||||
currentHtml += '<button type="button" is="paper-icon-button-light" class="btnViewItemUp btnViewItemMove autoSize" title="' + globalize.translate('Up') + '"><span class="material-icons keyboard_arrow_up"></span></button>';
|
||||
currentHtml += '<button type="button" is="paper-icon-button-light" class="btnViewItemDown btnViewItemMove autoSize" title="' + globalize.translate('Down') + '"><span class="material-icons keyboard_arrow_down"></span></button>';
|
||||
currentHtml += `<button type="button" is="paper-icon-button-light" class="btnViewItemUp btnViewItemMove autoSize" title="${globalize.translate('Up')}"><span class="material-icons keyboard_arrow_up"></span></button>`;
|
||||
currentHtml += `<button type="button" is="paper-icon-button-light" class="btnViewItemDown btnViewItemMove autoSize" title="${globalize.translate('Down')}"><span class="material-icons keyboard_arrow_down"></span></button>`;
|
||||
|
||||
currentHtml += '</div>';
|
||||
|
||||
index++;
|
||||
return currentHtml;
|
||||
|
||||
}).join('');
|
||||
|
||||
context.querySelector('.viewOrderList').innerHTML = html;
|
||||
}
|
||||
|
||||
function updateHomeSectionValues(context, userSettings) {
|
||||
for (let i = 1; i <= 7; i++) {
|
||||
const select = context.querySelector(`#selectHomeSection${i}`);
|
||||
const defaultValue = homeSections.getDefaultSection(i - 1);
|
||||
|
||||
for (var i = 1; i <= 7; i++) {
|
||||
const option = select.querySelector(`option[value=${defaultValue}]`) || select.querySelector('option[value=""]');
|
||||
|
||||
var select = context.querySelector('#selectHomeSection' + i);
|
||||
var defaultValue = homeSections.getDefaultSection(i - 1);
|
||||
|
||||
var option = select.querySelector('option[value=' + defaultValue + ']') || select.querySelector('option[value=""]');
|
||||
|
||||
var userValue = userSettings.get('homesection' + (i - 1));
|
||||
const userValue = userSettings.get(`homesection${i - 1}`);
|
||||
|
||||
option.value = '';
|
||||
|
||||
@@ -192,43 +189,39 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||
}
|
||||
|
||||
function getPerLibrarySettingsHtml(item, user, userSettings, apiClient) {
|
||||
let html = '';
|
||||
|
||||
var html = '';
|
||||
|
||||
var isChecked;
|
||||
let isChecked;
|
||||
|
||||
if (item.Type === 'Channel' || item.CollectionType === 'boxsets' || item.CollectionType === 'playlists') {
|
||||
isChecked = (user.Configuration.MyMediaExcludes || []).indexOf(item.Id) === -1;
|
||||
isChecked = !(user.Configuration.MyMediaExcludes || []).includes(item.Id);
|
||||
html += '<div>';
|
||||
html += '<label>';
|
||||
html += '<input type="checkbox" is="emby-checkbox" class="chkIncludeInMyMedia" data-folderid="' + item.Id + '"' + (isChecked ? ' checked="checked"' : '') + '/>';
|
||||
html += '<span>' + globalize.translate('DisplayInMyMedia') + '</span>';
|
||||
html += `<input type="checkbox" is="emby-checkbox" class="chkIncludeInMyMedia" data-folderid="${item.Id}"${isChecked ? ' checked="checked"' : ''}/>`;
|
||||
html += `<span>${globalize.translate('DisplayInMyMedia')}</span>`;
|
||||
html += '</label>';
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
var excludeFromLatest = ['playlists', 'livetv', 'boxsets', 'channels'];
|
||||
if (excludeFromLatest.indexOf(item.CollectionType || '') === -1) {
|
||||
|
||||
isChecked = user.Configuration.LatestItemsExcludes.indexOf(item.Id) === -1;
|
||||
const excludeFromLatest = ['playlists', 'livetv', 'boxsets', 'channels'];
|
||||
if (!excludeFromLatest.includes(item.CollectionType || '')) {
|
||||
isChecked = !user.Configuration.LatestItemsExcludes.includes(item.Id);
|
||||
html += '<label class="fldIncludeInLatest">';
|
||||
html += '<input type="checkbox" is="emby-checkbox" class="chkIncludeInLatest" data-folderid="' + item.Id + '"' + (isChecked ? ' checked="checked"' : '') + '/>';
|
||||
html += '<span>' + globalize.translate('DisplayInOtherHomeScreenSections') + '</span>';
|
||||
html += `<input type="checkbox" is="emby-checkbox" class="chkIncludeInLatest" data-folderid="${item.Id}"${isChecked ? ' checked="checked"' : ''}/>`;
|
||||
html += `<span>${globalize.translate('DisplayInOtherHomeScreenSections')}</span>`;
|
||||
html += '</label>';
|
||||
}
|
||||
|
||||
if (html) {
|
||||
|
||||
html = '<div class="checkboxListContainer">' + html + '</div>';
|
||||
html = `<div class="checkboxListContainer">${html}</div>`;
|
||||
}
|
||||
|
||||
if (item.CollectionType === 'movies' || item.CollectionType === 'tvshows' || item.CollectionType === 'music' || item.CollectionType === 'livetv') {
|
||||
|
||||
var idForLanding = item.CollectionType === 'livetv' ? item.CollectionType : item.Id;
|
||||
const idForLanding = item.CollectionType === 'livetv' ? item.CollectionType : item.Id;
|
||||
html += '<div class="selectContainer">';
|
||||
html += '<select is="emby-select" class="selectLanding" data-folderid="' + idForLanding + '" label="' + globalize.translate('LabelDefaultScreen') + '">';
|
||||
html += `<select is="emby-select" class="selectLanding" data-folderid="${idForLanding}" label="${globalize.translate('LabelDefaultScreen')}">`;
|
||||
|
||||
var userValue = userSettings.get('landing-' + idForLanding);
|
||||
const userValue = userSettings.get(`landing-${idForLanding}`);
|
||||
|
||||
html += getLandingScreenOptionsHtml(item.CollectionType, userValue);
|
||||
|
||||
@@ -237,8 +230,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||
}
|
||||
|
||||
if (html) {
|
||||
|
||||
var prefix = '';
|
||||
let prefix = '';
|
||||
prefix += '<div class="verticalSection">';
|
||||
|
||||
prefix += '<h2 class="sectionTitle">';
|
||||
@@ -253,12 +245,10 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||
}
|
||||
|
||||
function renderPerLibrarySettings(context, user, userViews, userSettings, apiClient) {
|
||||
const elem = context.querySelector('.perLibrarySettings');
|
||||
let html = '';
|
||||
|
||||
var elem = context.querySelector('.perLibrarySettings');
|
||||
var html = '';
|
||||
|
||||
for (var i = 0, length = userViews.length; i < length; i++) {
|
||||
|
||||
for (let i = 0, length = userViews.length; i < length; i++) {
|
||||
html += getPerLibrarySettingsHtml(userViews[i], user, userSettings, apiClient);
|
||||
}
|
||||
|
||||
@@ -266,16 +256,14 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||
}
|
||||
|
||||
function loadForm(context, user, userSettings, apiClient) {
|
||||
|
||||
context.querySelector('.chkHidePlayedFromLatest').checked = user.Configuration.HidePlayedInLatest || false;
|
||||
|
||||
updateHomeSectionValues(context, userSettings);
|
||||
|
||||
var promise1 = apiClient.getUserViews({ IncludeHidden: true }, user.Id);
|
||||
var promise2 = apiClient.getJSON(apiClient.getUrl('Users/' + user.Id + '/GroupingOptions'));
|
||||
|
||||
Promise.all([promise1, promise2]).then(function (responses) {
|
||||
const promise1 = apiClient.getUserViews({ IncludeHidden: true }, user.Id);
|
||||
const promise2 = apiClient.getJSON(apiClient.getUrl(`Users/${user.Id}/GroupingOptions`));
|
||||
|
||||
Promise.all([promise1, promise2]).then(responses => {
|
||||
renderViewOrder(context, user, responses[0]);
|
||||
|
||||
renderPerLibrarySettings(context, user, responses[0].Items, userSettings, apiClient);
|
||||
@@ -286,48 +274,23 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||
});
|
||||
}
|
||||
|
||||
function getSibling(elem, type, className) {
|
||||
|
||||
var sibling = elem[type];
|
||||
|
||||
while (sibling != null) {
|
||||
if (sibling.classList.contains(className)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sibling != null) {
|
||||
if (!sibling.classList.contains(className)) {
|
||||
sibling = null;
|
||||
}
|
||||
}
|
||||
|
||||
return sibling;
|
||||
}
|
||||
|
||||
function onSectionOrderListClick(e) {
|
||||
|
||||
var target = dom.parentWithClass(e.target, 'btnViewItemMove');
|
||||
const target = dom.parentWithClass(e.target, 'btnViewItemMove');
|
||||
|
||||
if (target) {
|
||||
var viewItem = dom.parentWithClass(target, 'viewItem');
|
||||
const viewItem = dom.parentWithClass(target, 'viewItem');
|
||||
|
||||
if (viewItem) {
|
||||
var ul = dom.parentWithClass(viewItem, 'paperList');
|
||||
|
||||
if (target.classList.contains('btnViewItemDown')) {
|
||||
|
||||
var next = viewItem.nextSibling;
|
||||
const next = viewItem.nextSibling;
|
||||
|
||||
if (next) {
|
||||
viewItem.parentNode.removeChild(viewItem);
|
||||
next.parentNode.insertBefore(viewItem, next.nextSibling);
|
||||
focusManager.focus(e.target);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
var prev = viewItem.previousSibling;
|
||||
const prev = viewItem.previousSibling;
|
||||
|
||||
if (prev) {
|
||||
viewItem.parentNode.removeChild(viewItem);
|
||||
@@ -340,44 +303,37 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||
}
|
||||
|
||||
function getCheckboxItems(selector, context, isChecked) {
|
||||
const inputs = context.querySelectorAll(selector);
|
||||
const list = [];
|
||||
|
||||
var inputs = context.querySelectorAll(selector);
|
||||
var list = [];
|
||||
|
||||
for (var i = 0, length = inputs.length; i < length; i++) {
|
||||
|
||||
for (let i = 0, length = inputs.length; i < length; i++) {
|
||||
if (inputs[i].checked === isChecked) {
|
||||
list.push(inputs[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
function saveUser(context, user, userSettingsInstance, apiClient) {
|
||||
|
||||
user.Configuration.HidePlayedInLatest = context.querySelector('.chkHidePlayedFromLatest').checked;
|
||||
|
||||
user.Configuration.LatestItemsExcludes = getCheckboxItems('.chkIncludeInLatest', context, false).map(function (i) {
|
||||
|
||||
user.Configuration.LatestItemsExcludes = getCheckboxItems('.chkIncludeInLatest', context, false).map(i => {
|
||||
return i.getAttribute('data-folderid');
|
||||
});
|
||||
|
||||
user.Configuration.MyMediaExcludes = getCheckboxItems('.chkIncludeInMyMedia', context, false).map(function (i) {
|
||||
|
||||
user.Configuration.MyMediaExcludes = getCheckboxItems('.chkIncludeInMyMedia', context, false).map(i => {
|
||||
return i.getAttribute('data-folderid');
|
||||
});
|
||||
|
||||
user.Configuration.GroupedFolders = getCheckboxItems('.chkGroupFolder', context, true).map(function (i) {
|
||||
|
||||
user.Configuration.GroupedFolders = getCheckboxItems('.chkGroupFolder', context, true).map(i => {
|
||||
return i.getAttribute('data-folderid');
|
||||
});
|
||||
|
||||
var viewItems = context.querySelectorAll('.viewItem');
|
||||
var orderedViews = [];
|
||||
var i;
|
||||
var length;
|
||||
const viewItems = context.querySelectorAll('.viewItem');
|
||||
const orderedViews = [];
|
||||
let i;
|
||||
let length;
|
||||
for (i = 0, length = viewItems.length; i < length; i++) {
|
||||
orderedViews.push(viewItems[i].getAttribute('data-viewid'));
|
||||
}
|
||||
@@ -394,48 +350,42 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||
userSettingsInstance.set('homesection5', context.querySelector('#selectHomeSection6').value);
|
||||
userSettingsInstance.set('homesection6', context.querySelector('#selectHomeSection7').value);
|
||||
|
||||
var selectLandings = context.querySelectorAll('.selectLanding');
|
||||
const selectLandings = context.querySelectorAll('.selectLanding');
|
||||
for (i = 0, length = selectLandings.length; i < length; i++) {
|
||||
var selectLanding = selectLandings[i];
|
||||
userSettingsInstance.set('landing-' + selectLanding.getAttribute('data-folderid'), selectLanding.value);
|
||||
const selectLanding = selectLandings[i];
|
||||
userSettingsInstance.set(`landing-${selectLanding.getAttribute('data-folderid')}`, selectLanding.value);
|
||||
}
|
||||
|
||||
return apiClient.updateUserConfiguration(user.Id, user.Configuration);
|
||||
}
|
||||
|
||||
function save(instance, context, userId, userSettings, apiClient, enableSaveConfirmation) {
|
||||
|
||||
loading.show();
|
||||
|
||||
apiClient.getUser(userId).then(function (user) {
|
||||
|
||||
saveUser(context, user, userSettings, apiClient).then(function () {
|
||||
|
||||
apiClient.getUser(userId).then(user => {
|
||||
saveUser(context, user, userSettings, apiClient).then(() => {
|
||||
loading.hide();
|
||||
if (enableSaveConfirmation) {
|
||||
require(['toast'], function (toast) {
|
||||
import('toast').then(({default: toast}) => {
|
||||
toast(globalize.translate('SettingsSaved'));
|
||||
});
|
||||
}
|
||||
|
||||
events.trigger(instance, 'saved');
|
||||
|
||||
}, function () {
|
||||
}, () => {
|
||||
loading.hide();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function onSubmit(e) {
|
||||
const self = this;
|
||||
const apiClient = connectionManager.getApiClient(self.options.serverId);
|
||||
const userId = self.options.userId;
|
||||
const userSettings = self.options.userSettings;
|
||||
|
||||
var self = this;
|
||||
var apiClient = connectionManager.getApiClient(self.options.serverId);
|
||||
var userId = self.options.userId;
|
||||
var userSettings = self.options.userSettings;
|
||||
|
||||
userSettings.setUserInfo(userId, apiClient).then(function () {
|
||||
|
||||
var enableSaveConfirmation = self.options.enableSaveConfirmation;
|
||||
userSettings.setUserInfo(userId, apiClient).then(() => {
|
||||
const enableSaveConfirmation = self.options.enableSaveConfirmation;
|
||||
save(self, self.options.element, userId, userSettings, apiClient, enableSaveConfirmation);
|
||||
});
|
||||
|
||||
@@ -447,14 +397,13 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||
}
|
||||
|
||||
function onChange(e) {
|
||||
|
||||
var chkIncludeInMyMedia = dom.parentWithClass(e.target, 'chkIncludeInMyMedia');
|
||||
const chkIncludeInMyMedia = dom.parentWithClass(e.target, 'chkIncludeInMyMedia');
|
||||
if (!chkIncludeInMyMedia) {
|
||||
return;
|
||||
}
|
||||
|
||||
var section = dom.parentWithClass(chkIncludeInMyMedia, 'verticalSection');
|
||||
var fldIncludeInLatest = section.querySelector('.fldIncludeInLatest');
|
||||
const section = dom.parentWithClass(chkIncludeInMyMedia, 'verticalSection');
|
||||
const fldIncludeInLatest = section.querySelector('.fldIncludeInLatest');
|
||||
if (fldIncludeInLatest) {
|
||||
if (chkIncludeInMyMedia.checked) {
|
||||
fldIncludeInLatest.classList.remove('hide');
|
||||
@@ -465,14 +414,12 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||
}
|
||||
|
||||
function embed(options, self) {
|
||||
|
||||
require(['text!./homeScreenSettings.template.html'], function (template) {
|
||||
|
||||
for (var i = 1; i <= numConfigurableSections; i++) {
|
||||
template = template.replace('{section' + i + 'label}', globalize.translate('LabelHomeScreenSectionValue', i));
|
||||
return import('text!./homeScreenSettings.template.html').then(({default: template}) => {
|
||||
for (let i = 1; i <= numConfigurableSections; i++) {
|
||||
template = template.replace(`{section${i}label}`, globalize.translate('LabelHomeScreenSectionValue', i));
|
||||
}
|
||||
|
||||
options.element.innerHTML = globalize.translateDocument(template, 'core');
|
||||
options.element.innerHTML = globalize.translateHtml(template, 'core');
|
||||
|
||||
options.element.querySelector('.viewOrderList').addEventListener('click', onSectionOrderListClick);
|
||||
options.element.querySelector('form').addEventListener('submit', onSubmit.bind(self));
|
||||
@@ -492,47 +439,44 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
|
||||
});
|
||||
}
|
||||
|
||||
function HomeScreenSettings(options) {
|
||||
class HomeScreenSettings {
|
||||
constructor(options) {
|
||||
this.options = options;
|
||||
embed(options, this);
|
||||
}
|
||||
|
||||
this.options = options;
|
||||
loadData(autoFocus) {
|
||||
const self = this;
|
||||
const context = self.options.element;
|
||||
|
||||
embed(options, this);
|
||||
loading.show();
|
||||
|
||||
const userId = self.options.userId;
|
||||
const apiClient = connectionManager.getApiClient(self.options.serverId);
|
||||
const userSettings = self.options.userSettings;
|
||||
|
||||
apiClient.getUser(userId).then(user => {
|
||||
userSettings.setUserInfo(userId, apiClient).then(() => {
|
||||
self.dataLoaded = true;
|
||||
|
||||
loadForm(context, user, userSettings, apiClient);
|
||||
|
||||
if (autoFocus) {
|
||||
focusManager.autoFocus(context);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
submit() {
|
||||
onSubmit.call(this);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.options = null;
|
||||
}
|
||||
}
|
||||
|
||||
HomeScreenSettings.prototype.loadData = function (autoFocus) {
|
||||
/* eslint-enable indent */
|
||||
|
||||
var self = this;
|
||||
var context = self.options.element;
|
||||
|
||||
loading.show();
|
||||
|
||||
var userId = self.options.userId;
|
||||
var apiClient = connectionManager.getApiClient(self.options.serverId);
|
||||
var userSettings = self.options.userSettings;
|
||||
|
||||
apiClient.getUser(userId).then(function (user) {
|
||||
|
||||
userSettings.setUserInfo(userId, apiClient).then(function () {
|
||||
|
||||
self.dataLoaded = true;
|
||||
|
||||
loadForm(context, user, userSettings, apiClient);
|
||||
|
||||
if (autoFocus) {
|
||||
focusManager.autoFocus(context);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
HomeScreenSettings.prototype.submit = function () {
|
||||
onSubmit.call(this);
|
||||
};
|
||||
|
||||
HomeScreenSettings.prototype.destroy = function () {
|
||||
|
||||
this.options = null;
|
||||
};
|
||||
|
||||
return HomeScreenSettings;
|
||||
});
|
||||
export default HomeScreenSettings;
|
||||
|
||||
@@ -1,7 +1,20 @@
|
||||
define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'layoutManager', 'imageLoader', 'globalize', 'itemShortcuts', 'itemHelper', 'appRouter', 'scripts/imagehelper', 'paper-icon-button-light', 'emby-itemscontainer', 'emby-scroller', 'emby-button', 'css!./homesections'], function (connectionManager, cardBuilder, appSettings, dom, appHost, layoutManager, imageLoader, globalize, itemShortcuts, itemHelper, appRouter, imageHelper) {
|
||||
'use strict';
|
||||
import connectionManager from 'connectionManager';
|
||||
import cardBuilder from 'cardBuilder';
|
||||
import dom from 'dom';
|
||||
import layoutManager from 'layoutManager';
|
||||
import imageLoader from 'imageLoader';
|
||||
import globalize from 'globalize';
|
||||
import appRouter from 'appRouter';
|
||||
import imageHelper from 'scripts/imagehelper';
|
||||
import 'paper-icon-button-light';
|
||||
import 'emby-itemscontainer';
|
||||
import 'emby-scroller';
|
||||
import 'emby-button';
|
||||
import 'css!./homesections';
|
||||
|
||||
function getDefaultSection(index) {
|
||||
/* eslint-disable indent */
|
||||
|
||||
export function getDefaultSection(index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return 'smalllibrarytiles';
|
||||
@@ -23,9 +36,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
}
|
||||
|
||||
function getAllSectionsToShow(userSettings, sectionCount) {
|
||||
var sections = [];
|
||||
for (var i = 0, length = sectionCount; i < length; i++) {
|
||||
var section = userSettings.get('homesection' + i) || getDefaultSection(i);
|
||||
const sections = [];
|
||||
for (let i = 0, length = sectionCount; i < length; i++) {
|
||||
let section = userSettings.get('homesection' + i) || getDefaultSection(i);
|
||||
if (section === 'folders') {
|
||||
section = getDefaultSection(0);
|
||||
}
|
||||
@@ -36,22 +49,22 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
return sections;
|
||||
}
|
||||
|
||||
function loadSections(elem, apiClient, user, userSettings) {
|
||||
export function loadSections(elem, apiClient, user, userSettings) {
|
||||
return getUserViews(apiClient, user.Id).then(function (userViews) {
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
if (userViews.length) {
|
||||
var sectionCount = 7;
|
||||
for (var i = 0; i < sectionCount; i++) {
|
||||
const sectionCount = 7;
|
||||
for (let i = 0; i < sectionCount; i++) {
|
||||
html += '<div class="verticalSection section' + i + '"></div>';
|
||||
}
|
||||
|
||||
elem.innerHTML = html;
|
||||
elem.classList.add('homeSectionsContainer');
|
||||
|
||||
var promises = [];
|
||||
var sections = getAllSectionsToShow(userSettings, sectionCount);
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
const promises = [];
|
||||
const sections = getAllSectionsToShow(userSettings, sectionCount);
|
||||
for (let i = 0; i < sections.length; i++) {
|
||||
promises.push(loadSection(elem, apiClient, user, userSettings, userViews, sections, i));
|
||||
}
|
||||
|
||||
@@ -62,7 +75,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
});
|
||||
});
|
||||
} else {
|
||||
var noLibDescription;
|
||||
let noLibDescription;
|
||||
if (user['Policy'] && user['Policy']['IsAdministrator']) {
|
||||
noLibDescription = globalize.translate('NoCreatedLibraries', '<br><a id="button-createLibrary" class="button-link">', '</a>');
|
||||
} else {
|
||||
@@ -75,7 +88,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
html += '</div>';
|
||||
elem.innerHTML = html;
|
||||
|
||||
var createNowLink = elem.querySelector('#button-createLibrary');
|
||||
const createNowLink = elem.querySelector('#button-createLibrary');
|
||||
if (createNowLink) {
|
||||
createNowLink.addEventListener('click', function () {
|
||||
Dashboard.navigate('library.html');
|
||||
@@ -85,9 +98,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
});
|
||||
}
|
||||
|
||||
function destroySections(elem) {
|
||||
var elems = elem.querySelectorAll('.itemsContainer');
|
||||
for (var i = 0; i < elems.length; i++) {
|
||||
export function destroySections(elem) {
|
||||
const elems = elem.querySelectorAll('.itemsContainer');
|
||||
for (let i = 0; i < elems.length; i++) {
|
||||
elems[i].fetchData = null;
|
||||
elems[i].parentContainer = null;
|
||||
elems[i].getItemsHtml = null;
|
||||
@@ -96,35 +109,32 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
elem.innerHTML = '';
|
||||
}
|
||||
|
||||
function pause(elem) {
|
||||
var elems = elem.querySelectorAll('.itemsContainer');
|
||||
for (var i = 0; i < elems.length; i++) {
|
||||
export function pause(elem) {
|
||||
const elems = elem.querySelectorAll('.itemsContainer');
|
||||
for (let i = 0; i < elems.length; i++) {
|
||||
elems[i].pause();
|
||||
}
|
||||
}
|
||||
|
||||
function resume(elem, options) {
|
||||
var elems = elem.querySelectorAll('.itemsContainer');
|
||||
var i;
|
||||
var length;
|
||||
var promises = [];
|
||||
export function resume(elem, options) {
|
||||
const elems = elem.querySelectorAll('.itemsContainer');
|
||||
const promises = [];
|
||||
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
for (let i = 0, length = elems.length; i < length; i++) {
|
||||
promises.push(elems[i].resume(options));
|
||||
}
|
||||
|
||||
var promise = Promise.all(promises);
|
||||
const promise = Promise.all(promises);
|
||||
if (!options || options.returnPromise !== false) {
|
||||
return promise;
|
||||
}
|
||||
}
|
||||
|
||||
function loadSection(page, apiClient, user, userSettings, userViews, allSections, index) {
|
||||
const section = allSections[index];
|
||||
const userId = user.Id;
|
||||
|
||||
var section = allSections[index];
|
||||
var userId = user.Id;
|
||||
|
||||
var elem = page.querySelector('.section' + index);
|
||||
const elem = page.querySelector('.section' + index);
|
||||
|
||||
if (section === 'latestmedia') {
|
||||
loadRecentlyAdded(elem, apiClient, user, userViews);
|
||||
@@ -172,7 +182,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
}
|
||||
|
||||
function getLibraryButtonsHtml(items) {
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
html += '<div class="verticalSection verticalSection-extrabottompadding">';
|
||||
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderMyMedia') + '</h2>';
|
||||
@@ -180,9 +190,9 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right vertical-wrap focuscontainer-x" data-multiselect="false">';
|
||||
|
||||
// library card background images
|
||||
for (var i = 0, length = items.length; i < length; i++) {
|
||||
var item = items[i];
|
||||
var icon = imageHelper.getLibraryIcon(item.CollectionType);
|
||||
for (let i = 0, length = items.length; i < length; i++) {
|
||||
const item = items[i];
|
||||
const icon = imageHelper.getLibraryIcon(item.CollectionType);
|
||||
html += '<a is="emby-linkbutton" href="' + appRouter.getRouteUrl(item) + '" class="raised homeLibraryButton"><span class="material-icons homeLibraryIcon ' + icon + '"></span><span class="homeLibraryText">' + item.Name + '</span></a>';
|
||||
}
|
||||
|
||||
@@ -194,24 +204,16 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
|
||||
function loadlibraryButtons(elem, apiClient, user, userSettings, userViews) {
|
||||
elem.classList.remove('verticalSection');
|
||||
var html = getLibraryButtonsHtml(userViews);
|
||||
const html = getLibraryButtonsHtml(userViews);
|
||||
|
||||
elem.innerHTML = html;
|
||||
imageLoader.lazyChildren(elem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random integer between min (inclusive) and max (inclusive)
|
||||
* Using Math.round() will give you a non-uniform distribution!
|
||||
*/
|
||||
function getRandomInt(min, max) {
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
}
|
||||
|
||||
function getFetchLatestItemsFn(serverId, parentId, collectionType) {
|
||||
return function () {
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
var limit = 16;
|
||||
const apiClient = connectionManager.getApiClient(serverId);
|
||||
let limit = 16;
|
||||
|
||||
if (enableScrollX()) {
|
||||
if (collectionType === 'music') {
|
||||
@@ -227,7 +229,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
}
|
||||
}
|
||||
|
||||
var options = {
|
||||
const options = {
|
||||
Limit: limit,
|
||||
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo,Path',
|
||||
ImageTypeLimit: 1,
|
||||
@@ -241,8 +243,8 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
|
||||
function getLatestItemsHtmlFn(itemType, viewType) {
|
||||
return function (items) {
|
||||
var cardLayout = false;
|
||||
var shape;
|
||||
const cardLayout = false;
|
||||
let shape;
|
||||
if (itemType === 'Channel' || viewType === 'movies' || viewType === 'books' || viewType === 'tvshows') {
|
||||
shape = getPortraitShape();
|
||||
} else if (viewType === 'music' || viewType === 'homevideos') {
|
||||
@@ -272,7 +274,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
}
|
||||
|
||||
function renderLatestSection(elem, apiClient, user, parent) {
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">';
|
||||
if (!layoutManager.tv) {
|
||||
@@ -303,7 +305,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
|
||||
elem.innerHTML = html;
|
||||
|
||||
var itemsContainer = elem.querySelector('.itemsContainer');
|
||||
const itemsContainer = elem.querySelector('.itemsContainer');
|
||||
itemsContainer.fetchData = getFetchLatestItemsFn(apiClient.serverId(), parent.Id, parent.CollectionType);
|
||||
itemsContainer.getItemsHtml = getLatestItemsHtmlFn(parent.Type, parent.CollectionType);
|
||||
itemsContainer.parentContainer = elem;
|
||||
@@ -311,10 +313,10 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
|
||||
function loadRecentlyAdded(elem, apiClient, user, userViews) {
|
||||
elem.classList.remove('verticalSection');
|
||||
var excludeViewTypes = ['playlists', 'livetv', 'boxsets', 'channels'];
|
||||
const excludeViewTypes = ['playlists', 'livetv', 'boxsets', 'channels'];
|
||||
|
||||
for (var i = 0, length = userViews.length; i < length; i++) {
|
||||
var item = userViews[i];
|
||||
for (let i = 0, length = userViews.length; i < length; i++) {
|
||||
const item = userViews[i];
|
||||
if (user.Configuration.LatestItemsExcludes.indexOf(item.Id) !== -1) {
|
||||
continue;
|
||||
}
|
||||
@@ -323,7 +325,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
continue;
|
||||
}
|
||||
|
||||
var frag = document.createElement('div');
|
||||
const frag = document.createElement('div');
|
||||
frag.classList.add('verticalSection');
|
||||
frag.classList.add('hide');
|
||||
elem.appendChild(frag);
|
||||
@@ -332,14 +334,8 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
}
|
||||
}
|
||||
|
||||
function getRequirePromise(deps) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
require(deps, resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function loadLibraryTiles(elem, apiClient, user, userSettings, shape, userViews, allSections) {
|
||||
var html = '';
|
||||
export function loadLibraryTiles(elem, apiClient, user, userSettings, shape, userViews, allSections) {
|
||||
let html = '';
|
||||
if (userViews.length) {
|
||||
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderMyMedia') + '</h2>';
|
||||
if (enableScrollX()) {
|
||||
@@ -372,10 +368,10 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
|
||||
function getContinueWatchingFetchFn(serverId) {
|
||||
return function () {
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
var screenWidth = dom.getWindowSize().innerWidth;
|
||||
const apiClient = connectionManager.getApiClient(serverId);
|
||||
const screenWidth = dom.getWindowSize().innerWidth;
|
||||
|
||||
var limit;
|
||||
let limit;
|
||||
if (enableScrollX()) {
|
||||
limit = 12;
|
||||
} else {
|
||||
@@ -383,7 +379,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
limit = Math.min(limit, 5);
|
||||
}
|
||||
|
||||
var options = {
|
||||
const options = {
|
||||
Limit: limit,
|
||||
Recursive: true,
|
||||
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
|
||||
@@ -398,7 +394,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
}
|
||||
|
||||
function getContinueWatchingItemsHtml(items) {
|
||||
var cardLayout = false;
|
||||
const cardLayout = false;
|
||||
return cardBuilder.getCardsHtml({
|
||||
items: items,
|
||||
preferThumb: true,
|
||||
@@ -419,7 +415,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
}
|
||||
|
||||
function loadResumeVideo(elem, apiClient, userId) {
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderContinueWatching') + '</h2>';
|
||||
if (enableScrollX()) {
|
||||
@@ -437,7 +433,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
elem.classList.add('hide');
|
||||
elem.innerHTML = html;
|
||||
|
||||
var itemsContainer = elem.querySelector('.itemsContainer');
|
||||
const itemsContainer = elem.querySelector('.itemsContainer');
|
||||
itemsContainer.fetchData = getContinueWatchingFetchFn(apiClient.serverId());
|
||||
itemsContainer.getItemsHtml = getContinueWatchingItemsHtml;
|
||||
itemsContainer.parentContainer = elem;
|
||||
@@ -445,10 +441,10 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
|
||||
function getContinueListeningFetchFn(serverId) {
|
||||
return function () {
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
var screenWidth = dom.getWindowSize().innerWidth;
|
||||
const apiClient = connectionManager.getApiClient(serverId);
|
||||
const screenWidth = dom.getWindowSize().innerWidth;
|
||||
|
||||
var limit;
|
||||
let limit;
|
||||
if (enableScrollX()) {
|
||||
limit = 12;
|
||||
} else {
|
||||
@@ -456,7 +452,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
limit = Math.min(limit, 5);
|
||||
}
|
||||
|
||||
var options = {
|
||||
const options = {
|
||||
Limit: limit,
|
||||
Recursive: true,
|
||||
Fields: 'PrimaryImageAspectRatio,BasicSyncInfo',
|
||||
@@ -471,7 +467,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
}
|
||||
|
||||
function getContinueListeningItemsHtml(items) {
|
||||
var cardLayout = false;
|
||||
const cardLayout = false;
|
||||
return cardBuilder.getCardsHtml({
|
||||
items: items,
|
||||
preferThumb: true,
|
||||
@@ -492,7 +488,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
}
|
||||
|
||||
function loadResumeAudio(elem, apiClient, userId) {
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + globalize.translate('HeaderContinueWatching') + '</h2>';
|
||||
if (enableScrollX()) {
|
||||
@@ -510,7 +506,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
elem.classList.add('hide');
|
||||
elem.innerHTML = html;
|
||||
|
||||
var itemsContainer = elem.querySelector('.itemsContainer');
|
||||
const itemsContainer = elem.querySelector('.itemsContainer');
|
||||
itemsContainer.fetchData = getContinueListeningFetchFn(apiClient.serverId());
|
||||
itemsContainer.getItemsHtml = getContinueListeningItemsHtml;
|
||||
itemsContainer.parentContainer = elem;
|
||||
@@ -518,7 +514,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
|
||||
function getOnNowFetchFn(serverId) {
|
||||
return function () {
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
const apiClient = connectionManager.getApiClient(serverId);
|
||||
return apiClient.getLiveTvRecommendedPrograms({
|
||||
userId: apiClient.getCurrentUserId(),
|
||||
IsAiring: true,
|
||||
@@ -532,7 +528,6 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
}
|
||||
|
||||
function getOnNowItemsHtml(items) {
|
||||
var cardLayout = false;
|
||||
return cardBuilder.getCardsHtml({
|
||||
items: items,
|
||||
preferThumb: 'auto',
|
||||
@@ -559,7 +554,6 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
var userId = user.Id;
|
||||
return apiClient.getLiveTvRecommendedPrograms({
|
||||
userId: apiClient.getCurrentUserId(),
|
||||
IsAiring: true,
|
||||
@@ -569,7 +563,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
EnableTotalRecordCount: false,
|
||||
Fields: 'ChannelInfo,PrimaryImageAspectRatio'
|
||||
}).then(function (result) {
|
||||
var html = '';
|
||||
let html = '';
|
||||
if (result.Items.length) {
|
||||
elem.classList.remove('padded-left');
|
||||
elem.classList.remove('padded-right');
|
||||
@@ -632,7 +626,6 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
html += '</h2>';
|
||||
html += '<span class="material-icons chevron_right"></span>';
|
||||
html += '</a>';
|
||||
|
||||
} else {
|
||||
html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate('HeaderOnNow') + '</h2>';
|
||||
}
|
||||
@@ -654,7 +647,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
|
||||
elem.innerHTML = html;
|
||||
|
||||
var itemsContainer = elem.querySelector('.itemsContainer');
|
||||
const itemsContainer = elem.querySelector('.itemsContainer');
|
||||
itemsContainer.parentContainer = elem;
|
||||
itemsContainer.fetchData = getOnNowFetchFn(apiClient.serverId());
|
||||
itemsContainer.getItemsHtml = getOnNowItemsHtml;
|
||||
@@ -664,7 +657,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
|
||||
function getNextUpFetchFn(serverId) {
|
||||
return function () {
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
const apiClient = connectionManager.getApiClient(serverId);
|
||||
return apiClient.getNextUpEpisodes({
|
||||
Limit: enableScrollX() ? 24 : 15,
|
||||
Fields: 'PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo,Path',
|
||||
@@ -677,7 +670,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
}
|
||||
|
||||
function getNextUpItemsHtml(items) {
|
||||
var cardLayout = false;
|
||||
const cardLayout = false;
|
||||
return cardBuilder.getCardsHtml({
|
||||
items: items,
|
||||
preferThumb: true,
|
||||
@@ -695,7 +688,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
}
|
||||
|
||||
function loadNextUp(elem, apiClient, userId) {
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">';
|
||||
if (!layoutManager.tv) {
|
||||
@@ -727,7 +720,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
elem.classList.add('hide');
|
||||
elem.innerHTML = html;
|
||||
|
||||
var itemsContainer = elem.querySelector('.itemsContainer');
|
||||
const itemsContainer = elem.querySelector('.itemsContainer');
|
||||
itemsContainer.fetchData = getNextUpFetchFn(apiClient.serverId());
|
||||
itemsContainer.getItemsHtml = getNextUpItemsHtml;
|
||||
itemsContainer.parentContainer = elem;
|
||||
@@ -735,7 +728,7 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
|
||||
function getLatestRecordingsFetchFn(serverId, activeRecordingsOnly) {
|
||||
return function () {
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
const apiClient = connectionManager.getApiClient(serverId);
|
||||
return apiClient.getLiveTvRecordings({
|
||||
userId: apiClient.getCurrentUserId(),
|
||||
Limit: enableScrollX() ? 12 : 5,
|
||||
@@ -749,7 +742,6 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
|
||||
function getLatestRecordingItemsHtml(activeRecordingsOnly) {
|
||||
return function (items) {
|
||||
var cardLayout = false;
|
||||
return cardBuilder.getCardsHtml({
|
||||
items: items,
|
||||
shape: enableScrollX() ? 'autooverflow' : 'auto',
|
||||
@@ -774,11 +766,11 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
}
|
||||
|
||||
function loadLatestLiveTvRecordings(elem, activeRecordingsOnly, apiClient, userId) {
|
||||
var title = activeRecordingsOnly ?
|
||||
const title = activeRecordingsOnly ?
|
||||
globalize.translate('HeaderActiveRecordings') :
|
||||
globalize.translate('HeaderLatestRecordings');
|
||||
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
html += '<div class="sectionTitleContainer sectionTitleContainer-cards">';
|
||||
html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + title + '</h2>';
|
||||
@@ -799,18 +791,19 @@ define(['connectionManager', 'cardBuilder', 'appSettings', 'dom', 'apphost', 'la
|
||||
elem.classList.add('hide');
|
||||
elem.innerHTML = html;
|
||||
|
||||
var itemsContainer = elem.querySelector('.itemsContainer');
|
||||
const itemsContainer = elem.querySelector('.itemsContainer');
|
||||
itemsContainer.fetchData = getLatestRecordingsFetchFn(apiClient.serverId(), activeRecordingsOnly);
|
||||
itemsContainer.getItemsHtml = getLatestRecordingItemsHtml(activeRecordingsOnly);
|
||||
itemsContainer.parentContainer = elem;
|
||||
}
|
||||
|
||||
return {
|
||||
loadLibraryTiles: loadLibraryTiles,
|
||||
getDefaultSection: getDefaultSection,
|
||||
loadSections: loadSections,
|
||||
destroySections: destroySections,
|
||||
pause: pause,
|
||||
resume: resume
|
||||
};
|
||||
});
|
||||
export default {
|
||||
loadLibraryTiles: loadLibraryTiles,
|
||||
getDefaultSection: getDefaultSection,
|
||||
loadSections: loadSections,
|
||||
destroySections: destroySections,
|
||||
pause: pause,
|
||||
resume: resume
|
||||
};
|
||||
|
||||
/* eslint-enable indent */
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
define(['appSettings', 'browser', 'events'], function (appSettings, browser, events) {
|
||||
'use strict';
|
||||
/* eslint-disable indent */
|
||||
|
||||
function getSavedVolume() {
|
||||
import appSettings from 'appSettings' ;
|
||||
import browser from 'browser';
|
||||
import events from 'events';
|
||||
|
||||
export function getSavedVolume() {
|
||||
return appSettings.get('volume') || 1;
|
||||
}
|
||||
|
||||
function saveVolume(value) {
|
||||
export function saveVolume(value) {
|
||||
if (value) {
|
||||
appSettings.set('volume', value);
|
||||
}
|
||||
}
|
||||
|
||||
function getCrossOriginValue(mediaSource) {
|
||||
export function getCrossOriginValue(mediaSource) {
|
||||
if (mediaSource.IsRemote) {
|
||||
return null;
|
||||
}
|
||||
@@ -30,34 +33,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
return false;
|
||||
}
|
||||
|
||||
function enableHlsShakaPlayer(item, mediaSource, mediaType) {
|
||||
/* eslint-disable-next-line compat/compat */
|
||||
if (!!window.MediaSource && !!MediaSource.isTypeSupported) {
|
||||
|
||||
if (canPlayNativeHls()) {
|
||||
|
||||
if (browser.edge && mediaType === 'Video') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// simple playback should use the native support
|
||||
if (mediaSource.RunTimeTicks) {
|
||||
//if (!browser.edge) {
|
||||
//return false;
|
||||
//}
|
||||
}
|
||||
|
||||
//return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function enableHlsJsPlayer(runTimeTicks, mediaType) {
|
||||
|
||||
export function enableHlsJsPlayer(runTimeTicks, mediaType) {
|
||||
if (window.MediaSource == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -73,7 +49,6 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
}
|
||||
|
||||
if (canPlayNativeHls()) {
|
||||
|
||||
// Having trouble with chrome's native support and transcoded music
|
||||
if (browser.android && mediaType === 'Audio') {
|
||||
return true;
|
||||
@@ -98,8 +73,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
|
||||
var recoverDecodingErrorDate;
|
||||
var recoverSwapAudioCodecDate;
|
||||
function handleHlsJsMediaError(instance, reject) {
|
||||
|
||||
export function handleHlsJsMediaError(instance, reject) {
|
||||
var hlsPlayer = instance._hlsPlayer;
|
||||
|
||||
if (!hlsPlayer) {
|
||||
@@ -134,8 +108,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
}
|
||||
}
|
||||
|
||||
function onErrorInternal(instance, type) {
|
||||
|
||||
export function onErrorInternal(instance, type) {
|
||||
// Needed for video
|
||||
if (instance.destroyCustomTrack) {
|
||||
instance.destroyCustomTrack(instance._mediaElement);
|
||||
@@ -148,7 +121,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
]);
|
||||
}
|
||||
|
||||
function isValidDuration(duration) {
|
||||
export function isValidDuration(duration) {
|
||||
if (duration && !isNaN(duration) && duration !== Number.POSITIVE_INFINITY && duration !== Number.NEGATIVE_INFINITY) {
|
||||
return true;
|
||||
}
|
||||
@@ -162,13 +135,10 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
}
|
||||
}
|
||||
|
||||
function seekOnPlaybackStart(instance, element, ticks, onMediaReady) {
|
||||
|
||||
export function seekOnPlaybackStart(instance, element, ticks, onMediaReady) {
|
||||
var seconds = (ticks || 0) / 10000000;
|
||||
|
||||
if (seconds) {
|
||||
var src = (instance.currentSrc() || '').toLowerCase();
|
||||
|
||||
// Appending #t=xxx to the query string doesn't seem to work with HLS
|
||||
// For plain video files, not all browsers support it either
|
||||
|
||||
@@ -200,12 +170,9 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
}
|
||||
}
|
||||
|
||||
function applySrc(elem, src, options) {
|
||||
|
||||
export function applySrc(elem, src, options) {
|
||||
if (window.Windows && options.mediaSource && options.mediaSource.IsLocal) {
|
||||
|
||||
return Windows.Storage.StorageFile.getFileFromPathAsync(options.url).then(function (file) {
|
||||
|
||||
var playlist = new Windows.Media.Playback.MediaPlaybackList();
|
||||
|
||||
var source1 = Windows.Media.Core.MediaSource.createFromStorageFile(file);
|
||||
@@ -214,9 +181,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
elem.src = URL.createObjectURL(playlist, { oneTimeOnly: true });
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
elem.src = src;
|
||||
}
|
||||
|
||||
@@ -224,18 +189,15 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
}
|
||||
|
||||
function onSuccessfulPlay(elem, onErrorFn) {
|
||||
|
||||
elem.addEventListener('error', onErrorFn);
|
||||
}
|
||||
|
||||
function playWithPromise(elem, onErrorFn) {
|
||||
|
||||
export function playWithPromise(elem, onErrorFn) {
|
||||
try {
|
||||
var promise = elem.play();
|
||||
if (promise && promise.then) {
|
||||
// Chrome now returns a promise
|
||||
return promise.catch(function (e) {
|
||||
|
||||
var errorName = (e.name || '').toLowerCase();
|
||||
// safari uses aborterror
|
||||
if (errorName === 'notallowederror' ||
|
||||
@@ -256,8 +218,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
}
|
||||
}
|
||||
|
||||
function destroyCastPlayer(instance) {
|
||||
|
||||
export function destroyCastPlayer(instance) {
|
||||
var player = instance._castPlayer;
|
||||
if (player) {
|
||||
try {
|
||||
@@ -270,20 +231,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
}
|
||||
}
|
||||
|
||||
function destroyShakaPlayer(instance) {
|
||||
var player = instance._shakaPlayer;
|
||||
if (player) {
|
||||
try {
|
||||
player.destroy();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
instance._shakaPlayer = null;
|
||||
}
|
||||
}
|
||||
|
||||
function destroyHlsPlayer(instance) {
|
||||
export function destroyHlsPlayer(instance) {
|
||||
var player = instance._hlsPlayer;
|
||||
if (player) {
|
||||
try {
|
||||
@@ -296,7 +244,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
}
|
||||
}
|
||||
|
||||
function destroyFlvPlayer(instance) {
|
||||
export function destroyFlvPlayer(instance) {
|
||||
var player = instance._flvPlayer;
|
||||
if (player) {
|
||||
try {
|
||||
@@ -311,11 +259,9 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
}
|
||||
}
|
||||
|
||||
function bindEventsToHlsPlayer(instance, hls, elem, onErrorFn, resolve, reject) {
|
||||
|
||||
export function bindEventsToHlsPlayer(instance, hls, elem, onErrorFn, resolve, reject) {
|
||||
hls.on(Hls.Events.MANIFEST_PARSED, function () {
|
||||
playWithPromise(elem, onErrorFn).then(resolve, function () {
|
||||
|
||||
if (reject) {
|
||||
reject();
|
||||
reject = null;
|
||||
@@ -324,14 +270,12 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
});
|
||||
|
||||
hls.on(Hls.Events.ERROR, function (event, data) {
|
||||
|
||||
console.error('HLS Error: Type: ' + data.type + ' Details: ' + (data.details || '') + ' Fatal: ' + (data.fatal || false));
|
||||
|
||||
switch (data.type) {
|
||||
case Hls.ErrorTypes.NETWORK_ERROR:
|
||||
// try to recover network error
|
||||
if (data.response && data.response.code && data.response.code >= 400) {
|
||||
|
||||
console.debug('hls.js response error code: ' + data.response.code);
|
||||
|
||||
// Trigger failure differently depending on whether this is prior to start of playback, or after
|
||||
@@ -345,7 +289,6 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -358,7 +301,6 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
case Hls.ErrorTypes.NETWORK_ERROR:
|
||||
|
||||
if (data.response && data.response.code === 0) {
|
||||
|
||||
// This could be a CORS error related to access control response headers
|
||||
|
||||
console.debug('hls.js response error code: ' + data.response.code);
|
||||
@@ -403,8 +345,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
});
|
||||
}
|
||||
|
||||
function onEndedInternal(instance, elem, onErrorFn) {
|
||||
|
||||
export function onEndedInternal(instance, elem, onErrorFn) {
|
||||
elem.removeEventListener('error', onErrorFn);
|
||||
|
||||
elem.src = '';
|
||||
@@ -413,7 +354,6 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
|
||||
destroyHlsPlayer(instance);
|
||||
destroyFlvPlayer(instance);
|
||||
destroyShakaPlayer(instance);
|
||||
destroyCastPlayer(instance);
|
||||
|
||||
var stopInfo = {
|
||||
@@ -427,8 +367,7 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
instance._currentPlayOptions = null;
|
||||
}
|
||||
|
||||
function getBufferedRanges(instance, elem) {
|
||||
|
||||
export function getBufferedRanges(instance, elem) {
|
||||
var ranges = [];
|
||||
var seekable = elem.buffered || [];
|
||||
|
||||
@@ -441,7 +380,6 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
offset = offset || 0;
|
||||
|
||||
for (var i = 0, length = seekable.length; i < length; i++) {
|
||||
|
||||
var start = seekable.start(i);
|
||||
var end = seekable.end(i);
|
||||
|
||||
@@ -462,23 +400,4 @@ define(['appSettings', 'browser', 'events'], function (appSettings, browser, eve
|
||||
return ranges;
|
||||
}
|
||||
|
||||
return {
|
||||
getSavedVolume: getSavedVolume,
|
||||
saveVolume: saveVolume,
|
||||
enableHlsJsPlayer: enableHlsJsPlayer,
|
||||
enableHlsShakaPlayer: enableHlsShakaPlayer,
|
||||
handleHlsJsMediaError: handleHlsJsMediaError,
|
||||
isValidDuration: isValidDuration,
|
||||
onErrorInternal: onErrorInternal,
|
||||
seekOnPlaybackStart: seekOnPlaybackStart,
|
||||
applySrc: applySrc,
|
||||
playWithPromise: playWithPromise,
|
||||
destroyHlsPlayer: destroyHlsPlayer,
|
||||
destroyFlvPlayer: destroyFlvPlayer,
|
||||
destroyCastPlayer: destroyCastPlayer,
|
||||
bindEventsToHlsPlayer: bindEventsToHlsPlayer,
|
||||
onEndedInternal: onEndedInternal,
|
||||
getCrossOriginValue: getCrossOriginValue,
|
||||
getBufferedRanges: getBufferedRanges
|
||||
};
|
||||
});
|
||||
/* eslint-enable indent */
|
||||
|
||||
@@ -1,24 +1,39 @@
|
||||
define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'imageLoader', 'browser', 'layoutManager', 'scrollHelper', 'globalize', 'require', 'emby-checkbox', 'paper-icon-button-light', 'emby-button', 'formDialogStyle', 'cardStyle'], function (dom, loading, appHost, dialogHelper, connectionManager, imageLoader, browser, layoutManager, scrollHelper, globalize, require) {
|
||||
'use strict';
|
||||
import dom from 'dom';
|
||||
import loading from 'loading';
|
||||
import appHost from 'apphost';
|
||||
import dialogHelper from 'dialogHelper';
|
||||
import connectionManager from 'connectionManager';
|
||||
import imageLoader from 'imageLoader';
|
||||
import browser from 'browser';
|
||||
import layoutManager from 'layoutManager';
|
||||
import scrollHelper from 'scrollHelper';
|
||||
import globalize from 'globalize';
|
||||
import require from 'require';
|
||||
import 'emby-checkbox';
|
||||
import 'paper-icon-button-light';
|
||||
import 'emby-button';
|
||||
import 'formDialogStyle';
|
||||
import 'cardStyle';
|
||||
|
||||
var enableFocusTransform = !browser.slow && !browser.edge;
|
||||
/* eslint-disable indent */
|
||||
|
||||
var currentItemId;
|
||||
var currentItemType;
|
||||
var currentResolve;
|
||||
var currentReject;
|
||||
var hasChanges = false;
|
||||
const enableFocusTransform = !browser.slow && !browser.edge;
|
||||
|
||||
let currentItemId;
|
||||
let currentItemType;
|
||||
let currentResolve;
|
||||
let currentReject;
|
||||
let hasChanges = false;
|
||||
|
||||
// These images can be large and we're seeing memory problems in safari
|
||||
var browsableImagePageSize = browser.slow ? 6 : 30;
|
||||
const browsableImagePageSize = browser.slow ? 6 : 30;
|
||||
|
||||
var browsableImageStartIndex = 0;
|
||||
var browsableImageType = 'Primary';
|
||||
var selectedProvider;
|
||||
let browsableImageStartIndex = 0;
|
||||
let browsableImageType = 'Primary';
|
||||
let selectedProvider;
|
||||
|
||||
function getBaseRemoteOptions() {
|
||||
|
||||
var options = {};
|
||||
const options = {};
|
||||
|
||||
options.itemId = currentItemId;
|
||||
|
||||
@@ -26,58 +41,53 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||
}
|
||||
|
||||
function reloadBrowsableImages(page, apiClient) {
|
||||
|
||||
loading.show();
|
||||
|
||||
var options = getBaseRemoteOptions();
|
||||
const options = getBaseRemoteOptions();
|
||||
|
||||
options.type = browsableImageType;
|
||||
options.startIndex = browsableImageStartIndex;
|
||||
options.limit = browsableImagePageSize;
|
||||
options.IncludeAllLanguages = page.querySelector('#chkAllLanguages').checked;
|
||||
|
||||
var provider = selectedProvider || '';
|
||||
const provider = selectedProvider || '';
|
||||
|
||||
if (provider) {
|
||||
options.ProviderName = provider;
|
||||
}
|
||||
|
||||
apiClient.getAvailableRemoteImages(options).then(function (result) {
|
||||
|
||||
renderRemoteImages(page, apiClient, result, browsableImageType, options.startIndex, options.limit);
|
||||
|
||||
page.querySelector('#selectBrowsableImageType').value = browsableImageType;
|
||||
|
||||
var providersHtml = result.Providers.map(function (p) {
|
||||
const providersHtml = result.Providers.map(function (p) {
|
||||
return '<option value="' + p + '">' + p + '</option>';
|
||||
});
|
||||
|
||||
var selectImageProvider = page.querySelector('#selectImageProvider');
|
||||
const selectImageProvider = page.querySelector('#selectImageProvider');
|
||||
selectImageProvider.innerHTML = '<option value="">' + globalize.translate('All') + '</option>' + providersHtml;
|
||||
selectImageProvider.value = provider;
|
||||
|
||||
loading.hide();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function renderRemoteImages(page, apiClient, imagesResult, imageType, startIndex, limit) {
|
||||
|
||||
page.querySelector('.availableImagesPaging').innerHTML = getPagingHtml(startIndex, limit, imagesResult.TotalRecordCount);
|
||||
|
||||
var html = '';
|
||||
|
||||
for (var i = 0, length = imagesResult.Images.length; i < length; i++) {
|
||||
let html = '';
|
||||
|
||||
for (let i = 0, length = imagesResult.Images.length; i < length; i++) {
|
||||
html += getRemoteImageHtml(imagesResult.Images[i], imageType, apiClient);
|
||||
}
|
||||
|
||||
var availableImagesList = page.querySelector('.availableImagesList');
|
||||
const availableImagesList = page.querySelector('.availableImagesList');
|
||||
availableImagesList.innerHTML = html;
|
||||
imageLoader.lazyChildren(availableImagesList);
|
||||
|
||||
var btnNextPage = page.querySelector('.btnNextPage');
|
||||
var btnPreviousPage = page.querySelector('.btnPreviousPage');
|
||||
const btnNextPage = page.querySelector('.btnNextPage');
|
||||
const btnPreviousPage = page.querySelector('.btnPreviousPage');
|
||||
|
||||
if (btnNextPage) {
|
||||
btnNextPage.addEventListener('click', function () {
|
||||
@@ -92,23 +102,21 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||
reloadBrowsableImages(page, apiClient);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getPagingHtml(startIndex, limit, totalRecordCount) {
|
||||
let html = '';
|
||||
|
||||
var html = '';
|
||||
|
||||
var recordsEnd = Math.min(startIndex + limit, totalRecordCount);
|
||||
const recordsEnd = Math.min(startIndex + limit, totalRecordCount);
|
||||
|
||||
// 20 is the minimum page size
|
||||
var showControls = totalRecordCount > limit;
|
||||
const showControls = totalRecordCount > limit;
|
||||
|
||||
html += '<div class="listPaging">';
|
||||
|
||||
html += '<span style="margin-right: 10px;">';
|
||||
|
||||
var startAtDisplay = totalRecordCount ? startIndex + 1 : 0;
|
||||
const startAtDisplay = totalRecordCount ? startIndex + 1 : 0;
|
||||
html += globalize.translate('ListPaging', startAtDisplay, recordsEnd, totalRecordCount);
|
||||
|
||||
html += '</span>';
|
||||
@@ -127,7 +135,7 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||
}
|
||||
|
||||
function downloadRemoteImage(page, apiClient, url, type, provider) {
|
||||
var options = getBaseRemoteOptions();
|
||||
const options = getBaseRemoteOptions();
|
||||
|
||||
options.Type = type;
|
||||
options.ImageUrl = url;
|
||||
@@ -136,9 +144,8 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||
loading.show();
|
||||
|
||||
apiClient.downloadRemoteImage(options).then(function () {
|
||||
|
||||
hasChanges = true;
|
||||
var dlg = dom.parentWithClass(page, 'dialog');
|
||||
const dlg = dom.parentWithClass(page, 'dialog');
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
}
|
||||
@@ -148,17 +155,17 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||
}
|
||||
|
||||
function getRemoteImageHtml(image, imageType, apiClient) {
|
||||
var tagName = layoutManager.tv ? 'button' : 'div';
|
||||
var enableFooterButtons = !layoutManager.tv;
|
||||
const tagName = layoutManager.tv ? 'button' : 'div';
|
||||
const enableFooterButtons = !layoutManager.tv;
|
||||
|
||||
// TODO move card creation code to Card component
|
||||
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
var cssClass = 'card scalableCard imageEditorCard';
|
||||
var cardBoxCssClass = 'cardBox visualCardBox';
|
||||
let cssClass = 'card scalableCard imageEditorCard';
|
||||
const cardBoxCssClass = 'cardBox visualCardBox';
|
||||
|
||||
var shape = 'backdrop';
|
||||
let shape;
|
||||
if (imageType === 'Backdrop' || imageType === 'Art' || imageType === 'Thumb' || imageType === 'Logo') {
|
||||
shape = 'backdrop';
|
||||
} else if (imageType === 'Banner') {
|
||||
@@ -166,7 +173,6 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||
} else if (imageType === 'Disc') {
|
||||
shape = 'square';
|
||||
} else {
|
||||
|
||||
if (currentItemType === 'Episode') {
|
||||
shape = 'backdrop';
|
||||
} else if (currentItemType === 'MusicAlbum' || currentItemType === 'MusicArtist') {
|
||||
@@ -217,19 +223,16 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||
html += '<div class="cardText cardTextCentered">' + image.ProviderName + '</div>';
|
||||
|
||||
if (image.Width || image.Height || image.Language) {
|
||||
|
||||
html += '<div class="cardText cardText-secondary cardTextCentered">';
|
||||
|
||||
if (image.Width && image.Height) {
|
||||
html += image.Width + ' x ' + image.Height;
|
||||
|
||||
if (image.Language) {
|
||||
|
||||
html += ' • ' + image.Language;
|
||||
}
|
||||
} else {
|
||||
if (image.Language) {
|
||||
|
||||
html += image.Language;
|
||||
}
|
||||
}
|
||||
@@ -238,13 +241,11 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||
}
|
||||
|
||||
if (image.CommunityRating != null) {
|
||||
|
||||
html += '<div class="cardText cardText-secondary cardTextCentered">';
|
||||
|
||||
if (image.RatingType === 'Likes') {
|
||||
html += image.CommunityRating + (image.CommunityRating === 1 ? ' like' : ' likes');
|
||||
} else {
|
||||
|
||||
if (image.CommunityRating) {
|
||||
html += image.CommunityRating.toFixed(1);
|
||||
|
||||
@@ -270,7 +271,6 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||
// end footer
|
||||
|
||||
html += '</div>';
|
||||
//html += '</div>';
|
||||
|
||||
html += '</' + tagName + '>';
|
||||
|
||||
@@ -287,7 +287,6 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||
});
|
||||
|
||||
page.querySelector('#selectImageProvider').addEventListener('change', function () {
|
||||
|
||||
browsableImageStartIndex = 0;
|
||||
selectedProvider = this.value;
|
||||
|
||||
@@ -295,22 +294,20 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||
});
|
||||
|
||||
page.querySelector('#chkAllLanguages').addEventListener('change', function () {
|
||||
|
||||
browsableImageStartIndex = 0;
|
||||
|
||||
reloadBrowsableImages(page, apiClient);
|
||||
});
|
||||
|
||||
page.addEventListener('click', function (e) {
|
||||
|
||||
var btnDownloadRemoteImage = dom.parentWithClass(e.target, 'btnDownloadRemoteImage');
|
||||
const btnDownloadRemoteImage = dom.parentWithClass(e.target, 'btnDownloadRemoteImage');
|
||||
if (btnDownloadRemoteImage) {
|
||||
var card = dom.parentWithClass(btnDownloadRemoteImage, 'card');
|
||||
const card = dom.parentWithClass(btnDownloadRemoteImage, 'card');
|
||||
downloadRemoteImage(page, apiClient, card.getAttribute('data-imageurl'), card.getAttribute('data-imagetype'), card.getAttribute('data-imageprovider'));
|
||||
return;
|
||||
}
|
||||
|
||||
var btnImageCard = dom.parentWithClass(e.target, 'btnImageCard');
|
||||
const btnImageCard = dom.parentWithClass(e.target, 'btnImageCard');
|
||||
if (btnImageCard) {
|
||||
downloadRemoteImage(page, apiClient, btnImageCard.getAttribute('data-imageurl'), btnImageCard.getAttribute('data-imagetype'), btnImageCard.getAttribute('data-imageprovider'));
|
||||
}
|
||||
@@ -321,13 +318,12 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||
loading.show();
|
||||
|
||||
require(['text!./imageDownloader.template.html'], function (template) {
|
||||
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
const apiClient = connectionManager.getApiClient(serverId);
|
||||
|
||||
currentItemId = itemId;
|
||||
currentItemType = itemType;
|
||||
|
||||
var dialogOptions = {
|
||||
const dialogOptions = {
|
||||
removeOnClose: true
|
||||
};
|
||||
|
||||
@@ -337,9 +333,9 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||
dialogOptions.size = 'small';
|
||||
}
|
||||
|
||||
var dlg = dialogHelper.createDialog(dialogOptions);
|
||||
const dlg = dialogHelper.createDialog(dialogOptions);
|
||||
|
||||
dlg.innerHTML = globalize.translateDocument(template, 'core');
|
||||
dlg.innerHTML = globalize.translateHtml(template, 'core');
|
||||
|
||||
if (layoutManager.tv) {
|
||||
scrollHelper.centerFocus.on(dlg, false);
|
||||
@@ -350,11 +346,10 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||
|
||||
dialogHelper.open(dlg);
|
||||
|
||||
var editorContent = dlg.querySelector('.formDialogContent');
|
||||
const editorContent = dlg.querySelector('.formDialogContent');
|
||||
initEditor(editorContent, apiClient);
|
||||
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', function () {
|
||||
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
|
||||
@@ -363,7 +358,7 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||
}
|
||||
|
||||
function onDialogClosed() {
|
||||
var dlg = this;
|
||||
const dlg = this;
|
||||
|
||||
if (layoutManager.tv) {
|
||||
scrollHelper.centerFocus.off(dlg, false);
|
||||
@@ -377,18 +372,20 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
show: function (itemId, serverId, itemType, imageType) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
currentResolve = resolve;
|
||||
currentReject = reject;
|
||||
hasChanges = false;
|
||||
browsableImageStartIndex = 0;
|
||||
browsableImageType = imageType || 'Primary';
|
||||
selectedProvider = null;
|
||||
export function show(itemId, serverId, itemType, imageType) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
currentResolve = resolve;
|
||||
currentReject = reject;
|
||||
hasChanges = false;
|
||||
browsableImageStartIndex = 0;
|
||||
browsableImageType = imageType || 'Primary';
|
||||
selectedProvider = null;
|
||||
showEditor(itemId, serverId, itemType);
|
||||
});
|
||||
}
|
||||
|
||||
showEditor(itemId, serverId, itemType);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
export default {
|
||||
show: show
|
||||
};
|
||||
|
||||
/* eslint-enable indent */
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
define(['globalize', 'dom', 'dialogHelper', 'emby-checkbox', 'emby-select', 'emby-input'], function (globalize, dom, dialogHelper) {
|
||||
'use strict';
|
||||
/* eslint-disable indent */
|
||||
|
||||
/**
|
||||
* Module for image Options Editor.
|
||||
* @module components/imageOptionsEditor/imageOptionsEditor
|
||||
*/
|
||||
|
||||
import globalize from 'globalize';
|
||||
import dom from 'dom';
|
||||
import dialogHelper from 'dialogHelper';
|
||||
import 'emby-checkbox';
|
||||
import 'emby-select';
|
||||
import 'emby-input';
|
||||
|
||||
function getDefaultImageConfig(itemType, type) {
|
||||
return {
|
||||
@@ -10,7 +21,7 @@ define(['globalize', 'dom', 'dialogHelper', 'emby-checkbox', 'emby-select', 'emb
|
||||
}
|
||||
|
||||
function findImageOptions(imageOptions, type) {
|
||||
return imageOptions.filter(function (i) {
|
||||
return imageOptions.filter(i => {
|
||||
return i.Type == type;
|
||||
})[0];
|
||||
}
|
||||
@@ -31,14 +42,14 @@ define(['globalize', 'dom', 'dialogHelper', 'emby-checkbox', 'emby-select', 'emb
|
||||
}
|
||||
|
||||
function loadValues(context, itemType, options, availableOptions) {
|
||||
var supportedImageTypes = availableOptions.SupportedImageTypes || [];
|
||||
setVisibilityOfBackdrops(context.querySelector('.backdropFields'), -1 != supportedImageTypes.indexOf('Backdrop'));
|
||||
setVisibilityOfBackdrops(context.querySelector('.screenshotFields'), -1 != supportedImageTypes.indexOf('Screenshot'));
|
||||
Array.prototype.forEach.call(context.querySelectorAll('.imageType'), function (i) {
|
||||
var imageType = i.getAttribute('data-imagetype');
|
||||
var container = dom.parentWithTag(i, 'LABEL');
|
||||
const supportedImageTypes = availableOptions.SupportedImageTypes || [];
|
||||
setVisibilityOfBackdrops(context.querySelector('.backdropFields'), supportedImageTypes.includes('Backdrop'));
|
||||
setVisibilityOfBackdrops(context.querySelector('.screenshotFields'), supportedImageTypes.includes('Screenshot'));
|
||||
Array.prototype.forEach.call(context.querySelectorAll('.imageType'), i => {
|
||||
const imageType = i.getAttribute('data-imagetype');
|
||||
const container = dom.parentWithTag(i, 'LABEL');
|
||||
|
||||
if (-1 == supportedImageTypes.indexOf(imageType)) {
|
||||
if (!supportedImageTypes.includes(imageType)) {
|
||||
container.classList.add('hide');
|
||||
} else {
|
||||
container.classList.remove('hide');
|
||||
@@ -50,16 +61,16 @@ define(['globalize', 'dom', 'dialogHelper', 'emby-checkbox', 'emby-select', 'emb
|
||||
i.checked = false;
|
||||
}
|
||||
});
|
||||
var backdropConfig = getImageConfig(options, availableOptions, 'Backdrop', itemType);
|
||||
const backdropConfig = getImageConfig(options, availableOptions, 'Backdrop', itemType);
|
||||
context.querySelector('#txtMaxBackdrops').value = backdropConfig.Limit;
|
||||
context.querySelector('#txtMinBackdropDownloadWidth').value = backdropConfig.MinWidth;
|
||||
var screenshotConfig = getImageConfig(options, availableOptions, 'Screenshot', itemType);
|
||||
const screenshotConfig = getImageConfig(options, availableOptions, 'Screenshot', itemType);
|
||||
context.querySelector('#txtMaxScreenshots').value = screenshotConfig.Limit;
|
||||
context.querySelector('#txtMinScreenshotDownloadWidth').value = screenshotConfig.MinWidth;
|
||||
}
|
||||
|
||||
function saveValues(context, options) {
|
||||
options.ImageOptions = Array.prototype.map.call(context.querySelectorAll('.imageType:not(.hide)'), function (c) {
|
||||
options.ImageOptions = Array.prototype.map.call(context.querySelectorAll('.imageType:not(.hide)'), c => {
|
||||
return {
|
||||
Type: c.getAttribute('data-imagetype'),
|
||||
Limit: c.checked ? 1 : 0,
|
||||
@@ -78,35 +89,36 @@ define(['globalize', 'dom', 'dialogHelper', 'emby-checkbox', 'emby-select', 'emb
|
||||
});
|
||||
}
|
||||
|
||||
function editor() {
|
||||
this.show = function (itemType, options, availableOptions) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', 'components/imageOptionsEditor/imageOptionsEditor.template.html', true);
|
||||
async function showEditor(itemType, options, availableOptions) {
|
||||
const response = await fetch('components/imageOptionsEditor/imageOptionsEditor.template.html');
|
||||
const template = await response.text();
|
||||
|
||||
xhr.onload = function (e) {
|
||||
var template = this.response;
|
||||
var dlg = dialogHelper.createDialog({
|
||||
size: 'small',
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
});
|
||||
dlg.classList.add('formDialog');
|
||||
dlg.innerHTML = globalize.translateDocument(template);
|
||||
dlg.addEventListener('close', function () {
|
||||
saveValues(dlg, options);
|
||||
});
|
||||
loadValues(dlg, itemType, options, availableOptions);
|
||||
dialogHelper.open(dlg).then(resolve, resolve);
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', function () {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
};
|
||||
|
||||
xhr.send();
|
||||
});
|
||||
};
|
||||
var dlg = dialogHelper.createDialog({
|
||||
size: 'small',
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
});
|
||||
dlg.classList.add('formDialog');
|
||||
dlg.innerHTML = globalize.translateHtml(template);
|
||||
dlg.addEventListener('close', function () {
|
||||
saveValues(dlg, options);
|
||||
});
|
||||
loadValues(dlg, itemType, options, availableOptions);
|
||||
dialogHelper.open(dlg).then(() => {
|
||||
return;
|
||||
}).catch(() => {
|
||||
return;
|
||||
});
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', function () {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
}
|
||||
|
||||
return editor;
|
||||
});
|
||||
export class editor {
|
||||
constructor() {
|
||||
this.show = showEditor;
|
||||
}
|
||||
}
|
||||
|
||||
/* eslint-enable indent */
|
||||
export default editor;
|
||||
|
||||
@@ -1,25 +1,40 @@
|
||||
define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', 'layoutManager', 'globalize', 'require', 'emby-button', 'emby-select', 'formDialogStyle', 'css!./style'], function (dialogHelper, connectionManager, dom, loading, scrollHelper, layoutManager, globalize, require) {
|
||||
'use strict';
|
||||
/* eslint-disable indent */
|
||||
|
||||
var currentItemId;
|
||||
var currentServerId;
|
||||
var currentFile;
|
||||
var hasChanges = false;
|
||||
/**
|
||||
* Module for imageUploader.
|
||||
* @module components/imageUploader/imageUploader
|
||||
*/
|
||||
|
||||
import dialogHelper from 'dialogHelper';
|
||||
import connectionManager from 'connectionManager';
|
||||
import dom from 'dom';
|
||||
import loading from 'loading';
|
||||
import scrollHelper from 'scrollHelper';
|
||||
import layoutManager from 'layoutManager';
|
||||
import globalize from 'globalize';
|
||||
import 'emby-button';
|
||||
import 'emby-select';
|
||||
import 'formDialogStyle';
|
||||
import 'css!./style';
|
||||
|
||||
let currentItemId;
|
||||
let currentServerId;
|
||||
let currentFile;
|
||||
let hasChanges = false;
|
||||
|
||||
function onFileReaderError(evt) {
|
||||
|
||||
loading.hide();
|
||||
|
||||
switch (evt.target.error.code) {
|
||||
case evt.target.error.NOT_FOUND_ERR:
|
||||
require(['toast'], function (toast) {
|
||||
import('toast').then(({default: toast}) => {
|
||||
toast(globalize.translate('MessageFileReadError'));
|
||||
});
|
||||
break;
|
||||
case evt.target.error.ABORT_ERR:
|
||||
break; // noop
|
||||
default:
|
||||
require(['toast'], function (toast) {
|
||||
import('toast').then(({default: toast}) => {
|
||||
toast(globalize.translate('MessageFileReadError'));
|
||||
});
|
||||
break;
|
||||
@@ -27,8 +42,7 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
|
||||
}
|
||||
|
||||
function setFiles(page, files) {
|
||||
|
||||
var file = files[0];
|
||||
const file = files[0];
|
||||
|
||||
if (!file || !file.type.match('image.*')) {
|
||||
page.querySelector('#imageOutput').innerHTML = '';
|
||||
@@ -39,23 +53,22 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
|
||||
|
||||
currentFile = file;
|
||||
|
||||
var reader = new FileReader();
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onerror = onFileReaderError;
|
||||
reader.onloadstart = function () {
|
||||
reader.onloadstart = () => {
|
||||
page.querySelector('#fldUpload').classList.add('hide');
|
||||
};
|
||||
reader.onabort = function () {
|
||||
reader.onabort = () => {
|
||||
loading.hide();
|
||||
console.debug('File read cancelled');
|
||||
};
|
||||
|
||||
// Closure to capture the file information.
|
||||
reader.onload = (function (theFile) {
|
||||
return function (e) {
|
||||
|
||||
reader.onload = (theFile => {
|
||||
return e => {
|
||||
// Render thumbnail.
|
||||
var html = ['<img style="max-width:100%;max-height:100%;" src="', e.target.result, '" title="', escape(theFile.name), '"/>'].join('');
|
||||
const html = ['<img style="max-width:100%;max-height:100%;" src="', e.target.result, '" title="', escape(theFile.name), '"/>'].join('');
|
||||
|
||||
page.querySelector('#imageOutput').innerHTML = html;
|
||||
page.querySelector('#dropImageText').classList.add('hide');
|
||||
@@ -68,15 +81,14 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
|
||||
}
|
||||
|
||||
function onSubmit(e) {
|
||||
|
||||
var file = currentFile;
|
||||
const file = currentFile;
|
||||
|
||||
if (!file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file.type.startsWith('image/')) {
|
||||
require(['toast'], function (toast) {
|
||||
import('toast').then(({default: toast}) => {
|
||||
toast(globalize.translate('MessageImageFileTypeAllowed'));
|
||||
});
|
||||
e.preventDefault();
|
||||
@@ -85,19 +97,18 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
|
||||
|
||||
loading.show();
|
||||
|
||||
var dlg = dom.parentWithClass(this, 'dialog');
|
||||
const dlg = dom.parentWithClass(this, 'dialog');
|
||||
|
||||
var imageType = dlg.querySelector('#selectImageType').value;
|
||||
const imageType = dlg.querySelector('#selectImageType').value;
|
||||
if (imageType === 'None') {
|
||||
require(['toast'], function(toast) {
|
||||
import('toast').then(({default: toast}) => {
|
||||
toast(globalize.translate('MessageImageTypeNotSelected'));
|
||||
});
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
connectionManager.getApiClient(currentServerId).uploadItemImage(currentItemId, imageType, file).then(function () {
|
||||
|
||||
connectionManager.getApiClient(currentServerId).uploadItemImage(currentItemId, imageType, file).then(() => {
|
||||
dlg.querySelector('#uploadImage').value = '';
|
||||
|
||||
loading.hide();
|
||||
@@ -110,28 +121,25 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
|
||||
}
|
||||
|
||||
function initEditor(page) {
|
||||
|
||||
page.querySelector('form').addEventListener('submit', onSubmit);
|
||||
|
||||
page.querySelector('#uploadImage').addEventListener('change', function () {
|
||||
setFiles(page, this.files);
|
||||
});
|
||||
|
||||
page.querySelector('.btnBrowse').addEventListener('click', function () {
|
||||
page.querySelector('.btnBrowse').addEventListener('click', () => {
|
||||
page.querySelector('#uploadImage').click();
|
||||
});
|
||||
}
|
||||
|
||||
function showEditor(options, resolve, reject) {
|
||||
|
||||
function showEditor(options, resolve) {
|
||||
options = options || {};
|
||||
|
||||
require(['text!./imageUploader.template.html'], function (template) {
|
||||
|
||||
return import('text!./imageUploader.template.html').then(({default: template}) => {
|
||||
currentItemId = options.itemId;
|
||||
currentServerId = options.serverId;
|
||||
|
||||
var dialogOptions = {
|
||||
const dialogOptions = {
|
||||
removeOnClose: true
|
||||
};
|
||||
|
||||
@@ -141,19 +149,18 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
|
||||
dialogOptions.size = 'small';
|
||||
}
|
||||
|
||||
var dlg = dialogHelper.createDialog(dialogOptions);
|
||||
const dlg = dialogHelper.createDialog(dialogOptions);
|
||||
|
||||
dlg.classList.add('formDialog');
|
||||
|
||||
dlg.innerHTML = globalize.translateDocument(template, 'core');
|
||||
dlg.innerHTML = globalize.translateHtml(template, 'core');
|
||||
|
||||
if (layoutManager.tv) {
|
||||
scrollHelper.centerFocus.on(dlg, false);
|
||||
}
|
||||
|
||||
// Has to be assigned a z-index after the call to .open()
|
||||
dlg.addEventListener('close', function () {
|
||||
|
||||
dlg.addEventListener('close', () => {
|
||||
if (layoutManager.tv) {
|
||||
scrollHelper.centerFocus.off(dlg, false);
|
||||
}
|
||||
@@ -168,22 +175,21 @@ define(['dialogHelper', 'connectionManager', 'dom', 'loading', 'scrollHelper', '
|
||||
|
||||
dlg.querySelector('#selectImageType').value = options.imageType || 'Primary';
|
||||
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', function () {
|
||||
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', () => {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
show: function (options) {
|
||||
export function show(options) {
|
||||
return new Promise(resolve => {
|
||||
hasChanges = false;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
showEditor(options, resolve);
|
||||
});
|
||||
}
|
||||
|
||||
hasChanges = false;
|
||||
|
||||
showEditor(options, resolve, reject);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
/* eslint-enable indent */
|
||||
export default {
|
||||
show: show
|
||||
};
|
||||
|
||||
@@ -1,14 +1,29 @@
|
||||
define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager', 'focusManager', 'globalize', 'scrollHelper', 'imageLoader', 'require', 'browser', 'apphost', 'cardStyle', 'formDialogStyle', 'emby-button', 'paper-icon-button-light', 'css!./imageeditor'], function (dialogHelper, connectionManager, loading, dom, layoutManager, focusManager, globalize, scrollHelper, imageLoader, require, browser, appHost) {
|
||||
'use strict';
|
||||
import dialogHelper from 'dialogHelper';
|
||||
import connectionManager from 'connectionManager';
|
||||
import loading from 'loading';
|
||||
import dom from 'dom';
|
||||
import layoutManager from 'layoutManager';
|
||||
import focusManager from 'focusManager';
|
||||
import globalize from 'globalize';
|
||||
import scrollHelper from 'scrollHelper';
|
||||
import imageLoader from 'imageLoader';
|
||||
import browser from 'browser';
|
||||
import appHost from 'apphost';
|
||||
import 'cardStyle';
|
||||
import 'formDialogStyle';
|
||||
import 'emby-button';
|
||||
import 'paper-icon-button-light';
|
||||
import 'css!./imageeditor';
|
||||
|
||||
var enableFocusTransform = !browser.slow && !browser.edge;
|
||||
/* eslint-disable indent */
|
||||
|
||||
var currentItem;
|
||||
var hasChanges = false;
|
||||
const enableFocusTransform = !browser.slow && !browser.edge;
|
||||
|
||||
let currentItem;
|
||||
let hasChanges = false;
|
||||
|
||||
function getBaseRemoteOptions() {
|
||||
|
||||
var options = {};
|
||||
const options = {};
|
||||
|
||||
options.itemId = currentItem.Id;
|
||||
|
||||
@@ -16,16 +31,14 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
}
|
||||
|
||||
function reload(page, item, focusContext) {
|
||||
|
||||
loading.show();
|
||||
|
||||
var apiClient;
|
||||
let apiClient;
|
||||
|
||||
if (item) {
|
||||
apiClient = connectionManager.getApiClient(item.ServerId);
|
||||
reloadItem(page, item, apiClient, focusContext);
|
||||
} else {
|
||||
|
||||
apiClient = connectionManager.getApiClient(currentItem.ServerId);
|
||||
apiClient.getItem(apiClient.getCurrentUserId(), currentItem.Id).then(function (item) {
|
||||
reloadItem(page, item, apiClient, focusContext);
|
||||
@@ -34,9 +47,8 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
}
|
||||
|
||||
function addListeners(container, className, eventName, fn) {
|
||||
|
||||
container.addEventListener(eventName, function (e) {
|
||||
var elem = dom.parentWithClass(e.target, className);
|
||||
const elem = dom.parentWithClass(e.target, className);
|
||||
if (elem) {
|
||||
fn.call(elem, e);
|
||||
}
|
||||
@@ -44,14 +56,11 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
}
|
||||
|
||||
function reloadItem(page, item, apiClient, focusContext) {
|
||||
|
||||
currentItem = item;
|
||||
|
||||
apiClient.getRemoteImageProviders(getBaseRemoteOptions()).then(function (providers) {
|
||||
|
||||
var btnBrowseAllImages = page.querySelectorAll('.btnBrowseAllImages');
|
||||
for (var i = 0, length = btnBrowseAllImages.length; i < length; i++) {
|
||||
|
||||
const btnBrowseAllImages = page.querySelectorAll('.btnBrowseAllImages');
|
||||
for (let i = 0, length = btnBrowseAllImages.length; i < length; i++) {
|
||||
if (providers.length) {
|
||||
btnBrowseAllImages[i].classList.remove('hide');
|
||||
} else {
|
||||
@@ -60,7 +69,6 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
}
|
||||
|
||||
apiClient.getItemImageInfos(currentItem.Id).then(function (imageInfos) {
|
||||
|
||||
renderStandardImages(page, apiClient, item, imageInfos, providers);
|
||||
renderBackdrops(page, apiClient, item, imageInfos, providers);
|
||||
renderScreenshots(page, apiClient, item, imageInfos, providers);
|
||||
@@ -74,7 +82,6 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
}
|
||||
|
||||
function getImageUrl(item, apiClient, type, index, options) {
|
||||
|
||||
options = options || {};
|
||||
options.type = type;
|
||||
options.index = index;
|
||||
@@ -94,13 +101,12 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
}
|
||||
|
||||
function getCardHtml(image, index, numImages, apiClient, imageProviders, imageSize, tagName, enableFooterButtons) {
|
||||
|
||||
// TODO move card creation code to Card component
|
||||
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
var cssClass = 'card scalableCard imageEditorCard';
|
||||
var cardBoxCssClass = 'cardBox visualCardBox';
|
||||
let cssClass = 'card scalableCard imageEditorCard';
|
||||
const cardBoxCssClass = 'cardBox visualCardBox';
|
||||
|
||||
cssClass += ' backdropCard backdropCard-scalable';
|
||||
|
||||
@@ -130,7 +136,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
|
||||
html += '<div class="cardContent">';
|
||||
|
||||
var imageUrl = getImageUrl(currentItem, apiClient, image.ImageType, image.ImageIndex, { maxWidth: imageSize });
|
||||
const imageUrl = getImageUrl(currentItem, apiClient, image.ImageType, image.ImageIndex, { maxWidth: imageSize });
|
||||
|
||||
html += '<div class="cardImageContainer" style="background-image:url(\'' + imageUrl + '\');background-position:center center;background-size:contain;"></div>';
|
||||
|
||||
@@ -153,7 +159,6 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
html += '<div class="cardText cardTextCentered">';
|
||||
|
||||
if (image.ImageType === 'Backdrop' || image.ImageType === 'Screenshot') {
|
||||
|
||||
if (index > 0) {
|
||||
html += '<button type="button" is="paper-icon-button-light" class="btnMoveImage autoSize" data-imagetype="' + image.ImageType + '" data-index="' + image.ImageIndex + '" data-newindex="' + (image.ImageIndex - 1) + '" title="' + globalize.translate('MoveLeft') + '"><span class="material-icons chevron_left"></span></button>';
|
||||
} else {
|
||||
@@ -183,13 +188,10 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
}
|
||||
|
||||
function deleteImage(context, itemId, type, index, apiClient, enableConfirmation) {
|
||||
|
||||
var afterConfirm = function () {
|
||||
const afterConfirm = function () {
|
||||
apiClient.deleteItemImage(itemId, type, index).then(function () {
|
||||
|
||||
hasChanges = true;
|
||||
reload(context);
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
@@ -198,8 +200,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
return;
|
||||
}
|
||||
|
||||
require(['confirm'], function (confirm) {
|
||||
|
||||
import('confirm').then(({default: confirm}) => {
|
||||
confirm({
|
||||
|
||||
text: globalize.translate('ConfirmDeleteImage'),
|
||||
@@ -211,36 +212,30 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
}
|
||||
|
||||
function moveImage(context, apiClient, itemId, type, index, newIndex, focusContext) {
|
||||
|
||||
apiClient.updateItemImageIndex(itemId, type, index, newIndex).then(function () {
|
||||
|
||||
hasChanges = true;
|
||||
reload(context, null, focusContext);
|
||||
}, function () {
|
||||
|
||||
require(['alert'], function (alert) {
|
||||
import('alert').then(({default: alert}) => {
|
||||
alert(globalize.translate('DefaultErrorMessage'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function renderImages(page, item, apiClient, images, imageProviders, elem) {
|
||||
let html = '';
|
||||
|
||||
var html = '';
|
||||
|
||||
var imageSize = 300;
|
||||
var windowSize = dom.getWindowSize();
|
||||
let imageSize = 300;
|
||||
const windowSize = dom.getWindowSize();
|
||||
if (windowSize.innerWidth >= 1280) {
|
||||
imageSize = Math.round(windowSize.innerWidth / 4);
|
||||
}
|
||||
|
||||
var tagName = layoutManager.tv ? 'button' : 'div';
|
||||
var enableFooterButtons = !layoutManager.tv;
|
||||
|
||||
for (var i = 0, length = images.length; i < length; i++) {
|
||||
|
||||
var image = images[i];
|
||||
const tagName = layoutManager.tv ? 'button' : 'div';
|
||||
const enableFooterButtons = !layoutManager.tv;
|
||||
|
||||
for (let i = 0, length = images.length; i < length; i++) {
|
||||
const image = images[i];
|
||||
html += getCardHtml(image, i, length, apiClient, imageProviders, imageSize, tagName, enableFooterButtons);
|
||||
}
|
||||
|
||||
@@ -249,8 +244,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
}
|
||||
|
||||
function renderStandardImages(page, apiClient, item, imageInfos, imageProviders) {
|
||||
|
||||
var images = imageInfos.filter(function (i) {
|
||||
const images = imageInfos.filter(function (i) {
|
||||
return i.ImageType !== 'Screenshot' && i.ImageType !== 'Backdrop' && i.ImageType !== 'Chapter';
|
||||
});
|
||||
|
||||
@@ -258,10 +252,8 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
}
|
||||
|
||||
function renderBackdrops(page, apiClient, item, imageInfos, imageProviders) {
|
||||
|
||||
var images = imageInfos.filter(function (i) {
|
||||
const images = imageInfos.filter(function (i) {
|
||||
return i.ImageType === 'Backdrop';
|
||||
|
||||
}).sort(function (a, b) {
|
||||
return a.ImageIndex - b.ImageIndex;
|
||||
});
|
||||
@@ -275,10 +267,8 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
}
|
||||
|
||||
function renderScreenshots(page, apiClient, item, imageInfos, imageProviders) {
|
||||
|
||||
var images = imageInfos.filter(function (i) {
|
||||
const images = imageInfos.filter(function (i) {
|
||||
return i.ImageType === 'Screenshot';
|
||||
|
||||
}).sort(function (a, b) {
|
||||
return a.ImageIndex - b.ImageIndex;
|
||||
});
|
||||
@@ -292,32 +282,26 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
}
|
||||
|
||||
function showImageDownloader(page, imageType) {
|
||||
|
||||
require(['imageDownloader'], function (ImageDownloader) {
|
||||
|
||||
import('imageDownloader').then(({default: ImageDownloader}) => {
|
||||
ImageDownloader.show(currentItem.Id, currentItem.ServerId, currentItem.Type, imageType).then(function () {
|
||||
|
||||
hasChanges = true;
|
||||
reload(page);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function showActionSheet(context, imageCard) {
|
||||
const itemId = imageCard.getAttribute('data-id');
|
||||
const serverId = imageCard.getAttribute('data-serverid');
|
||||
const apiClient = connectionManager.getApiClient(serverId);
|
||||
|
||||
var itemId = imageCard.getAttribute('data-id');
|
||||
var serverId = imageCard.getAttribute('data-serverid');
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
const type = imageCard.getAttribute('data-imagetype');
|
||||
const index = parseInt(imageCard.getAttribute('data-index'));
|
||||
const providerCount = parseInt(imageCard.getAttribute('data-providers'));
|
||||
const numImages = parseInt(imageCard.getAttribute('data-numimages'));
|
||||
|
||||
var type = imageCard.getAttribute('data-imagetype');
|
||||
var index = parseInt(imageCard.getAttribute('data-index'));
|
||||
var providerCount = parseInt(imageCard.getAttribute('data-providers'));
|
||||
var numImages = parseInt(imageCard.getAttribute('data-numimages'));
|
||||
|
||||
require(['actionsheet'], function (actionSheet) {
|
||||
|
||||
var commands = [];
|
||||
import('actionsheet').then(({default: actionSheet}) => {
|
||||
const commands = [];
|
||||
|
||||
commands.push({
|
||||
name: globalize.translate('Delete'),
|
||||
@@ -353,9 +337,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
positionTo: imageCard
|
||||
|
||||
}).then(function (id) {
|
||||
|
||||
switch (id) {
|
||||
|
||||
case 'delete':
|
||||
deleteImage(context, itemId, type, index, apiClient, false);
|
||||
break;
|
||||
@@ -371,16 +353,14 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function initEditor(context, options) {
|
||||
|
||||
var uploadButtons = context.querySelectorAll('.btnOpenUploadMenu');
|
||||
var isFileInputSupported = appHost.supports('fileinput');
|
||||
for (var i = 0, length = uploadButtons.length; i < length; i++) {
|
||||
const uploadButtons = context.querySelectorAll('.btnOpenUploadMenu');
|
||||
const isFileInputSupported = appHost.supports('fileinput');
|
||||
for (let i = 0, length = uploadButtons.length; i < length; i++) {
|
||||
if (isFileInputSupported) {
|
||||
uploadButtons[i].classList.remove('hide');
|
||||
} else {
|
||||
@@ -389,10 +369,9 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
}
|
||||
|
||||
addListeners(context, 'btnOpenUploadMenu', 'click', function () {
|
||||
var imageType = this.getAttribute('data-imagetype');
|
||||
|
||||
require(['imageUploader'], function (imageUploader) {
|
||||
const imageType = this.getAttribute('data-imagetype');
|
||||
|
||||
import('imageUploader').then(({default: imageUploader}) => {
|
||||
imageUploader.show({
|
||||
|
||||
theme: options.theme,
|
||||
@@ -401,7 +380,6 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
serverId: currentItem.ServerId
|
||||
|
||||
}).then(function (hasChanged) {
|
||||
|
||||
if (hasChanged) {
|
||||
hasChanges = true;
|
||||
reload(context);
|
||||
@@ -423,34 +401,32 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
});
|
||||
|
||||
addListeners(context, 'btnDeleteImage', 'click', function () {
|
||||
var type = this.getAttribute('data-imagetype');
|
||||
var index = this.getAttribute('data-index');
|
||||
const type = this.getAttribute('data-imagetype');
|
||||
let index = this.getAttribute('data-index');
|
||||
index = index === 'null' ? null : parseInt(index);
|
||||
var apiClient = connectionManager.getApiClient(currentItem.ServerId);
|
||||
const apiClient = connectionManager.getApiClient(currentItem.ServerId);
|
||||
deleteImage(context, currentItem.Id, type, index, apiClient, true);
|
||||
});
|
||||
|
||||
addListeners(context, 'btnMoveImage', 'click', function () {
|
||||
var type = this.getAttribute('data-imagetype');
|
||||
var index = this.getAttribute('data-index');
|
||||
var newIndex = this.getAttribute('data-newindex');
|
||||
var apiClient = connectionManager.getApiClient(currentItem.ServerId);
|
||||
const type = this.getAttribute('data-imagetype');
|
||||
const index = this.getAttribute('data-index');
|
||||
const newIndex = this.getAttribute('data-newindex');
|
||||
const apiClient = connectionManager.getApiClient(currentItem.ServerId);
|
||||
moveImage(context, apiClient, currentItem.Id, type, index, newIndex, dom.parentWithClass(this, 'itemsContainer'));
|
||||
});
|
||||
}
|
||||
|
||||
function showEditor(options, resolve, reject) {
|
||||
|
||||
var itemId = options.itemId;
|
||||
var serverId = options.serverId;
|
||||
const itemId = options.itemId;
|
||||
const serverId = options.serverId;
|
||||
|
||||
loading.show();
|
||||
|
||||
require(['text!./imageeditor.template.html'], function (template) {
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
import('text!./imageeditor.template.html').then(({default: template}) => {
|
||||
const apiClient = connectionManager.getApiClient(serverId);
|
||||
apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) {
|
||||
|
||||
var dialogOptions = {
|
||||
const dialogOptions = {
|
||||
removeOnClose: true
|
||||
};
|
||||
|
||||
@@ -460,11 +436,11 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
dialogOptions.size = 'small';
|
||||
}
|
||||
|
||||
var dlg = dialogHelper.createDialog(dialogOptions);
|
||||
const dlg = dialogHelper.createDialog(dialogOptions);
|
||||
|
||||
dlg.classList.add('formDialog');
|
||||
|
||||
dlg.innerHTML = globalize.translateDocument(template, 'core');
|
||||
dlg.innerHTML = globalize.translateHtml(template, 'core');
|
||||
|
||||
if (layoutManager.tv) {
|
||||
scrollHelper.centerFocus.on(dlg, false);
|
||||
@@ -474,7 +450,6 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
|
||||
// Has to be assigned a z-index after the call to .open()
|
||||
dlg.addEventListener('close', function () {
|
||||
|
||||
if (layoutManager.tv) {
|
||||
scrollHelper.centerFocus.off(dlg, false);
|
||||
}
|
||||
@@ -493,22 +468,21 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
|
||||
reload(dlg, item);
|
||||
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', function () {
|
||||
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
show: function (options) {
|
||||
export function show (options) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
hasChanges = false;
|
||||
showEditor(options, resolve, reject);
|
||||
});
|
||||
}
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
export default {
|
||||
show
|
||||
};
|
||||
|
||||
hasChanges = false;
|
||||
|
||||
showEditor(options, resolve, reject);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
/* eslint-enable indent */
|
||||
|
||||
@@ -120,7 +120,7 @@ import 'css!./style';
|
||||
|
||||
export function lazyChildren(elem) {
|
||||
if (userSettings.enableBlurhash()) {
|
||||
for (const lazyElem of elem.getElementsByClassName('lazy')) {
|
||||
for (const lazyElem of elem.querySelectorAll('.lazy')) {
|
||||
const blurhashstr = lazyElem.getAttribute('data-blurhash');
|
||||
if (!lazyElem.classList.contains('blurhashed', 'non-blurhashable') && blurhashstr) {
|
||||
itemBlurhashing(lazyElem, blurhashstr);
|
||||
@@ -133,11 +133,9 @@ import 'css!./style';
|
||||
}
|
||||
|
||||
export function getPrimaryImageAspectRatio(items) {
|
||||
|
||||
var values = [];
|
||||
|
||||
for (var i = 0, length = items.length; i < length; i++) {
|
||||
|
||||
var ratio = items[i].PrimaryImageAspectRatio || 0;
|
||||
|
||||
if (!ratio) {
|
||||
@@ -193,7 +191,6 @@ import 'css!./style';
|
||||
}
|
||||
|
||||
export function fillImages(elems) {
|
||||
|
||||
for (var i = 0, length = elems.length; i < length; i++) {
|
||||
var elem = elems[0];
|
||||
fillImage(elem);
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter', 'playbackManager', 'loading', 'appSettings', 'browser', 'actionsheet'], function (appHost, globalize, connectionManager, itemHelper, appRouter, playbackManager, loading, appSettings, browser, actionsheet) {
|
||||
'use strict';
|
||||
import appHost from 'apphost';
|
||||
import globalize from 'globalize';
|
||||
import connectionManager from 'connectionManager';
|
||||
import itemHelper from 'itemHelper';
|
||||
import appRouter from 'appRouter';
|
||||
import playbackManager from 'playbackManager';
|
||||
import browser from 'browser';
|
||||
import actionsheet from 'actionsheet';
|
||||
|
||||
function getCommands(options) {
|
||||
var item = options.item;
|
||||
var user = options.user;
|
||||
/* eslint-disable indent */
|
||||
|
||||
var canPlay = playbackManager.canPlay(item);
|
||||
var restrictOptions = (browser.operaTv || browser.web0s) && !user.Policy.IsAdministrator;
|
||||
export function getCommands(options) {
|
||||
const item = options.item;
|
||||
const user = options.user;
|
||||
|
||||
var commands = [];
|
||||
const canPlay = playbackManager.canPlay(item);
|
||||
const restrictOptions = (browser.operaTv || browser.web0s) && !user.Policy.IsAdministrator;
|
||||
|
||||
let commands = [];
|
||||
|
||||
if (canPlay && item.MediaType !== 'Photo') {
|
||||
if (options.play !== false) {
|
||||
@@ -134,7 +142,6 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
||||
}
|
||||
|
||||
if (item.CanDelete && options.deleteItem !== false) {
|
||||
|
||||
if (item.Type === 'Playlist' || item.Type === 'BoxSet') {
|
||||
commands.push({
|
||||
name: globalize.translate('Delete'),
|
||||
@@ -171,10 +178,10 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
||||
});
|
||||
}
|
||||
|
||||
var canEdit = itemHelper.canEdit(user, item);
|
||||
const canEdit = itemHelper.canEdit(user, item);
|
||||
if (canEdit) {
|
||||
if (options.edit !== false && item.Type !== 'SeriesTimer') {
|
||||
var text = (item.Type === 'Timer' || item.Type === 'SeriesTimer') ? globalize.translate('Edit') : globalize.translate('EditMetadata');
|
||||
const text = (item.Type === 'Timer' || item.Type === 'SeriesTimer') ? globalize.translate('Edit') : globalize.translate('EditMetadata');
|
||||
commands.push({
|
||||
name: text,
|
||||
id: 'edit',
|
||||
@@ -322,31 +329,31 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
||||
}
|
||||
|
||||
function executeCommand(item, id, options) {
|
||||
var itemId = item.Id;
|
||||
var serverId = item.ServerId;
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
const itemId = item.Id;
|
||||
const serverId = item.ServerId;
|
||||
const apiClient = connectionManager.getApiClient(serverId);
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
switch (id) {
|
||||
case 'addtocollection':
|
||||
require(['collectionEditor'], function (collectionEditor) {
|
||||
new collectionEditor().show({
|
||||
import('collectionEditor').then(({default: collectionEditor}) => {
|
||||
new collectionEditor({
|
||||
items: [itemId],
|
||||
serverId: serverId
|
||||
}).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
||||
});
|
||||
break;
|
||||
case 'addtoplaylist':
|
||||
require(['playlistEditor'], function (playlistEditor) {
|
||||
new playlistEditor().show({
|
||||
import('playlistEditor').then(({default: playlistEditor}) => {
|
||||
new playlistEditor({
|
||||
items: [itemId],
|
||||
serverId: serverId
|
||||
}).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
||||
});
|
||||
break;
|
||||
case 'download':
|
||||
require(['fileDownloader'], function (fileDownloader) {
|
||||
var downloadHref = apiClient.getItemDownloadUrl(itemId);
|
||||
import('fileDownloader').then((fileDownloader) => {
|
||||
const downloadHref = apiClient.getItemDownloadUrl(itemId);
|
||||
fileDownloader.download([{
|
||||
url: downloadHref,
|
||||
itemId: itemId,
|
||||
@@ -357,17 +364,17 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
||||
getResolveFunction(getResolveFunction(resolve, id), id)();
|
||||
});
|
||||
break;
|
||||
case 'copy-stream':
|
||||
var downloadHref = apiClient.getItemDownloadUrl(itemId);
|
||||
var textAreaCopy = function () {
|
||||
var textArea = document.createElement('textarea');
|
||||
case 'copy-stream': {
|
||||
const downloadHref = apiClient.getItemDownloadUrl(itemId);
|
||||
const textAreaCopy = function () {
|
||||
let textArea = document.createElement('textarea');
|
||||
textArea.value = downloadHref;
|
||||
document.body.appendChild(textArea);
|
||||
textArea.focus();
|
||||
textArea.select();
|
||||
|
||||
if (document.execCommand('copy')) {
|
||||
require(['toast'], function (toast) {
|
||||
import('toast').then(({default: toast}) => {
|
||||
toast(globalize.translate('CopyStreamURLSuccess'));
|
||||
});
|
||||
} else {
|
||||
@@ -382,7 +389,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
||||
} else {
|
||||
/* eslint-disable-next-line compat/compat */
|
||||
navigator.clipboard.writeText(downloadHref).then(function () {
|
||||
require(['toast'], function (toast) {
|
||||
import('toast').then(({default: toast}) => {
|
||||
toast(globalize.translate('CopyStreamURLSuccess'));
|
||||
});
|
||||
}).catch(function () {
|
||||
@@ -391,8 +398,9 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
||||
}
|
||||
getResolveFunction(resolve, id)();
|
||||
break;
|
||||
}
|
||||
case 'editsubtitles':
|
||||
require(['subtitleEditor'], function (subtitleEditor) {
|
||||
import('subtitleEditor').then(({default: subtitleEditor}) => {
|
||||
subtitleEditor.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
||||
});
|
||||
break;
|
||||
@@ -400,7 +408,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
||||
editItem(apiClient, item).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
||||
break;
|
||||
case 'editimages':
|
||||
require(['imageEditor'], function (imageEditor) {
|
||||
import('imageEditor').then(({default: imageEditor}) => {
|
||||
imageEditor.show({
|
||||
itemId: itemId,
|
||||
serverId: serverId
|
||||
@@ -408,12 +416,12 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
||||
});
|
||||
break;
|
||||
case 'identify':
|
||||
require(['itemIdentifier'], function (itemIdentifier) {
|
||||
import('itemIdentifier').then(({default: itemIdentifier}) => {
|
||||
itemIdentifier.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
||||
});
|
||||
break;
|
||||
case 'moremediainfo':
|
||||
require(['itemMediaInfo'], function (itemMediaInfo) {
|
||||
import('itemMediaInfo').then(({default: itemMediaInfo}) => {
|
||||
itemMediaInfo.show(itemId, serverId).then(getResolveFunction(resolve, id), getResolveFunction(resolve, id));
|
||||
});
|
||||
break;
|
||||
@@ -448,7 +456,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
||||
playbackManager.clearQueue();
|
||||
break;
|
||||
case 'record':
|
||||
require(['recordingCreator'], function (recordingCreator) {
|
||||
import('recordingCreator').then(({default: recordingCreator}) => {
|
||||
recordingCreator.show(itemId, serverId).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id));
|
||||
});
|
||||
break;
|
||||
@@ -519,8 +527,8 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
||||
}
|
||||
|
||||
function deleteTimer(apiClient, item, resolve, command) {
|
||||
require(['recordingHelper'], function (recordingHelper) {
|
||||
var timerId = item.TimerId || item.Id;
|
||||
import('recordingHelper').then(({default: recordingHelper}) => {
|
||||
const timerId = item.TimerId || item.Id;
|
||||
recordingHelper.cancelTimerWithConfirmation(timerId, item.ServerId).then(function () {
|
||||
getResolveFunction(resolve, command, true)();
|
||||
});
|
||||
@@ -528,7 +536,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
||||
}
|
||||
|
||||
function deleteSeriesTimer(apiClient, item, resolve, command) {
|
||||
require(['recordingHelper'], function (recordingHelper) {
|
||||
import('recordingHelper').then(({default: recordingHelper}) => {
|
||||
recordingHelper.cancelSeriesTimerWithConfirmation(item.Id, item.ServerId).then(function () {
|
||||
getResolveFunction(resolve, command, true)();
|
||||
});
|
||||
@@ -536,9 +544,9 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
||||
}
|
||||
|
||||
function play(item, resume, queue, queueNext) {
|
||||
var method = queue ? (queueNext ? 'queueNext' : 'queue') : 'play';
|
||||
const method = queue ? (queueNext ? 'queueNext' : 'queue') : 'play';
|
||||
|
||||
var startPosition = 0;
|
||||
let startPosition = 0;
|
||||
if (resume && item.UserData && item.UserData.PlaybackPositionTicks) {
|
||||
startPosition = item.UserData.PlaybackPositionTicks;
|
||||
}
|
||||
@@ -559,18 +567,18 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
||||
|
||||
function editItem(apiClient, item) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var serverId = apiClient.serverInfo().Id;
|
||||
const serverId = apiClient.serverInfo().Id;
|
||||
|
||||
if (item.Type === 'Timer') {
|
||||
require(['recordingEditor'], function (recordingEditor) {
|
||||
import('recordingEditor').then(({default: recordingEditor}) => {
|
||||
recordingEditor.show(item.Id, serverId).then(resolve, reject);
|
||||
});
|
||||
} else if (item.Type === 'SeriesTimer') {
|
||||
require(['seriesRecordingEditor'], function (recordingEditor) {
|
||||
import('seriesRecordingEditor').then(({default: recordingEditor}) => {
|
||||
recordingEditor.show(item.Id, serverId).then(resolve, reject);
|
||||
});
|
||||
} else {
|
||||
require(['metadataEditor'], function (metadataEditor) {
|
||||
import('metadataEditor').then(({default: metadataEditor}) => {
|
||||
metadataEditor.show(item.Id, serverId).then(resolve, reject);
|
||||
});
|
||||
}
|
||||
@@ -579,7 +587,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
||||
|
||||
function deleteItem(apiClient, item) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
require(['deleteHelper'], function (deleteHelper) {
|
||||
import('deleteHelper').then(({default: deleteHelper}) => {
|
||||
deleteHelper.deleteItem({
|
||||
item: item,
|
||||
navigate: false
|
||||
@@ -591,7 +599,7 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
||||
}
|
||||
|
||||
function refresh(apiClient, item) {
|
||||
require(['refreshDialog'], function (refreshDialog) {
|
||||
import('refreshDialog').then(({default: refreshDialog}) => {
|
||||
new refreshDialog({
|
||||
itemIds: [item.Id],
|
||||
serverId: apiClient.serverInfo().Id,
|
||||
@@ -600,8 +608,8 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
||||
});
|
||||
}
|
||||
|
||||
function show(options) {
|
||||
var commands = getCommands(options);
|
||||
export function show(options) {
|
||||
const commands = getCommands(options);
|
||||
if (!commands.length) {
|
||||
return Promise.reject();
|
||||
}
|
||||
@@ -615,8 +623,9 @@ define(['apphost', 'globalize', 'connectionManager', 'itemHelper', 'appRouter',
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
getCommands: getCommands,
|
||||
show: show
|
||||
};
|
||||
});
|
||||
/* eslint-enable indent */
|
||||
|
||||
export default {
|
||||
getCommands: getCommands,
|
||||
show: show
|
||||
};
|
||||
|
||||
@@ -2,7 +2,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
|
||||
'use strict';
|
||||
|
||||
function getDisplayName(item, options = {}) {
|
||||
|
||||
if (!item) {
|
||||
throw new Error('null item passed into getDisplayName');
|
||||
}
|
||||
@@ -22,7 +21,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
|
||||
if (item.Type === 'Episode' && item.ParentIndexNumber === 0) {
|
||||
name = globalize.translate('ValueSpecialEpisodeName', name);
|
||||
} else if ((item.Type === 'Episode' || item.Type === 'Program') && item.IndexNumber != null && item.ParentIndexNumber != null && options.includeIndexNumber !== false) {
|
||||
|
||||
var displayIndexNumber = item.IndexNumber;
|
||||
|
||||
var number = displayIndexNumber;
|
||||
@@ -35,7 +33,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
|
||||
}
|
||||
|
||||
if (item.IndexNumberEnd) {
|
||||
|
||||
displayIndexNumber = item.IndexNumberEnd;
|
||||
number += '-' + displayIndexNumber;
|
||||
}
|
||||
@@ -49,7 +46,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
|
||||
}
|
||||
|
||||
function supportsAddingToCollection(item) {
|
||||
|
||||
var invalidTypes = ['Genre', 'MusicGenre', 'Studio', 'UserView', 'CollectionFolder', 'Audio', 'Program', 'Timer', 'SeriesTimer'];
|
||||
|
||||
if (item.Type === 'Recording') {
|
||||
@@ -62,7 +58,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
|
||||
}
|
||||
|
||||
function supportsAddingToPlaylist(item) {
|
||||
|
||||
if (item.Type === 'Program') {
|
||||
return false;
|
||||
}
|
||||
@@ -96,7 +91,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
|
||||
}
|
||||
|
||||
function canEdit(user, item) {
|
||||
|
||||
var itemType = item.Type;
|
||||
|
||||
if (itemType === 'UserRootFolder' || itemType === 'UserView') {
|
||||
@@ -129,7 +123,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
|
||||
}
|
||||
|
||||
function isLocalItem(item) {
|
||||
|
||||
if (item && item.Id && item.Id.indexOf('local') === 0) {
|
||||
return true;
|
||||
}
|
||||
@@ -144,7 +137,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
|
||||
isLocalItem: isLocalItem,
|
||||
|
||||
canIdentify: function (user, item) {
|
||||
|
||||
var itemType = item.Type;
|
||||
|
||||
if (itemType === 'Movie' ||
|
||||
@@ -156,9 +148,7 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
|
||||
itemType === 'MusicAlbum' ||
|
||||
itemType === 'MusicArtist' ||
|
||||
itemType === 'MusicVideo') {
|
||||
|
||||
if (user.Policy.IsAdministrator) {
|
||||
|
||||
if (!isLocalItem(item)) {
|
||||
return true;
|
||||
}
|
||||
@@ -171,7 +161,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
|
||||
canEdit: canEdit,
|
||||
|
||||
canEditImages: function (user, item) {
|
||||
|
||||
var itemType = item.Type;
|
||||
|
||||
if (item.MediaType === 'Photo') {
|
||||
@@ -180,7 +169,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
|
||||
|
||||
if (itemType === 'UserView') {
|
||||
if (user.Policy.IsAdministrator) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -197,7 +185,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
|
||||
},
|
||||
|
||||
canSync: function (user, item) {
|
||||
|
||||
if (user && !user.Policy.EnableContentDownloading) {
|
||||
return false;
|
||||
}
|
||||
@@ -210,7 +197,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
|
||||
},
|
||||
|
||||
canShare: function (item, user) {
|
||||
|
||||
if (item.Type === 'Program') {
|
||||
return false;
|
||||
}
|
||||
@@ -239,7 +225,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
|
||||
},
|
||||
|
||||
canMarkPlayed: function (item) {
|
||||
|
||||
if (item.Type === 'Program') {
|
||||
return false;
|
||||
}
|
||||
@@ -269,7 +254,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
|
||||
},
|
||||
|
||||
canRate: function (item) {
|
||||
|
||||
if (item.Type === 'Program'
|
||||
|| item.Type === 'Timer'
|
||||
|| item.Type === 'SeriesTimer'
|
||||
@@ -284,7 +268,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
|
||||
},
|
||||
|
||||
canConvert: function (item, user) {
|
||||
|
||||
if (!user.Policy.EnableMediaConversion) {
|
||||
return false;
|
||||
}
|
||||
@@ -320,16 +303,13 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
|
||||
},
|
||||
|
||||
canRefreshMetadata: function (item, user) {
|
||||
|
||||
if (user.Policy.IsAdministrator) {
|
||||
|
||||
var collectionType = item.CollectionType;
|
||||
if (collectionType === 'livetv') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item.Type !== 'Timer' && item.Type !== 'SeriesTimer' && item.Type !== 'Program' && item.Type !== 'TvChannel' && !(item.Type === 'Recording' && item.Status !== 'Completed')) {
|
||||
|
||||
if (!isLocalItem(item)) {
|
||||
return true;
|
||||
}
|
||||
@@ -340,7 +320,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
|
||||
},
|
||||
|
||||
supportsMediaSourceSelection: function (item) {
|
||||
|
||||
if (item.MediaType !== 'Video') {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,44 +1,61 @@
|
||||
define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings', 'connectionManager', 'loading', 'focusManager', 'dom', 'apphost', 'emby-select', 'listViewStyle', 'paper-icon-button-light', 'css!./../formdialog', 'material-icons', 'emby-button', 'flexStyles'], function (dialogHelper, require, layoutManager, globalize, userSettings, connectionManager, loading, focusManager, dom, appHost) {
|
||||
'use strict';
|
||||
/* eslint-disable indent */
|
||||
|
||||
/**
|
||||
* Module for display media info.
|
||||
* @module components/itemMediaInfo/itemMediaInfo
|
||||
*/
|
||||
|
||||
import dialogHelper from 'dialogHelper';
|
||||
import layoutManager from 'layoutManager';
|
||||
import globalize from 'globalize';
|
||||
import connectionManager from 'connectionManager';
|
||||
import loading from 'loading';
|
||||
import 'emby-select';
|
||||
import 'listViewStyle';
|
||||
import 'paper-icon-button-light';
|
||||
import 'css!./../formdialog';
|
||||
import 'material-icons';
|
||||
import 'emby-button';
|
||||
import 'flexStyles';
|
||||
|
||||
function setMediaInfo(user, page, item) {
|
||||
var html = item.MediaSources.map(function (version) {
|
||||
let html = item.MediaSources.map(version => {
|
||||
return getMediaSourceHtml(user, item, version);
|
||||
}).join('<div style="border-top:1px solid #444;margin: 1em 0;"></div>');
|
||||
if (item.MediaSources.length > 1) {
|
||||
html = '<br/>' + html;
|
||||
html = `<br/>${html}`;
|
||||
}
|
||||
var mediaInfoContent = page.querySelector('#mediaInfoContent');
|
||||
const mediaInfoContent = page.querySelector('#mediaInfoContent');
|
||||
mediaInfoContent.innerHTML = html;
|
||||
}
|
||||
|
||||
function getMediaSourceHtml(user, item, version) {
|
||||
var html = '';
|
||||
let html = '';
|
||||
if (version.Name) {
|
||||
html += '<div><h2 class="mediaInfoStreamType">' + version.Name + '</h2></div>';
|
||||
html += `<div><h2 class="mediaInfoStreamType">${version.Name}</h2></div>`;
|
||||
}
|
||||
if (version.Container) {
|
||||
html += createAttribute(globalize.translate('MediaInfoContainer'), version.Container) + '<br/>';
|
||||
html += `${createAttribute(globalize.translate('MediaInfoContainer'), version.Container)}<br/>`;
|
||||
}
|
||||
if (version.Formats && version.Formats.length) {
|
||||
html += createAttribute(globalize.translate('MediaInfoFormat'), version.Formats.join(',')) + '<br/>';
|
||||
html += `${createAttribute(globalize.translate('MediaInfoFormat'), version.Formats.join(','))}<br/>`;
|
||||
}
|
||||
if (version.Path && user && user.Policy.IsAdministrator) {
|
||||
html += createAttribute(globalize.translate('MediaInfoPath'), version.Path) + '<br/>';
|
||||
html += `${createAttribute(globalize.translate('MediaInfoPath'), version.Path)}<br/>`;
|
||||
}
|
||||
if (version.Size) {
|
||||
var size = (version.Size / (1024 * 1024)).toFixed(0) + ' MB';
|
||||
html += createAttribute(globalize.translate('MediaInfoSize'), size) + '<br/>';
|
||||
const size = `${(version.Size / (1024 * 1024)).toFixed(0)} MB`;
|
||||
html += `${createAttribute(globalize.translate('MediaInfoSize'), size)}<br/>`;
|
||||
}
|
||||
for (var i = 0, length = version.MediaStreams.length; i < length; i++) {
|
||||
var stream = version.MediaStreams[i];
|
||||
for (let i = 0, length = version.MediaStreams.length; i < length; i++) {
|
||||
const stream = version.MediaStreams[i];
|
||||
if (stream.Type === 'Data') {
|
||||
continue;
|
||||
}
|
||||
html += '<div class="mediaInfoStream">';
|
||||
var displayType = globalize.translate('MediaInfoStreamType' + stream.Type);
|
||||
html += '<h2 class="mediaInfoStreamType">' + displayType + '</h2>';
|
||||
var attributes = [];
|
||||
const displayType = globalize.translate(`MediaInfoStreamType${stream.Type}`);
|
||||
html += `<h2 class="mediaInfoStreamType">${displayType}</h2>`;
|
||||
const attributes = [];
|
||||
if (stream.DisplayTitle) {
|
||||
attributes.push(createAttribute('Title', stream.DisplayTitle));
|
||||
}
|
||||
@@ -61,7 +78,7 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings',
|
||||
attributes.push(createAttribute(globalize.translate('MediaInfoLevel'), stream.Level));
|
||||
}
|
||||
if (stream.Width || stream.Height) {
|
||||
attributes.push(createAttribute(globalize.translate('MediaInfoResolution'), stream.Width + 'x' + stream.Height));
|
||||
attributes.push(createAttribute(globalize.translate('MediaInfoResolution'), `${stream.Width}x${stream.Height}`));
|
||||
}
|
||||
if (stream.AspectRatio && stream.Codec !== 'mjpeg') {
|
||||
attributes.push(createAttribute(globalize.translate('MediaInfoAspectRatio'), stream.AspectRatio));
|
||||
@@ -79,16 +96,16 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings',
|
||||
attributes.push(createAttribute(globalize.translate('MediaInfoLayout'), stream.ChannelLayout));
|
||||
}
|
||||
if (stream.Channels) {
|
||||
attributes.push(createAttribute(globalize.translate('MediaInfoChannels'), stream.Channels + ' ch'));
|
||||
attributes.push(createAttribute(globalize.translate('MediaInfoChannels'), `${stream.Channels} ch`));
|
||||
}
|
||||
if (stream.BitRate && stream.Codec !== 'mjpeg') {
|
||||
attributes.push(createAttribute(globalize.translate('MediaInfoBitrate'), (parseInt(stream.BitRate / 1000)) + ' kbps'));
|
||||
attributes.push(createAttribute(globalize.translate('MediaInfoBitrate'), `${parseInt(stream.BitRate / 1000)} kbps`));
|
||||
}
|
||||
if (stream.SampleRate) {
|
||||
attributes.push(createAttribute(globalize.translate('MediaInfoSampleRate'), stream.SampleRate + ' Hz'));
|
||||
attributes.push(createAttribute(globalize.translate('MediaInfoSampleRate'), `${stream.SampleRate} Hz`));
|
||||
}
|
||||
if (stream.BitDepth) {
|
||||
attributes.push(createAttribute(globalize.translate('MediaInfoBitDepth'), stream.BitDepth + ' bit'));
|
||||
attributes.push(createAttribute(globalize.translate('MediaInfoBitDepth'), `${stream.BitDepth} bit`));
|
||||
}
|
||||
if (stream.PixelFormat) {
|
||||
attributes.push(createAttribute(globalize.translate('MediaInfoPixelFormat'), stream.PixelFormat));
|
||||
@@ -116,13 +133,13 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings',
|
||||
}
|
||||
|
||||
function createAttribute(label, value) {
|
||||
return '<span class="mediaInfoLabel">' + label + '</span><span class="mediaInfoAttribute">' + value + '</span>';
|
||||
return `<span class="mediaInfoLabel">${label}</span><span class="mediaInfoAttribute">${value}</span>`;
|
||||
}
|
||||
|
||||
function showMediaInfoMore(itemId, serverId, template) {
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
return apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) {
|
||||
var dialogOptions = {
|
||||
function loadMediaInfo(itemId, serverId, template) {
|
||||
const apiClient = connectionManager.getApiClient(serverId);
|
||||
return apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(item => {
|
||||
const dialogOptions = {
|
||||
size: 'small',
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
@@ -130,35 +147,35 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings',
|
||||
if (layoutManager.tv) {
|
||||
dialogOptions.size = 'fullscreen';
|
||||
}
|
||||
var dlg = dialogHelper.createDialog(dialogOptions);
|
||||
const dlg = dialogHelper.createDialog(dialogOptions);
|
||||
dlg.classList.add('formDialog');
|
||||
var html = '';
|
||||
html += globalize.translateDocument(template, 'core');
|
||||
let html = '';
|
||||
html += globalize.translateHtml(template, 'core');
|
||||
dlg.innerHTML = html;
|
||||
if (layoutManager.tv) {
|
||||
dlg.querySelector('.formDialogContent');
|
||||
}
|
||||
dialogHelper.open(dlg);
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', function (e) {
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', () => {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
apiClient.getCurrentUser().then(function (user) {
|
||||
apiClient.getCurrentUser().then(user => {
|
||||
setMediaInfo(user, dlg, item);
|
||||
});
|
||||
loading.hide();
|
||||
});
|
||||
}
|
||||
|
||||
function showMediaInfo(itemId, serverId) {
|
||||
export function show(itemId, serverId) {
|
||||
loading.show();
|
||||
return new Promise(function (resolve, reject) {
|
||||
require(['text!./itemMediaInfo.template.html'], function (template) {
|
||||
showMediaInfoMore(itemId, serverId, template).then(resolve, reject);
|
||||
return import('text!./itemMediaInfo.template.html').then(({default: template}) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
loadMediaInfo(itemId, serverId, template).then(resolve, reject);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
show: showMediaInfo
|
||||
};
|
||||
});
|
||||
/* eslint-enable indent */
|
||||
export default {
|
||||
show: show
|
||||
};
|
||||
|
||||
@@ -1,36 +1,52 @@
|
||||
define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize', 'scrollHelper', 'layoutManager', 'focusManager', 'browser', 'emby-input', 'emby-checkbox', 'paper-icon-button-light', 'css!./../formdialog', 'material-icons', 'cardStyle'], function (dialogHelper, loading, connectionManager, require, globalize, scrollHelper, layoutManager, focusManager, browser) {
|
||||
'use strict';
|
||||
/* eslint-disable indent */
|
||||
|
||||
var enableFocusTransform = !browser.slow && !browser.edge;
|
||||
/**
|
||||
* Module for itemidentifier media item.
|
||||
* @module components/itemidentifier/itemidentifier
|
||||
*/
|
||||
|
||||
var currentItem;
|
||||
var currentItemType;
|
||||
var currentServerId;
|
||||
var currentResolve;
|
||||
var currentReject;
|
||||
var hasChanges = false;
|
||||
var currentSearchResult;
|
||||
import dialogHelper from 'dialogHelper';
|
||||
import loading from 'loading';
|
||||
import connectionManager from 'connectionManager';
|
||||
import globalize from 'globalize';
|
||||
import scrollHelper from 'scrollHelper';
|
||||
import layoutManager from 'layoutManager';
|
||||
import focusManager from 'focusManager';
|
||||
import browser from 'browser';
|
||||
import 'emby-input';
|
||||
import 'emby-checkbox';
|
||||
import 'paper-icon-button-light';
|
||||
import 'css!./../formdialog';
|
||||
import 'material-icons';
|
||||
import 'cardStyle';
|
||||
|
||||
const enableFocusTransform = !browser.slow && !browser.edge;
|
||||
|
||||
let currentItem;
|
||||
let currentItemType;
|
||||
let currentServerId;
|
||||
let currentResolve;
|
||||
let currentReject;
|
||||
let hasChanges = false;
|
||||
let currentSearchResult;
|
||||
|
||||
function getApiClient() {
|
||||
return connectionManager.getApiClient(currentServerId);
|
||||
}
|
||||
|
||||
function searchForIdentificationResults(page) {
|
||||
|
||||
var lookupInfo = {
|
||||
let lookupInfo = {
|
||||
ProviderIds: {}
|
||||
};
|
||||
|
||||
var i;
|
||||
var length;
|
||||
var identifyField = page.querySelectorAll('.identifyField');
|
||||
var value;
|
||||
let i;
|
||||
let length;
|
||||
const identifyField = page.querySelectorAll('.identifyField');
|
||||
let value;
|
||||
for (i = 0, length = identifyField.length; i < length; i++) {
|
||||
|
||||
value = identifyField[i].value;
|
||||
|
||||
if (value) {
|
||||
|
||||
if (identifyField[i].type === 'number') {
|
||||
value = parseInt(value);
|
||||
}
|
||||
@@ -39,11 +55,10 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
|
||||
}
|
||||
}
|
||||
|
||||
var hasId = false;
|
||||
let hasId = false;
|
||||
|
||||
var txtLookupId = page.querySelectorAll('.txtLookupId');
|
||||
const txtLookupId = page.querySelectorAll('.txtLookupId');
|
||||
for (i = 0, length = txtLookupId.length; i < length; i++) {
|
||||
|
||||
value = txtLookupId[i].value;
|
||||
|
||||
if (value) {
|
||||
@@ -53,7 +68,7 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
|
||||
}
|
||||
|
||||
if (!hasId && !lookupInfo.Name) {
|
||||
require(['toast'], function (toast) {
|
||||
import('toast').then(({default: toast}) => {
|
||||
toast(globalize.translate('PleaseEnterNameOrId'));
|
||||
});
|
||||
return;
|
||||
@@ -71,60 +86,54 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
|
||||
|
||||
loading.show();
|
||||
|
||||
var apiClient = getApiClient();
|
||||
const apiClient = getApiClient();
|
||||
|
||||
apiClient.ajax({
|
||||
type: 'POST',
|
||||
url: apiClient.getUrl('Items/RemoteSearch/' + currentItemType),
|
||||
url: apiClient.getUrl(`Items/RemoteSearch/${currentItemType}`),
|
||||
data: JSON.stringify(lookupInfo),
|
||||
contentType: 'application/json',
|
||||
dataType: 'json'
|
||||
|
||||
}).then(function (results) {
|
||||
|
||||
}).then(results => {
|
||||
loading.hide();
|
||||
showIdentificationSearchResults(page, results);
|
||||
});
|
||||
}
|
||||
|
||||
function showIdentificationSearchResults(page, results) {
|
||||
|
||||
var identificationSearchResults = page.querySelector('.identificationSearchResults');
|
||||
const identificationSearchResults = page.querySelector('.identificationSearchResults');
|
||||
|
||||
page.querySelector('.popupIdentifyForm').classList.add('hide');
|
||||
identificationSearchResults.classList.remove('hide');
|
||||
page.querySelector('.identifyOptionsForm').classList.add('hide');
|
||||
page.querySelector('.dialogContentInner').classList.remove('dialog-content-centered');
|
||||
|
||||
var html = '';
|
||||
var i;
|
||||
var length;
|
||||
let html = '';
|
||||
let i;
|
||||
let length;
|
||||
for (i = 0, length = results.length; i < length; i++) {
|
||||
|
||||
var result = results[i];
|
||||
const result = results[i];
|
||||
html += getSearchResultHtml(result, i);
|
||||
}
|
||||
|
||||
var elem = page.querySelector('.identificationSearchResultList');
|
||||
const elem = page.querySelector('.identificationSearchResultList');
|
||||
elem.innerHTML = html;
|
||||
|
||||
function onSearchImageClick() {
|
||||
var index = parseInt(this.getAttribute('data-index'));
|
||||
const index = parseInt(this.getAttribute('data-index'));
|
||||
|
||||
var currentResult = results[index];
|
||||
const currentResult = results[index];
|
||||
|
||||
if (currentItem != null) {
|
||||
|
||||
showIdentifyOptions(page, currentResult);
|
||||
} else {
|
||||
|
||||
finishFindNewDialog(page, currentResult);
|
||||
}
|
||||
}
|
||||
|
||||
var searchImages = elem.querySelectorAll('.card');
|
||||
const searchImages = elem.querySelectorAll('.card');
|
||||
for (i = 0, length = searchImages.length; i < length; i++) {
|
||||
|
||||
searchImages[i].addEventListener('click', onSearchImageClick);
|
||||
}
|
||||
|
||||
@@ -142,8 +151,7 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
|
||||
}
|
||||
|
||||
function showIdentifyOptions(page, identifyResult) {
|
||||
|
||||
var identifyOptionsForm = page.querySelector('.identifyOptionsForm');
|
||||
const identifyOptionsForm = page.querySelector('.identifyOptionsForm');
|
||||
|
||||
page.querySelector('.popupIdentifyForm').classList.add('hide');
|
||||
page.querySelector('.identificationSearchResults').classList.add('hide');
|
||||
@@ -153,19 +161,19 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
|
||||
|
||||
currentSearchResult = identifyResult;
|
||||
|
||||
var lines = [];
|
||||
const lines = [];
|
||||
lines.push(identifyResult.Name);
|
||||
|
||||
if (identifyResult.ProductionYear) {
|
||||
lines.push(identifyResult.ProductionYear);
|
||||
}
|
||||
|
||||
var resultHtml = lines.join('<br/>');
|
||||
let resultHtml = lines.join('<br/>');
|
||||
|
||||
if (identifyResult.ImageUrl) {
|
||||
var displayUrl = getSearchImageDisplayUrl(identifyResult.ImageUrl, identifyResult.SearchProviderName);
|
||||
const displayUrl = getSearchImageDisplayUrl(identifyResult.ImageUrl, identifyResult.SearchProviderName);
|
||||
|
||||
resultHtml = '<div style="display:flex;align-items:center;"><img src="' + displayUrl + '" style="max-height:240px;" /><div style="margin-left:1em;">' + resultHtml + '</div>';
|
||||
resultHtml = `<div style="display:flex;align-items:center;"><img src="${displayUrl}" style="max-height:240px;" /><div style="margin-left:1em;">${resultHtml}</div>`;
|
||||
}
|
||||
|
||||
page.querySelector('.selectedSearchResult').innerHTML = resultHtml;
|
||||
@@ -174,13 +182,12 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
|
||||
}
|
||||
|
||||
function getSearchResultHtml(result, index) {
|
||||
|
||||
// TODO move card creation code to Card component
|
||||
|
||||
var html = '';
|
||||
var cssClass = 'card scalableCard';
|
||||
var cardBoxCssClass = 'cardBox';
|
||||
var padderClass;
|
||||
let html = '';
|
||||
let cssClass = 'card scalableCard';
|
||||
let cardBoxCssClass = 'cardBox';
|
||||
let padderClass;
|
||||
|
||||
if (currentItemType === 'Episode') {
|
||||
cssClass += ' backdropCard backdropCard-scalable';
|
||||
@@ -203,30 +210,29 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
|
||||
|
||||
cardBoxCssClass += ' cardBox-bottompadded';
|
||||
|
||||
html += '<button type="button" class="' + cssClass + '" data-index="' + index + '">';
|
||||
html += '<div class="' + cardBoxCssClass + '">';
|
||||
html += `<button type="button" class="${cssClass}" data-index="${index}">`;
|
||||
html += `<div class="${cardBoxCssClass}">`;
|
||||
html += '<div class="cardScalable">';
|
||||
html += '<div class="' + padderClass + '"></div>';
|
||||
html += `<div class="${padderClass}"></div>`;
|
||||
|
||||
html += '<div class="cardContent searchImage">';
|
||||
|
||||
if (result.ImageUrl) {
|
||||
var displayUrl = getSearchImageDisplayUrl(result.ImageUrl, result.SearchProviderName);
|
||||
const displayUrl = getSearchImageDisplayUrl(result.ImageUrl, result.SearchProviderName);
|
||||
|
||||
html += '<div class="cardImageContainer coveredImage" style="background-image:url(\'' + displayUrl + '\');"></div>';
|
||||
html += `<div class="cardImageContainer coveredImage" style="background-image:url('${displayUrl}');"></div>`;
|
||||
} else {
|
||||
|
||||
html += '<div class="cardImageContainer coveredImage defaultCardBackground defaultCardBackground1"><div class="cardText cardCenteredText">' + result.Name + '</div></div>';
|
||||
html += `<div class="cardImageContainer coveredImage defaultCardBackground defaultCardBackground1"><div class="cardText cardCenteredText">${result.Name}</div></div>`;
|
||||
}
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
|
||||
var numLines = 3;
|
||||
let numLines = 3;
|
||||
if (currentItemType === 'MusicAlbum') {
|
||||
numLines++;
|
||||
}
|
||||
|
||||
var lines = [result.Name];
|
||||
const lines = [result.Name];
|
||||
|
||||
lines.push(result.SearchProviderName);
|
||||
|
||||
@@ -237,8 +243,7 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
|
||||
lines.push(result.ProductionYear);
|
||||
}
|
||||
|
||||
for (var i = 0; i < numLines; i++) {
|
||||
|
||||
for (let i = 0; i < numLines; i++) {
|
||||
if (i === 0) {
|
||||
html += '<div class="cardText cardText-first cardTextCentered">';
|
||||
} else {
|
||||
@@ -254,36 +259,32 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
|
||||
}
|
||||
|
||||
function getSearchImageDisplayUrl(url, provider) {
|
||||
var apiClient = getApiClient();
|
||||
const apiClient = getApiClient();
|
||||
|
||||
return apiClient.getUrl('Items/RemoteSearch/Image', { imageUrl: url, ProviderName: provider });
|
||||
}
|
||||
|
||||
function submitIdentficationResult(page) {
|
||||
|
||||
loading.show();
|
||||
|
||||
var options = {
|
||||
const options = {
|
||||
ReplaceAllImages: page.querySelector('#chkIdentifyReplaceImages').checked
|
||||
};
|
||||
|
||||
var apiClient = getApiClient();
|
||||
const apiClient = getApiClient();
|
||||
|
||||
apiClient.ajax({
|
||||
type: 'POST',
|
||||
url: apiClient.getUrl('Items/RemoteSearch/Apply/' + currentItem.Id, options),
|
||||
url: apiClient.getUrl(`Items/RemoteSearch/Apply/${currentItem.Id}`, options),
|
||||
data: JSON.stringify(currentSearchResult),
|
||||
contentType: 'application/json'
|
||||
|
||||
}).then(function () {
|
||||
|
||||
}).then(() => {
|
||||
hasChanges = true;
|
||||
loading.hide();
|
||||
|
||||
dialogHelper.close(page);
|
||||
|
||||
}, function () {
|
||||
|
||||
}, () => {
|
||||
loading.hide();
|
||||
|
||||
dialogHelper.close(page);
|
||||
@@ -291,29 +292,26 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
|
||||
}
|
||||
|
||||
function showIdentificationForm(page, item) {
|
||||
const apiClient = getApiClient();
|
||||
|
||||
var apiClient = getApiClient();
|
||||
apiClient.getJSON(apiClient.getUrl(`Items/${item.Id}/ExternalIdInfos`)).then(idList => {
|
||||
let html = '';
|
||||
|
||||
apiClient.getJSON(apiClient.getUrl('Items/' + item.Id + '/ExternalIdInfos')).then(function (idList) {
|
||||
for (let i = 0, length = idList.length; i < length; i++) {
|
||||
const idInfo = idList[i];
|
||||
|
||||
var html = '';
|
||||
|
||||
for (var i = 0, length = idList.length; i < length; i++) {
|
||||
|
||||
var idInfo = idList[i];
|
||||
|
||||
var id = 'txtLookup' + idInfo.Key;
|
||||
const id = `txtLookup${idInfo.Key}`;
|
||||
|
||||
html += '<div class="inputContainer">';
|
||||
|
||||
var fullName = idInfo.Name;
|
||||
let fullName = idInfo.Name;
|
||||
if (idInfo.Type) {
|
||||
fullName = idInfo.Name + ' ' + globalize.translate(idInfo.Type);
|
||||
fullName = `${idInfo.Name} ${globalize.translate(idInfo.Type)}`;
|
||||
}
|
||||
|
||||
var idLabel = globalize.translate('LabelDynamicExternalId', fullName);
|
||||
const idLabel = globalize.translate('LabelDynamicExternalId', fullName);
|
||||
|
||||
html += '<input is="emby-input" class="txtLookupId" data-providerkey="' + idInfo.Key + '" id="' + id + '" label="' + idLabel + '"/>';
|
||||
html += `<input is="emby-input" class="txtLookupId" data-providerkey="${idInfo.Key}" id="${id}" label="${idLabel}"/>`;
|
||||
|
||||
html += '</div>';
|
||||
}
|
||||
@@ -321,11 +319,9 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
|
||||
page.querySelector('#txtLookupName').value = '';
|
||||
|
||||
if (item.Type === 'Person' || item.Type === 'BoxSet') {
|
||||
|
||||
page.querySelector('.fldLookupYear').classList.add('hide');
|
||||
page.querySelector('#txtLookupYear').value = '';
|
||||
} else {
|
||||
|
||||
page.querySelector('.fldLookupYear').classList.remove('hide');
|
||||
page.querySelector('#txtLookupYear').value = '';
|
||||
}
|
||||
@@ -337,19 +333,16 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
|
||||
}
|
||||
|
||||
function showEditor(itemId) {
|
||||
|
||||
loading.show();
|
||||
|
||||
require(['text!./itemidentifier.template.html'], function (template) {
|
||||
|
||||
var apiClient = getApiClient();
|
||||
|
||||
apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) {
|
||||
return import('text!./itemidentifier.template.html').then(({default: template}) => {
|
||||
const apiClient = getApiClient();
|
||||
|
||||
apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(item => {
|
||||
currentItem = item;
|
||||
currentItemType = currentItem.Type;
|
||||
|
||||
var dialogOptions = {
|
||||
const dialogOptions = {
|
||||
size: 'small',
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
@@ -359,13 +352,13 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
|
||||
dialogOptions.size = 'fullscreen';
|
||||
}
|
||||
|
||||
var dlg = dialogHelper.createDialog(dialogOptions);
|
||||
const dlg = dialogHelper.createDialog(dialogOptions);
|
||||
|
||||
dlg.classList.add('formDialog');
|
||||
dlg.classList.add('recordingDialog');
|
||||
|
||||
var html = '';
|
||||
html += globalize.translateDocument(template, 'core');
|
||||
let html = '';
|
||||
html += globalize.translateHtml(template, 'core');
|
||||
|
||||
dlg.innerHTML = html;
|
||||
|
||||
@@ -386,22 +379,19 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
|
||||
|
||||
dialogHelper.open(dlg);
|
||||
|
||||
dlg.querySelector('.popupIdentifyForm').addEventListener('submit', function (e) {
|
||||
|
||||
dlg.querySelector('.popupIdentifyForm').addEventListener('submit', e => {
|
||||
e.preventDefault();
|
||||
searchForIdentificationResults(dlg);
|
||||
return false;
|
||||
});
|
||||
|
||||
dlg.querySelector('.identifyOptionsForm').addEventListener('submit', function (e) {
|
||||
|
||||
dlg.querySelector('.identifyOptionsForm').addEventListener('submit', e => {
|
||||
e.preventDefault();
|
||||
submitIdentficationResult(dlg);
|
||||
return false;
|
||||
});
|
||||
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', function (e) {
|
||||
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', () => {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
|
||||
@@ -414,7 +404,6 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
|
||||
}
|
||||
|
||||
function onDialogClosed() {
|
||||
|
||||
loading.hide();
|
||||
if (hasChanges) {
|
||||
currentResolve();
|
||||
@@ -423,14 +412,13 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
|
||||
}
|
||||
}
|
||||
|
||||
// TODO investigate where this was used
|
||||
function showEditorFindNew(itemName, itemYear, itemType, resolveFunc) {
|
||||
|
||||
currentItem = null;
|
||||
currentItemType = itemType;
|
||||
|
||||
require(['text!./itemidentifier.template.html'], function (template) {
|
||||
|
||||
var dialogOptions = {
|
||||
return import('text!./itemidentifier.template.html').then(({default: template}) => {
|
||||
const dialogOptions = {
|
||||
size: 'small',
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
@@ -440,13 +428,13 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
|
||||
dialogOptions.size = 'fullscreen';
|
||||
}
|
||||
|
||||
var dlg = dialogHelper.createDialog(dialogOptions);
|
||||
const dlg = dialogHelper.createDialog(dialogOptions);
|
||||
|
||||
dlg.classList.add('formDialog');
|
||||
dlg.classList.add('recordingDialog');
|
||||
|
||||
var html = '';
|
||||
html += globalize.translateDocument(template, 'core');
|
||||
let html = '';
|
||||
html += globalize.translateHtml(template, 'core');
|
||||
|
||||
dlg.innerHTML = html;
|
||||
|
||||
@@ -456,22 +444,19 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
|
||||
|
||||
dialogHelper.open(dlg);
|
||||
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', function (e) {
|
||||
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', () => {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
|
||||
dlg.querySelector('.popupIdentifyForm').addEventListener('submit', function (e) {
|
||||
|
||||
dlg.querySelector('.popupIdentifyForm').addEventListener('submit', e => {
|
||||
e.preventDefault();
|
||||
searchForIdentificationResults(dlg);
|
||||
return false;
|
||||
});
|
||||
|
||||
dlg.addEventListener('close', function () {
|
||||
|
||||
dlg.addEventListener('close', () => {
|
||||
loading.hide();
|
||||
var foundItem = hasChanges ? currentSearchResult : null;
|
||||
const foundItem = hasChanges ? currentSearchResult : null;
|
||||
|
||||
resolveFunc(foundItem);
|
||||
});
|
||||
@@ -483,16 +468,12 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
|
||||
}
|
||||
|
||||
function showIdentificationFormFindNew(dlg, itemName, itemYear, itemType) {
|
||||
|
||||
dlg.querySelector('#txtLookupName').value = itemName;
|
||||
|
||||
if (itemType === 'Person' || itemType === 'BoxSet') {
|
||||
|
||||
dlg.querySelector('.fldLookupYear').classList.add('hide');
|
||||
dlg.querySelector('#txtLookupYear').value = '';
|
||||
|
||||
} else {
|
||||
|
||||
dlg.querySelector('.fldLookupYear').classList.remove('hide');
|
||||
dlg.querySelector('#txtLookupYear').value = itemYear;
|
||||
}
|
||||
@@ -500,29 +481,28 @@ define(['dialogHelper', 'loading', 'connectionManager', 'require', 'globalize',
|
||||
dlg.querySelector('.formDialogHeaderTitle').innerHTML = globalize.translate('Search');
|
||||
}
|
||||
|
||||
return {
|
||||
show: function (itemId, serverId) {
|
||||
export function show(itemId, serverId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
currentResolve = resolve;
|
||||
currentReject = reject;
|
||||
currentServerId = serverId;
|
||||
hasChanges = false;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
showEditor(itemId);
|
||||
});
|
||||
}
|
||||
|
||||
currentResolve = resolve;
|
||||
currentReject = reject;
|
||||
currentServerId = serverId;
|
||||
hasChanges = false;
|
||||
export function showFindNew(itemName, itemYear, itemType, serverId) {
|
||||
return new Promise((resolve) => {
|
||||
currentServerId = serverId;
|
||||
|
||||
showEditor(itemId);
|
||||
});
|
||||
},
|
||||
hasChanges = false;
|
||||
showEditorFindNew(itemName, itemYear, itemType, resolve);
|
||||
});
|
||||
}
|
||||
|
||||
showFindNew: function (itemName, itemYear, itemType, serverId) {
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
currentServerId = serverId;
|
||||
|
||||
hasChanges = false;
|
||||
showEditorFindNew(itemName, itemYear, itemType, resolve);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
/* eslint-enable indent */
|
||||
export default {
|
||||
show: show,
|
||||
showFindNew: showFindNew
|
||||
};
|
||||
|
||||
@@ -2,23 +2,19 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
|
||||
'use strict';
|
||||
|
||||
function onUserDataChanged(e, apiClient, userData) {
|
||||
|
||||
var instance = this;
|
||||
|
||||
var eventsToMonitor = getEventsToMonitor(instance);
|
||||
|
||||
// TODO: Check user data change reason?
|
||||
if (eventsToMonitor.indexOf('markfavorite') !== -1) {
|
||||
|
||||
instance.notifyRefreshNeeded();
|
||||
} else if (eventsToMonitor.indexOf('markplayed') !== -1) {
|
||||
|
||||
instance.notifyRefreshNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
function getEventsToMonitor(instance) {
|
||||
|
||||
var options = instance.options;
|
||||
var monitor = options ? options.monitorEvents : null;
|
||||
if (monitor) {
|
||||
@@ -29,21 +25,17 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
|
||||
}
|
||||
|
||||
function onTimerCreated(e, apiClient, data) {
|
||||
|
||||
var instance = this;
|
||||
|
||||
if (getEventsToMonitor(instance).indexOf('timers') !== -1) {
|
||||
|
||||
instance.notifyRefreshNeeded();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function onSeriesTimerCreated(e, apiClient, data) {
|
||||
|
||||
var instance = this;
|
||||
if (getEventsToMonitor(instance).indexOf('seriestimers') !== -1) {
|
||||
|
||||
instance.notifyRefreshNeeded();
|
||||
return;
|
||||
}
|
||||
@@ -53,28 +45,23 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
|
||||
var instance = this;
|
||||
|
||||
if (getEventsToMonitor(instance).indexOf('timers') !== -1) {
|
||||
|
||||
instance.notifyRefreshNeeded();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function onSeriesTimerCancelled(e, apiClient, data) {
|
||||
|
||||
var instance = this;
|
||||
if (getEventsToMonitor(instance).indexOf('seriestimers') !== -1) {
|
||||
|
||||
instance.notifyRefreshNeeded();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function onLibraryChanged(e, apiClient, data) {
|
||||
|
||||
var instance = this;
|
||||
var eventsToMonitor = getEventsToMonitor(instance);
|
||||
if (eventsToMonitor.indexOf('seriestimers') !== -1 || eventsToMonitor.indexOf('timers') !== -1) {
|
||||
|
||||
// yes this is an assumption
|
||||
return;
|
||||
}
|
||||
@@ -101,23 +88,18 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
|
||||
}
|
||||
|
||||
function onPlaybackStopped(e, stopInfo) {
|
||||
|
||||
var instance = this;
|
||||
|
||||
var state = stopInfo.state;
|
||||
|
||||
var eventsToMonitor = getEventsToMonitor(instance);
|
||||
if (state.NowPlayingItem && state.NowPlayingItem.MediaType === 'Video') {
|
||||
|
||||
if (eventsToMonitor.indexOf('videoplayback') !== -1) {
|
||||
|
||||
instance.notifyRefreshNeeded(true);
|
||||
return;
|
||||
}
|
||||
} else if (state.NowPlayingItem && state.NowPlayingItem.MediaType === 'Audio') {
|
||||
|
||||
if (eventsToMonitor.indexOf('audioplayback') !== -1) {
|
||||
|
||||
instance.notifyRefreshNeeded(true);
|
||||
return;
|
||||
}
|
||||
@@ -125,7 +107,6 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
|
||||
}
|
||||
|
||||
function addNotificationEvent(instance, name, handler, owner) {
|
||||
|
||||
var localHandler = handler.bind(instance);
|
||||
owner = owner || serverNotifications;
|
||||
events.on(owner, name, localHandler);
|
||||
@@ -133,7 +114,6 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
|
||||
}
|
||||
|
||||
function removeNotificationEvent(instance, name, owner) {
|
||||
|
||||
var handler = instance['event_' + name];
|
||||
if (handler) {
|
||||
owner = owner || serverNotifications;
|
||||
@@ -143,7 +123,6 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
|
||||
}
|
||||
|
||||
function ItemsRefresher(options) {
|
||||
|
||||
this.options = options || {};
|
||||
|
||||
addNotificationEvent(this, 'UserDataChanged', onUserDataChanged);
|
||||
@@ -156,24 +135,19 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
|
||||
}
|
||||
|
||||
ItemsRefresher.prototype.pause = function () {
|
||||
|
||||
clearRefreshInterval(this, true);
|
||||
|
||||
this.paused = true;
|
||||
};
|
||||
|
||||
ItemsRefresher.prototype.resume = function (options) {
|
||||
|
||||
this.paused = false;
|
||||
|
||||
var refreshIntervalEndTime = this.refreshIntervalEndTime;
|
||||
if (refreshIntervalEndTime) {
|
||||
|
||||
var remainingMs = refreshIntervalEndTime - new Date().getTime();
|
||||
if (remainingMs > 0 && !this.needsRefresh) {
|
||||
|
||||
resetRefreshInterval(this, remainingMs);
|
||||
|
||||
} else {
|
||||
this.needsRefresh = true;
|
||||
this.refreshIntervalEndTime = null;
|
||||
@@ -188,7 +162,6 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
|
||||
};
|
||||
|
||||
ItemsRefresher.prototype.refreshItems = function () {
|
||||
|
||||
if (!this.fetchData) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
@@ -204,7 +177,6 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
|
||||
};
|
||||
|
||||
ItemsRefresher.prototype.notifyRefreshNeeded = function (isInForeground) {
|
||||
|
||||
if (this.paused) {
|
||||
this.needsRefresh = true;
|
||||
return;
|
||||
@@ -223,9 +195,7 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
|
||||
};
|
||||
|
||||
function clearRefreshInterval(instance, isPausing) {
|
||||
|
||||
if (instance.refreshInterval) {
|
||||
|
||||
clearInterval(instance.refreshInterval);
|
||||
instance.refreshInterval = null;
|
||||
|
||||
@@ -236,7 +206,6 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
|
||||
}
|
||||
|
||||
function resetRefreshInterval(instance, intervalMs) {
|
||||
|
||||
clearRefreshInterval(instance);
|
||||
|
||||
if (!intervalMs) {
|
||||
@@ -253,7 +222,6 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
|
||||
}
|
||||
|
||||
function onDataFetched(result) {
|
||||
|
||||
resetRefreshInterval(this);
|
||||
|
||||
if (this.afterRefresh) {
|
||||
@@ -262,7 +230,6 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
|
||||
}
|
||||
|
||||
ItemsRefresher.prototype.destroy = function () {
|
||||
|
||||
clearRefreshInterval(this);
|
||||
|
||||
removeNotificationEvent(this, 'UserDataChanged');
|
||||
|
||||
@@ -16,7 +16,6 @@ define(['browser', 'appSettings', 'events'], function (browser, appSettings, eve
|
||||
}
|
||||
|
||||
LayoutManager.prototype.setLayout = function (layout, save) {
|
||||
|
||||
if (!layout || layout === 'auto') {
|
||||
this.autoLayout();
|
||||
|
||||
@@ -41,7 +40,6 @@ define(['browser', 'appSettings', 'events'], function (browser, appSettings, eve
|
||||
};
|
||||
|
||||
LayoutManager.prototype.autoLayout = function () {
|
||||
|
||||
// Take a guess at initial layout. The consuming app can override
|
||||
if (browser.mobile) {
|
||||
this.setLayout('mobile', false);
|
||||
|
||||
@@ -1,63 +1,73 @@
|
||||
define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], function(globalize, dom) {
|
||||
'use strict';
|
||||
/* eslint-disable indent */
|
||||
|
||||
/**
|
||||
* Module for library options editor.
|
||||
* @module components/libraryoptionseditor/libraryoptionseditor
|
||||
*/
|
||||
|
||||
import globalize from 'globalize';
|
||||
import dom from 'dom';
|
||||
import 'emby-checkbox';
|
||||
import 'emby-select';
|
||||
import 'emby-input';
|
||||
|
||||
function populateLanguages(parent) {
|
||||
return ApiClient.getCultures().then(function(languages) {
|
||||
return ApiClient.getCultures().then(languages => {
|
||||
populateLanguagesIntoSelect(parent.querySelector('#selectLanguage'), languages);
|
||||
populateLanguagesIntoList(parent.querySelector('.subtitleDownloadLanguages'), languages);
|
||||
});
|
||||
}
|
||||
|
||||
function populateLanguagesIntoSelect(select, languages) {
|
||||
var html = '';
|
||||
let html = '';
|
||||
html += "<option value=''></option>";
|
||||
for (var i = 0; i < languages.length; i++) {
|
||||
var culture = languages[i];
|
||||
html += "<option value='" + culture.TwoLetterISOLanguageName + "'>" + culture.DisplayName + '</option>';
|
||||
for (let i = 0; i < languages.length; i++) {
|
||||
const culture = languages[i];
|
||||
html += `<option value='${culture.TwoLetterISOLanguageName}'>${culture.DisplayName}</option>`;
|
||||
}
|
||||
select.innerHTML = html;
|
||||
}
|
||||
|
||||
function populateLanguagesIntoList(element, languages) {
|
||||
var html = '';
|
||||
for (var i = 0; i < languages.length; i++) {
|
||||
var culture = languages[i];
|
||||
html += '<label><input type="checkbox" is="emby-checkbox" class="chkSubtitleLanguage" data-lang="' + culture.ThreeLetterISOLanguageName.toLowerCase() + '" /><span>' + culture.DisplayName + '</span></label>';
|
||||
let html = '';
|
||||
for (let i = 0; i < languages.length; i++) {
|
||||
const culture = languages[i];
|
||||
html += `<label><input type="checkbox" is="emby-checkbox" class="chkSubtitleLanguage" data-lang="${culture.ThreeLetterISOLanguageName.toLowerCase()}" /><span>${culture.DisplayName}</span></label>`;
|
||||
}
|
||||
element.innerHTML = html;
|
||||
}
|
||||
|
||||
function populateCountries(select) {
|
||||
return ApiClient.getCountries().then(function(allCountries) {
|
||||
var html = '';
|
||||
return ApiClient.getCountries().then(allCountries => {
|
||||
let html = '';
|
||||
html += "<option value=''></option>";
|
||||
for (var i = 0; i < allCountries.length; i++) {
|
||||
var culture = allCountries[i];
|
||||
html += "<option value='" + culture.TwoLetterISORegionName + "'>" + culture.DisplayName + '</option>';
|
||||
for (let i = 0; i < allCountries.length; i++) {
|
||||
const culture = allCountries[i];
|
||||
html += `<option value='${culture.TwoLetterISORegionName}'>${culture.DisplayName}</option>`;
|
||||
}
|
||||
select.innerHTML = html;
|
||||
});
|
||||
}
|
||||
|
||||
function populateRefreshInterval(select) {
|
||||
var html = '';
|
||||
html += "<option value='0'>" + globalize.translate('Never') + '</option>';
|
||||
html += [30, 60, 90].map(function(val) {
|
||||
return "<option value='" + val + "'>" + globalize.translate('EveryNDays', val) + '</option>';
|
||||
let html = '';
|
||||
html += `<option value='0'>${globalize.translate('Never')}</option>`;
|
||||
html += [30, 60, 90].map(val => {
|
||||
return `<option value='${val}'>${globalize.translate('EveryNDays', val)}</option>`;
|
||||
}).join('');
|
||||
select.innerHTML = html;
|
||||
}
|
||||
|
||||
function renderMetadataReaders(page, plugins) {
|
||||
var html = '';
|
||||
var elem = page.querySelector('.metadataReaders');
|
||||
let html = '';
|
||||
const elem = page.querySelector('.metadataReaders');
|
||||
|
||||
if (plugins.length < 1) return elem.innerHTML = '', elem.classList.add('hide'), !1;
|
||||
html += '<h3 class="checkboxListLabel">' + globalize.translate('LabelMetadataReaders') + '</h3>';
|
||||
html += `<h3 class="checkboxListLabel">${globalize.translate('LabelMetadataReaders')}</h3>`;
|
||||
html += '<div class="checkboxList paperList checkboxList-paperList">';
|
||||
for (var i = 0; i < plugins.length; i++) {
|
||||
var plugin = plugins[i];
|
||||
html += '<div class="listItem localReaderOption sortableOption" data-pluginname="' + plugin.Name + '">';
|
||||
for (let i = 0; i < plugins.length; i++) {
|
||||
const plugin = plugins[i];
|
||||
html += `<div class="listItem localReaderOption sortableOption" data-pluginname="${plugin.Name}">`;
|
||||
html += '<span class="listItemIcon material-icons live_tv"></span>';
|
||||
html += '<div class="listItemBody">';
|
||||
html += '<h3 class="listItemBodyText">';
|
||||
@@ -65,14 +75,14 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
|
||||
html += '</h3>';
|
||||
html += '</div>';
|
||||
if (i > 0) {
|
||||
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('ButtonUp') + '" class="btnSortableMoveUp btnSortable" data-pluginindex="' + i + '"><span class="material-icons keyboard_arrow_up"></span></button>';
|
||||
html += `<button type="button" is="paper-icon-button-light" title="${globalize.translate('ButtonUp')}" class="btnSortableMoveUp btnSortable" data-pluginindex="${i}"><span class="material-icons keyboard_arrow_up"></span></button>`;
|
||||
} else if (plugins.length > 1) {
|
||||
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('ButtonDown') + '" class="btnSortableMoveDown btnSortable" data-pluginindex="' + i + '"><span class="material-icons keyboard_arrow_down"></span></button>';
|
||||
html += `<button type="button" is="paper-icon-button-light" title="${globalize.translate('ButtonDown')}" class="btnSortableMoveDown btnSortable" data-pluginindex="${i}"><span class="material-icons keyboard_arrow_down"></span></button>`;
|
||||
}
|
||||
html += '</div>';
|
||||
}
|
||||
html += '</div>';
|
||||
html += '<div class="fieldDescription">' + globalize.translate('LabelMetadataReadersHelp') + '</div>';
|
||||
html += `<div class="fieldDescription">${globalize.translate('LabelMetadataReadersHelp')}</div>`;
|
||||
if (plugins.length < 2) {
|
||||
elem.classList.add('hide');
|
||||
} else {
|
||||
@@ -83,25 +93,25 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
|
||||
}
|
||||
|
||||
function renderMetadataSavers(page, metadataSavers) {
|
||||
var html = '';
|
||||
var elem = page.querySelector('.metadataSavers');
|
||||
let html = '';
|
||||
const elem = page.querySelector('.metadataSavers');
|
||||
if (!metadataSavers.length) return elem.innerHTML = '', elem.classList.add('hide'), false;
|
||||
html += '<h3 class="checkboxListLabel">' + globalize.translate('LabelMetadataSavers') + '</h3>';
|
||||
html += `<h3 class="checkboxListLabel">${globalize.translate('LabelMetadataSavers')}</h3>`;
|
||||
html += '<div class="checkboxList paperList checkboxList-paperList">';
|
||||
for (var i = 0; i < metadataSavers.length; i++) {
|
||||
var plugin = metadataSavers[i];
|
||||
html += '<label><input type="checkbox" data-defaultenabled="' + plugin.DefaultEnabled + '" is="emby-checkbox" class="chkMetadataSaver" data-pluginname="' + plugin.Name + '" ' + false + '><span>' + plugin.Name + '</span></label>';
|
||||
for (let i = 0; i < metadataSavers.length; i++) {
|
||||
const plugin = metadataSavers[i];
|
||||
html += `<label><input type="checkbox" data-defaultenabled="${plugin.DefaultEnabled}" is="emby-checkbox" class="chkMetadataSaver" data-pluginname="${plugin.Name}" ${false}><span>${plugin.Name}</span></label>`;
|
||||
}
|
||||
html += '</div>';
|
||||
html += '<div class="fieldDescription" style="margin-top:.25em;">' + globalize.translate('LabelMetadataSaversHelp') + '</div>';
|
||||
html += `<div class="fieldDescription" style="margin-top:.25em;">${globalize.translate('LabelMetadataSaversHelp')}</div>`;
|
||||
elem.innerHTML = html;
|
||||
elem.classList.remove('hide');
|
||||
return true;
|
||||
}
|
||||
|
||||
function getMetadataFetchersForTypeHtml(availableTypeOptions, libraryOptionsForType) {
|
||||
var html = '';
|
||||
var plugins = availableTypeOptions.MetadataFetchers;
|
||||
let html = '';
|
||||
let plugins = availableTypeOptions.MetadataFetchers;
|
||||
|
||||
plugins = getOrderedPlugins(plugins, libraryOptionsForType.MetadataFetcherOrder || []);
|
||||
if (!plugins.length) return html;
|
||||
@@ -112,8 +122,8 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
|
||||
|
||||
plugins.forEach((plugin, index) => {
|
||||
html += '<div class="listItem metadataFetcherItem sortableOption" data-pluginname="' + plugin.Name + '">';
|
||||
var isChecked = libraryOptionsForType.MetadataFetchers ? -1 !== libraryOptionsForType.MetadataFetchers.indexOf(plugin.Name) : plugin.DefaultEnabled;
|
||||
var checkedHtml = isChecked ? ' checked="checked"' : '';
|
||||
const isChecked = libraryOptionsForType.MetadataFetchers ? libraryOptionsForType.MetadataFetchers.includes(plugin.Name) : plugin.DefaultEnabled;
|
||||
const checkedHtml = isChecked ? ' checked="checked"' : '';
|
||||
html += '<label class="listItemCheckboxContainer"><input type="checkbox" is="emby-checkbox" class="chkMetadataFetcher" data-pluginname="' + plugin.Name + '" ' + checkedHtml + '><span></span></label>';
|
||||
html += '<div class="listItemBody">';
|
||||
html += '<h3 class="listItemBodyText">';
|
||||
@@ -135,19 +145,19 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
|
||||
}
|
||||
|
||||
function getTypeOptions(allOptions, type) {
|
||||
var allTypeOptions = allOptions.TypeOptions || [];
|
||||
for (var i = 0; i < allTypeOptions.length; i++) {
|
||||
var typeOptions = allTypeOptions[i];
|
||||
const allTypeOptions = allOptions.TypeOptions || [];
|
||||
for (let i = 0; i < allTypeOptions.length; i++) {
|
||||
const typeOptions = allTypeOptions[i];
|
||||
if (typeOptions.Type === type) return typeOptions;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function renderMetadataFetchers(page, availableOptions, libraryOptions) {
|
||||
var html = '';
|
||||
var elem = page.querySelector('.metadataFetchers');
|
||||
for (var i = 0; i < availableOptions.TypeOptions.length; i++) {
|
||||
var availableTypeOptions = availableOptions.TypeOptions[i];
|
||||
let html = '';
|
||||
const elem = page.querySelector('.metadataFetchers');
|
||||
for (let i = 0; i < availableOptions.TypeOptions.length; i++) {
|
||||
const availableTypeOptions = availableOptions.TypeOptions[i];
|
||||
html += getMetadataFetchersForTypeHtml(availableTypeOptions, getTypeOptions(libraryOptions, availableTypeOptions.Type) || {});
|
||||
}
|
||||
elem.innerHTML = html;
|
||||
@@ -166,41 +176,41 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
|
||||
}
|
||||
|
||||
function renderSubtitleFetchers(page, availableOptions, libraryOptions) {
|
||||
var html = '';
|
||||
var elem = page.querySelector('.subtitleFetchers');
|
||||
let html = '';
|
||||
const elem = page.querySelector('.subtitleFetchers');
|
||||
|
||||
var plugins = availableOptions.SubtitleFetchers;
|
||||
let plugins = availableOptions.SubtitleFetchers;
|
||||
plugins = getOrderedPlugins(plugins, libraryOptions.SubtitleFetcherOrder || []);
|
||||
if (!plugins.length) return html;
|
||||
|
||||
html += '<h3 class="checkboxListLabel">' + globalize.translate('LabelSubtitleDownloaders') + '</h3>';
|
||||
html += `<h3 class="checkboxListLabel">${globalize.translate('LabelSubtitleDownloaders')}</h3>`;
|
||||
html += '<div class="checkboxList paperList checkboxList-paperList">';
|
||||
for (var i = 0; i < plugins.length; i++) {
|
||||
var plugin = plugins[i];
|
||||
html += '<div class="listItem subtitleFetcherItem sortableOption" data-pluginname="' + plugin.Name + '">';
|
||||
var isChecked = libraryOptions.DisabledSubtitleFetchers ? -1 === libraryOptions.DisabledSubtitleFetchers.indexOf(plugin.Name) : plugin.DefaultEnabled;
|
||||
var checkedHtml = isChecked ? ' checked="checked"' : '';
|
||||
html += '<label class="listItemCheckboxContainer"><input type="checkbox" is="emby-checkbox" class="chkSubtitleFetcher" data-pluginname="' + plugin.Name + '" ' + checkedHtml + '><span></span></label>';
|
||||
for (let i = 0; i < plugins.length; i++) {
|
||||
const plugin = plugins[i];
|
||||
html += `<div class="listItem subtitleFetcherItem sortableOption" data-pluginname="${plugin.Name}">`;
|
||||
const isChecked = libraryOptions.DisabledSubtitleFetchers ? !libraryOptions.DisabledSubtitleFetchers.includes(plugin.Name) : plugin.DefaultEnabled;
|
||||
const checkedHtml = isChecked ? ' checked="checked"' : '';
|
||||
html += `<label class="listItemCheckboxContainer"><input type="checkbox" is="emby-checkbox" class="chkSubtitleFetcher" data-pluginname="${plugin.Name}" ${checkedHtml}><span></span></label>`;
|
||||
html += '<div class="listItemBody">';
|
||||
html += '<h3 class="listItemBodyText">';
|
||||
html += plugin.Name;
|
||||
html += '</h3>';
|
||||
html += '</div>';
|
||||
if (i > 0) {
|
||||
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('ButtonUp') + '" class="btnSortableMoveUp btnSortable" data-pluginindex="' + i + '"><span class="material-icons keyboard_arrow_up"></span></button>';
|
||||
html += `<button type="button" is="paper-icon-button-light" title="${globalize.translate('ButtonUp')}" class="btnSortableMoveUp btnSortable" data-pluginindex="${i}"><span class="material-icons keyboard_arrow_up"></span></button>`;
|
||||
} else if (plugins.length > 1) {
|
||||
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('ButtonDown') + '" class="btnSortableMoveDown btnSortable" data-pluginindex="' + i + '"><span class="material-icons keyboard_arrow_down"></span></button>';
|
||||
html += `<button type="button" is="paper-icon-button-light" title="${globalize.translate('ButtonDown')}" class="btnSortableMoveDown btnSortable" data-pluginindex="${i}"><span class="material-icons keyboard_arrow_down"></span></button>`;
|
||||
}
|
||||
html += '</div>';
|
||||
}
|
||||
html += '</div>';
|
||||
html += '<div class="fieldDescription">' + globalize.translate('SubtitleDownloadersHelp') + '</div>';
|
||||
html += `<div class="fieldDescription">${globalize.translate('SubtitleDownloadersHelp')}</div>`;
|
||||
elem.innerHTML = html;
|
||||
}
|
||||
|
||||
function getImageFetchersForTypeHtml(availableTypeOptions, libraryOptionsForType) {
|
||||
var html = '';
|
||||
var plugins = availableTypeOptions.ImageFetchers;
|
||||
let html = '';
|
||||
let plugins = availableTypeOptions.ImageFetchers;
|
||||
|
||||
plugins = getOrderedPlugins(plugins, libraryOptionsForType.ImageFetcherOrder || []);
|
||||
if (!plugins.length) return html;
|
||||
@@ -208,17 +218,17 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
|
||||
html += '<div class="imageFetcher" data-type="' + availableTypeOptions.Type + '">';
|
||||
html += '<div class="flex align-items-center" style="margin:1.5em 0 .5em;">';
|
||||
html += '<h3 class="checkboxListLabel" style="margin:0;">' + globalize.translate('HeaderTypeImageFetchers', availableTypeOptions.Type) + '</h3>';
|
||||
var supportedImageTypes = availableTypeOptions.SupportedImageTypes || [];
|
||||
const supportedImageTypes = availableTypeOptions.SupportedImageTypes || [];
|
||||
if (supportedImageTypes.length > 1 || 1 === supportedImageTypes.length && 'Primary' !== supportedImageTypes[0]) {
|
||||
html += '<button is="emby-button" class="raised btnImageOptionsForType" type="button" style="margin-left:1.5em;font-size:90%;"><span>' + globalize.translate('HeaderFetcherSettings') + '</span></button>';
|
||||
}
|
||||
html += '</div>';
|
||||
html += '<div class="checkboxList paperList checkboxList-paperList">';
|
||||
for (var i = 0; i < plugins.length; i++) {
|
||||
var plugin = plugins[i];
|
||||
for (let i = 0; i < plugins.length; i++) {
|
||||
const plugin = plugins[i];
|
||||
html += '<div class="listItem imageFetcherItem sortableOption" data-pluginname="' + plugin.Name + '">';
|
||||
var isChecked = libraryOptionsForType.ImageFetchers ? -1 !== libraryOptionsForType.ImageFetchers.indexOf(plugin.Name) : plugin.DefaultEnabled;
|
||||
var checkedHtml = isChecked ? ' checked="checked"' : '';
|
||||
const isChecked = libraryOptionsForType.ImageFetchers ? libraryOptionsForType.ImageFetchers.includes(plugin.Name) : plugin.DefaultEnabled;
|
||||
const checkedHtml = isChecked ? ' checked="checked"' : '';
|
||||
html += '<label class="listItemCheckboxContainer"><input type="checkbox" is="emby-checkbox" class="chkImageFetcher" data-pluginname="' + plugin.Name + '" ' + checkedHtml + '><span></span></label>';
|
||||
html += '<div class="listItemBody">';
|
||||
html += '<h3 class="listItemBodyText">';
|
||||
@@ -239,10 +249,10 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
|
||||
}
|
||||
|
||||
function renderImageFetchers(page, availableOptions, libraryOptions) {
|
||||
var html = '';
|
||||
var elem = page.querySelector('.imageFetchers');
|
||||
for (var i = 0; i < availableOptions.TypeOptions.length; i++) {
|
||||
var availableTypeOptions = availableOptions.TypeOptions[i];
|
||||
let html = '';
|
||||
const elem = page.querySelector('.imageFetchers');
|
||||
for (let i = 0; i < availableOptions.TypeOptions.length; i++) {
|
||||
const availableTypeOptions = availableOptions.TypeOptions[i];
|
||||
html += getImageFetchersForTypeHtml(availableTypeOptions, getTypeOptions(libraryOptions, availableTypeOptions.Type) || {});
|
||||
}
|
||||
elem.innerHTML = html;
|
||||
@@ -258,12 +268,12 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
|
||||
return true;
|
||||
}
|
||||
|
||||
function populateMetadataSettings(parent, contentType, isNewLibrary) {
|
||||
var isNewLibrary = parent.classList.contains('newlibrary');
|
||||
function populateMetadataSettings(parent, contentType) {
|
||||
const isNewLibrary = parent.classList.contains('newlibrary');
|
||||
return ApiClient.getJSON(ApiClient.getUrl('Libraries/AvailableOptions', {
|
||||
LibraryContentType: contentType,
|
||||
IsNewLibrary: isNewLibrary
|
||||
})).then(function(availableOptions) {
|
||||
})).then(availableOptions => {
|
||||
currentAvailableOptions = availableOptions;
|
||||
parent.availableOptions = availableOptions;
|
||||
renderMetadataSavers(parent, availableOptions.MetadataSavers);
|
||||
@@ -272,14 +282,14 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
|
||||
renderSubtitleFetchers(parent, availableOptions, {});
|
||||
renderImageFetchers(parent, availableOptions, {});
|
||||
availableOptions.SubtitleFetchers.length ? parent.querySelector('.subtitleDownloadSettings').classList.remove('hide') : parent.querySelector('.subtitleDownloadSettings').classList.add('hide');
|
||||
}).catch(function() {
|
||||
}).catch(() => {
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
|
||||
function adjustSortableListElement(elem) {
|
||||
var btnSortable = elem.querySelector('.btnSortable');
|
||||
var inner = btnSortable.querySelector('.material-icons');
|
||||
const btnSortable = elem.querySelector('.btnSortable');
|
||||
const inner = btnSortable.querySelector('.material-icons');
|
||||
if (elem.previousSibling) {
|
||||
btnSortable.title = globalize.translate('ButtonUp');
|
||||
btnSortable.classList.add('btnSortableMoveUp');
|
||||
@@ -296,22 +306,22 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
|
||||
}
|
||||
|
||||
function showImageOptionsForType(type) {
|
||||
require(['imageoptionseditor'], function(ImageOptionsEditor) {
|
||||
var typeOptions = getTypeOptions(currentLibraryOptions, type);
|
||||
import('imageoptionseditor').then(({default: ImageOptionsEditor}) => {
|
||||
let typeOptions = getTypeOptions(currentLibraryOptions, type);
|
||||
if (!typeOptions) {
|
||||
typeOptions = {
|
||||
Type: type
|
||||
};
|
||||
currentLibraryOptions.TypeOptions.push(typeOptions);
|
||||
}
|
||||
var availableOptions = getTypeOptions(currentAvailableOptions || {}, type);
|
||||
var imageOptionsEditor = new ImageOptionsEditor();
|
||||
const availableOptions = getTypeOptions(currentAvailableOptions || {}, type);
|
||||
const imageOptionsEditor = new ImageOptionsEditor();
|
||||
imageOptionsEditor.show(type, typeOptions, availableOptions);
|
||||
});
|
||||
}
|
||||
|
||||
function onImageFetchersContainerClick(e) {
|
||||
var btnImageOptionsForType = dom.parentWithClass(e.target, 'btnImageOptionsForType');
|
||||
const btnImageOptionsForType = dom.parentWithClass(e.target, 'btnImageOptionsForType');
|
||||
if (btnImageOptionsForType) {
|
||||
return void showImageOptionsForType(dom.parentWithClass(btnImageOptionsForType, 'imageFetcher').getAttribute('data-type'));
|
||||
}
|
||||
@@ -319,18 +329,18 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
|
||||
}
|
||||
|
||||
function onSortableContainerClick(e) {
|
||||
var btnSortable = dom.parentWithClass(e.target, 'btnSortable');
|
||||
const btnSortable = dom.parentWithClass(e.target, 'btnSortable');
|
||||
if (btnSortable) {
|
||||
var li = dom.parentWithClass(btnSortable, 'sortableOption');
|
||||
var list = dom.parentWithClass(li, 'paperList');
|
||||
const li = dom.parentWithClass(btnSortable, 'sortableOption');
|
||||
const list = dom.parentWithClass(li, 'paperList');
|
||||
if (btnSortable.classList.contains('btnSortableMoveDown')) {
|
||||
var next = li.nextSibling;
|
||||
const next = li.nextSibling;
|
||||
if (next) {
|
||||
li.parentNode.removeChild(li);
|
||||
next.parentNode.insertBefore(li, next.nextSibling);
|
||||
}
|
||||
} else {
|
||||
var prev = li.previousSibling;
|
||||
const prev = li.previousSibling;
|
||||
if (prev) {
|
||||
li.parentNode.removeChild(li);
|
||||
prev.parentNode.insertBefore(li, prev);
|
||||
@@ -347,41 +357,35 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
|
||||
parent.querySelector('.imageFetchers').addEventListener('click', onImageFetchersContainerClick);
|
||||
}
|
||||
|
||||
function embed(parent, contentType, libraryOptions) {
|
||||
export async function embed(parent, contentType, libraryOptions) {
|
||||
currentLibraryOptions = {
|
||||
TypeOptions: []
|
||||
};
|
||||
currentAvailableOptions = null;
|
||||
var isNewLibrary = null === libraryOptions;
|
||||
const isNewLibrary = null === libraryOptions;
|
||||
isNewLibrary && parent.classList.add('newlibrary');
|
||||
return new Promise(function(resolve, reject) {
|
||||
var xhr = new XMLHttpRequest;
|
||||
xhr.open('GET', 'components/libraryoptionseditor/libraryoptionseditor.template.html', true);
|
||||
xhr.onload = function(e) {
|
||||
var template = this.response;
|
||||
parent.innerHTML = globalize.translateDocument(template);
|
||||
populateRefreshInterval(parent.querySelector('#selectAutoRefreshInterval'));
|
||||
var promises = [populateLanguages(parent), populateCountries(parent.querySelector('#selectCountry'))];
|
||||
Promise.all(promises).then(function() {
|
||||
return setContentType(parent, contentType).then(function() {
|
||||
libraryOptions && setLibraryOptions(parent, libraryOptions);
|
||||
bindEvents(parent);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
xhr.send();
|
||||
const response = await fetch('components/libraryoptionseditor/libraryoptionseditor.template.html');
|
||||
const template = await response.text();
|
||||
parent.innerHTML = globalize.translateHtml(template);
|
||||
populateRefreshInterval(parent.querySelector('#selectAutoRefreshInterval'));
|
||||
const promises = [populateLanguages(parent), populateCountries(parent.querySelector('#selectCountry'))];
|
||||
Promise.all(promises).then(function() {
|
||||
return setContentType(parent, contentType).then(function() {
|
||||
libraryOptions && setLibraryOptions(parent, libraryOptions);
|
||||
bindEvents(parent);
|
||||
return;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setAdvancedVisible(parent, visible) {
|
||||
var elems = parent.querySelectorAll('.advanced');
|
||||
for (var i = 0; i < elems.length; i++) {
|
||||
export function setAdvancedVisible(parent, visible) {
|
||||
const elems = parent.querySelectorAll('.advanced');
|
||||
for (let i = 0; i < elems.length; i++) {
|
||||
visible ? elems[i].classList.remove('advancedHide') : elems[i].classList.add('advancedHide');
|
||||
}
|
||||
}
|
||||
|
||||
function setContentType(parent, contentType) {
|
||||
export function setContentType(parent, contentType) {
|
||||
if (contentType === 'homevideos' || contentType === 'photos') {
|
||||
parent.querySelector('.chkEnablePhotosContainer').classList.remove('hide');
|
||||
} else {
|
||||
@@ -422,47 +426,47 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
|
||||
}
|
||||
|
||||
function setSubtitleFetchersIntoOptions(parent, options) {
|
||||
options.DisabledSubtitleFetchers = Array.prototype.map.call(Array.prototype.filter.call(parent.querySelectorAll('.chkSubtitleFetcher'), function(elem) {
|
||||
options.DisabledSubtitleFetchers = Array.prototype.map.call(Array.prototype.filter.call(parent.querySelectorAll('.chkSubtitleFetcher'), elem => {
|
||||
return !elem.checked;
|
||||
}), function(elem) {
|
||||
}), elem => {
|
||||
return elem.getAttribute('data-pluginname');
|
||||
});
|
||||
|
||||
options.SubtitleFetcherOrder = Array.prototype.map.call(parent.querySelectorAll('.subtitleFetcherItem'), function(elem) {
|
||||
options.SubtitleFetcherOrder = Array.prototype.map.call(parent.querySelectorAll('.subtitleFetcherItem'), elem => {
|
||||
return elem.getAttribute('data-pluginname');
|
||||
});
|
||||
}
|
||||
|
||||
function setMetadataFetchersIntoOptions(parent, options) {
|
||||
var sections = parent.querySelectorAll('.metadataFetcher');
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
var section = sections[i];
|
||||
var type = section.getAttribute('data-type');
|
||||
var typeOptions = getTypeOptions(options, type);
|
||||
const sections = parent.querySelectorAll('.metadataFetcher');
|
||||
for (let i = 0; i < sections.length; i++) {
|
||||
const section = sections[i];
|
||||
const type = section.getAttribute('data-type');
|
||||
let typeOptions = getTypeOptions(options, type);
|
||||
if (!typeOptions) {
|
||||
typeOptions = {
|
||||
Type: type
|
||||
};
|
||||
options.TypeOptions.push(typeOptions);
|
||||
}
|
||||
typeOptions.MetadataFetchers = Array.prototype.map.call(Array.prototype.filter.call(section.querySelectorAll('.chkMetadataFetcher'), function(elem) {
|
||||
typeOptions.MetadataFetchers = Array.prototype.map.call(Array.prototype.filter.call(section.querySelectorAll('.chkMetadataFetcher'), elem => {
|
||||
return elem.checked;
|
||||
}), function(elem) {
|
||||
}), elem => {
|
||||
return elem.getAttribute('data-pluginname');
|
||||
});
|
||||
|
||||
typeOptions.MetadataFetcherOrder = Array.prototype.map.call(section.querySelectorAll('.metadataFetcherItem'), function(elem) {
|
||||
typeOptions.MetadataFetcherOrder = Array.prototype.map.call(section.querySelectorAll('.metadataFetcherItem'), elem => {
|
||||
return elem.getAttribute('data-pluginname');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function setImageFetchersIntoOptions(parent, options) {
|
||||
var sections = parent.querySelectorAll('.imageFetcher');
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
var section = sections[i];
|
||||
var type = section.getAttribute('data-type');
|
||||
var typeOptions = getTypeOptions(options, type);
|
||||
const sections = parent.querySelectorAll('.imageFetcher');
|
||||
for (let i = 0; i < sections.length; i++) {
|
||||
const section = sections[i];
|
||||
const type = section.getAttribute('data-type');
|
||||
let typeOptions = getTypeOptions(options, type);
|
||||
if (!typeOptions) {
|
||||
typeOptions = {
|
||||
Type: type
|
||||
@@ -470,23 +474,23 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
|
||||
options.TypeOptions.push(typeOptions);
|
||||
}
|
||||
|
||||
typeOptions.ImageFetchers = Array.prototype.map.call(Array.prototype.filter.call(section.querySelectorAll('.chkImageFetcher'), function(elem) {
|
||||
typeOptions.ImageFetchers = Array.prototype.map.call(Array.prototype.filter.call(section.querySelectorAll('.chkImageFetcher'), elem => {
|
||||
return elem.checked;
|
||||
}), function(elem) {
|
||||
}), elem => {
|
||||
return elem.getAttribute('data-pluginname');
|
||||
});
|
||||
|
||||
typeOptions.ImageFetcherOrder = Array.prototype.map.call(section.querySelectorAll('.imageFetcherItem'), function(elem) {
|
||||
typeOptions.ImageFetcherOrder = Array.prototype.map.call(section.querySelectorAll('.imageFetcherItem'), elem => {
|
||||
return elem.getAttribute('data-pluginname');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function setImageOptionsIntoOptions(parent, options) {
|
||||
var originalTypeOptions = (currentLibraryOptions || {}).TypeOptions || [];
|
||||
for (var i = 0; i < originalTypeOptions.length; i++) {
|
||||
var originalTypeOption = originalTypeOptions[i];
|
||||
var typeOptions = getTypeOptions(options, originalTypeOption.Type);
|
||||
function setImageOptionsIntoOptions(options) {
|
||||
const originalTypeOptions = (currentLibraryOptions || {}).TypeOptions || [];
|
||||
for (let i = 0; i < originalTypeOptions.length; i++) {
|
||||
const originalTypeOption = originalTypeOptions[i];
|
||||
let typeOptions = getTypeOptions(options, originalTypeOption.Type);
|
||||
|
||||
if (!typeOptions) {
|
||||
typeOptions = {
|
||||
@@ -498,8 +502,8 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
|
||||
}
|
||||
}
|
||||
|
||||
function getLibraryOptions(parent) {
|
||||
var options = {
|
||||
export function getLibraryOptions(parent) {
|
||||
const options = {
|
||||
EnableArchiveMediaFiles: false,
|
||||
EnablePhotos: parent.querySelector('.chkEnablePhotos').checked,
|
||||
EnableRealtimeMonitor: parent.querySelector('.chkEnableRealtimeMonitor').checked,
|
||||
@@ -520,39 +524,39 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
|
||||
SkipSubtitlesIfAudioTrackMatches: parent.querySelector('#chkSkipIfAudioTrackPresent').checked,
|
||||
SaveSubtitlesWithMedia: parent.querySelector('#chkSaveSubtitlesLocally').checked,
|
||||
RequirePerfectSubtitleMatch: parent.querySelector('#chkRequirePerfectMatch').checked,
|
||||
MetadataSavers: Array.prototype.map.call(Array.prototype.filter.call(parent.querySelectorAll('.chkMetadataSaver'), function(elem) {
|
||||
MetadataSavers: Array.prototype.map.call(Array.prototype.filter.call(parent.querySelectorAll('.chkMetadataSaver'), elem => {
|
||||
return elem.checked;
|
||||
}), function(elem) {
|
||||
}), elem => {
|
||||
return elem.getAttribute('data-pluginname');
|
||||
}),
|
||||
TypeOptions: []
|
||||
};
|
||||
|
||||
options.LocalMetadataReaderOrder = Array.prototype.map.call(parent.querySelectorAll('.localReaderOption'), function(elem) {
|
||||
options.LocalMetadataReaderOrder = Array.prototype.map.call(parent.querySelectorAll('.localReaderOption'), elem => {
|
||||
return elem.getAttribute('data-pluginname');
|
||||
});
|
||||
options.SubtitleDownloadLanguages = Array.prototype.map.call(Array.prototype.filter.call(parent.querySelectorAll('.chkSubtitleLanguage'), function(elem) {
|
||||
options.SubtitleDownloadLanguages = Array.prototype.map.call(Array.prototype.filter.call(parent.querySelectorAll('.chkSubtitleLanguage'), elem => {
|
||||
return elem.checked;
|
||||
}), function(elem) {
|
||||
}), elem => {
|
||||
return elem.getAttribute('data-lang');
|
||||
});
|
||||
setSubtitleFetchersIntoOptions(parent, options);
|
||||
setMetadataFetchersIntoOptions(parent, options);
|
||||
setImageFetchersIntoOptions(parent, options);
|
||||
setImageOptionsIntoOptions(parent, options);
|
||||
setImageOptionsIntoOptions(options);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
function getOrderedPlugins(plugins, configuredOrder) {
|
||||
plugins = plugins.slice(0);
|
||||
plugins.sort(function(a, b) {
|
||||
plugins.sort((a, b) => {
|
||||
return a = configuredOrder.indexOf(a.Name), b = configuredOrder.indexOf(b.Name), a < b ? -1 : a > b ? 1 : 0;
|
||||
});
|
||||
return plugins;
|
||||
}
|
||||
|
||||
function setLibraryOptions(parent, options) {
|
||||
export function setLibraryOptions(parent, options) {
|
||||
currentLibraryOptions = options;
|
||||
currentAvailableOptions = parent.availableOptions;
|
||||
parent.querySelector('#selectLanguage').value = options.PreferredMetadataLanguage || '';
|
||||
@@ -573,11 +577,11 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
|
||||
parent.querySelector('#chkSaveSubtitlesLocally').checked = options.SaveSubtitlesWithMedia;
|
||||
parent.querySelector('#chkSkipIfAudioTrackPresent').checked = options.SkipSubtitlesIfAudioTrackMatches;
|
||||
parent.querySelector('#chkRequirePerfectMatch').checked = options.RequirePerfectSubtitleMatch;
|
||||
Array.prototype.forEach.call(parent.querySelectorAll('.chkMetadataSaver'), function(elem) {
|
||||
elem.checked = options.MetadataSavers ? -1 !== options.MetadataSavers.indexOf(elem.getAttribute('data-pluginname')) : 'true' === elem.getAttribute('data-defaultenabled');
|
||||
Array.prototype.forEach.call(parent.querySelectorAll('.chkMetadataSaver'), elem => {
|
||||
elem.checked = options.MetadataSavers ? options.MetadataSavers.includes(elem.getAttribute('data-pluginname')) : 'true' === elem.getAttribute('data-defaultenabled');
|
||||
});
|
||||
Array.prototype.forEach.call(parent.querySelectorAll('.chkSubtitleLanguage'), function(elem) {
|
||||
elem.checked = !!options.SubtitleDownloadLanguages && -1 !== options.SubtitleDownloadLanguages.indexOf(elem.getAttribute('data-lang'));
|
||||
Array.prototype.forEach.call(parent.querySelectorAll('.chkSubtitleLanguage'), elem => {
|
||||
elem.checked = !!options.SubtitleDownloadLanguages && options.SubtitleDownloadLanguages.includes(elem.getAttribute('data-lang'));
|
||||
});
|
||||
renderMetadataReaders(parent, getOrderedPlugins(parent.availableOptions.MetadataReaders, options.LocalMetadataReaderOrder || []));
|
||||
renderMetadataFetchers(parent, parent.availableOptions, options);
|
||||
@@ -585,14 +589,14 @@ define(['globalize', 'dom', 'emby-checkbox', 'emby-select', 'emby-input'], funct
|
||||
renderSubtitleFetchers(parent, parent.availableOptions, options);
|
||||
}
|
||||
|
||||
var currentLibraryOptions;
|
||||
var currentAvailableOptions;
|
||||
let currentLibraryOptions;
|
||||
let currentAvailableOptions;
|
||||
|
||||
return {
|
||||
embed: embed,
|
||||
setContentType: setContentType,
|
||||
getLibraryOptions: getLibraryOptions,
|
||||
setLibraryOptions: setLibraryOptions,
|
||||
setAdvancedVisible: setAdvancedVisible
|
||||
};
|
||||
});
|
||||
/* eslint-enable indent */
|
||||
export default {
|
||||
embed: embed,
|
||||
setContentType: setContentType,
|
||||
getLibraryOptions: getLibraryOptions,
|
||||
setLibraryOptions: setLibraryOptions,
|
||||
setAdvancedVisible: setAdvancedVisible
|
||||
};
|
||||
|
||||
@@ -1,19 +1,32 @@
|
||||
define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutManager', 'globalize', 'datetime', 'cardBuilder', 'css!./listview', 'emby-ratingbutton', 'emby-playstatebutton'], function (itemHelper, mediaInfo, indicators, connectionManager, layoutManager, globalize, datetime, cardBuilder) {
|
||||
'use strict';
|
||||
/* eslint-disable indent */
|
||||
|
||||
/**
|
||||
* Module for display list view.
|
||||
* @module components/listview/listview
|
||||
*/
|
||||
|
||||
import itemHelper from 'itemHelper';
|
||||
import mediaInfo from 'mediaInfo';
|
||||
import indicators from 'indicators';
|
||||
import connectionManager from 'connectionManager';
|
||||
import layoutManager from 'layoutManager';
|
||||
import globalize from 'globalize';
|
||||
import datetime from 'datetime';
|
||||
import cardBuilder from 'cardBuilder';
|
||||
import 'css!./listview';
|
||||
import 'emby-ratingbutton';
|
||||
import 'emby-playstatebutton';
|
||||
|
||||
function getIndex(item, options) {
|
||||
|
||||
if (options.index === 'disc') {
|
||||
|
||||
return item.ParentIndexNumber == null ? '' : globalize.translate('ValueDiscNumber', item.ParentIndexNumber);
|
||||
}
|
||||
|
||||
var sortBy = (options.sortBy || '').toLowerCase();
|
||||
var code;
|
||||
var name;
|
||||
const sortBy = (options.sortBy || '').toLowerCase();
|
||||
let code;
|
||||
let name;
|
||||
|
||||
if (sortBy.indexOf('sortname') === 0) {
|
||||
|
||||
if (item.Type === 'Episode') {
|
||||
return '';
|
||||
}
|
||||
@@ -29,11 +42,9 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
return name.toUpperCase();
|
||||
}
|
||||
if (sortBy.indexOf('officialrating') === 0) {
|
||||
|
||||
return item.OfficialRating || globalize.translate('Unrated');
|
||||
}
|
||||
if (sortBy.indexOf('communityrating') === 0) {
|
||||
|
||||
if (item.CommunityRating == null) {
|
||||
return globalize.translate('Unrated');
|
||||
}
|
||||
@@ -41,7 +52,6 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
return Math.floor(item.CommunityRating);
|
||||
}
|
||||
if (sortBy.indexOf('criticrating') === 0) {
|
||||
|
||||
if (item.CriticRating == null) {
|
||||
return globalize.translate('Unrated');
|
||||
}
|
||||
@@ -49,7 +59,6 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
return Math.floor(item.CriticRating);
|
||||
}
|
||||
if (sortBy.indexOf('albumartist') === 0) {
|
||||
|
||||
// SortName
|
||||
if (!item.AlbumArtist) {
|
||||
return '';
|
||||
@@ -68,11 +77,10 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
}
|
||||
|
||||
function getImageUrl(item, width) {
|
||||
|
||||
var apiClient = connectionManager.getApiClient(item.ServerId);
|
||||
const apiClient = connectionManager.getApiClient(item.ServerId);
|
||||
let itemId;
|
||||
|
||||
var options = {
|
||||
const options = {
|
||||
maxWidth: width * 2,
|
||||
type: 'Primary'
|
||||
};
|
||||
@@ -98,9 +106,8 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
}
|
||||
|
||||
function getChannelImageUrl(item, width) {
|
||||
|
||||
var apiClient = connectionManager.getApiClient(item.ServerId);
|
||||
var options = {
|
||||
const apiClient = connectionManager.getApiClient(item.ServerId);
|
||||
const options = {
|
||||
maxWidth: width * 2,
|
||||
type: 'Primary'
|
||||
};
|
||||
@@ -115,9 +122,9 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
}
|
||||
|
||||
function getTextLinesHtml(textlines, isLargeStyle) {
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
var largeTitleTagName = layoutManager.tv ? 'h2' : 'div';
|
||||
const largeTitleTagName = layoutManager.tv ? 'h2' : 'div';
|
||||
|
||||
for (const [i, text] of textlines.entries()) {
|
||||
if (!text) {
|
||||
@@ -126,7 +133,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
|
||||
if (i === 0) {
|
||||
if (isLargeStyle) {
|
||||
html += '<' + largeTitleTagName + ' class="listItemBodyText">';
|
||||
html += `<${largeTitleTagName} class="listItemBodyText">`;
|
||||
} else {
|
||||
html += '<div class="listItemBodyText">';
|
||||
}
|
||||
@@ -135,7 +142,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
}
|
||||
html += (textlines[i] || ' ');
|
||||
if (i === 0 && isLargeStyle) {
|
||||
html += '</' + largeTitleTagName + '>';
|
||||
html += `</${largeTitleTagName}>`;
|
||||
} else {
|
||||
html += '</div>';
|
||||
}
|
||||
@@ -145,14 +152,12 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
}
|
||||
|
||||
function getRightButtonsHtml(options) {
|
||||
let html = '';
|
||||
|
||||
var html = '';
|
||||
for (let i = 0, length = options.rightButtons.length; i < length; i++) {
|
||||
const button = options.rightButtons[i];
|
||||
|
||||
for (var i = 0, length = options.rightButtons.length; i < length; i++) {
|
||||
|
||||
var button = options.rightButtons[i];
|
||||
|
||||
html += '<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="custom" data-customaction="' + button.id + '" title="' + button.title + '"><span class="material-icons ' + button.icon + '"></span></button>';
|
||||
html += `<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="custom" data-customaction="${button.id}" title="${button.title}"><span class="material-icons ${button.icon}"></span></button>`;
|
||||
}
|
||||
|
||||
return html;
|
||||
@@ -162,37 +167,33 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
return item.Id;
|
||||
}
|
||||
|
||||
function getListViewHtml(options) {
|
||||
export function getListViewHtml(options) {
|
||||
const items = options.items;
|
||||
|
||||
var items = options.items;
|
||||
let groupTitle = '';
|
||||
const action = options.action || 'link';
|
||||
|
||||
var groupTitle = '';
|
||||
var action = options.action || 'link';
|
||||
const isLargeStyle = options.imageSize === 'large';
|
||||
const enableOverview = options.enableOverview;
|
||||
|
||||
var isLargeStyle = options.imageSize === 'large';
|
||||
var enableOverview = options.enableOverview;
|
||||
const clickEntireItem = layoutManager.tv ? true : false;
|
||||
const outerTagName = clickEntireItem ? 'button' : 'div';
|
||||
const enableSideMediaInfo = options.enableSideMediaInfo != null ? options.enableSideMediaInfo : true;
|
||||
|
||||
var clickEntireItem = layoutManager.tv ? true : false;
|
||||
var outerTagName = clickEntireItem ? 'button' : 'div';
|
||||
var enableSideMediaInfo = options.enableSideMediaInfo != null ? options.enableSideMediaInfo : true;
|
||||
let outerHtml = '';
|
||||
|
||||
var outerHtml = '';
|
||||
const enableContentWrapper = options.enableOverview && !layoutManager.tv;
|
||||
const containerAlbumArtistIds = (options.containerAlbumArtists || []).map(getId);
|
||||
|
||||
var enableContentWrapper = options.enableOverview && !layoutManager.tv;
|
||||
var containerAlbumArtistIds = (options.containerAlbumArtists || []).map(getId);
|
||||
for (let i = 0, length = items.length; i < length; i++) {
|
||||
const item = items[i];
|
||||
|
||||
for (var i = 0, length = items.length; i < length; i++) {
|
||||
|
||||
var item = items[i];
|
||||
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
if (options.showIndex) {
|
||||
|
||||
var itemGroupTitle = getIndex(item, options);
|
||||
const itemGroupTitle = getIndex(item, options);
|
||||
|
||||
if (itemGroupTitle !== groupTitle) {
|
||||
|
||||
if (html) {
|
||||
html += '</div>';
|
||||
}
|
||||
@@ -211,7 +212,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
}
|
||||
}
|
||||
|
||||
var cssClass = 'listItem';
|
||||
let cssClass = 'listItem';
|
||||
|
||||
if (options.border || (options.highlight !== false && !layoutManager.tv)) {
|
||||
cssClass += ' listItem-border';
|
||||
@@ -225,37 +226,33 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
cssClass += ' listItem-focusscale';
|
||||
}
|
||||
|
||||
var downloadWidth = 80;
|
||||
let downloadWidth = 80;
|
||||
|
||||
if (isLargeStyle) {
|
||||
cssClass += ' listItem-largeImage';
|
||||
downloadWidth = 500;
|
||||
}
|
||||
|
||||
var playlistItemId = item.PlaylistItemId ? (' data-playlistitemid="' + item.PlaylistItemId + '"') : '';
|
||||
const playlistItemId = item.PlaylistItemId ? (` data-playlistitemid="${item.PlaylistItemId}"`) : '';
|
||||
|
||||
var positionTicksData = item.UserData && item.UserData.PlaybackPositionTicks ? (' data-positionticks="' + item.UserData.PlaybackPositionTicks + '"') : '';
|
||||
var collectionIdData = options.collectionId ? (' data-collectionid="' + options.collectionId + '"') : '';
|
||||
var playlistIdData = options.playlistId ? (' data-playlistid="' + options.playlistId + '"') : '';
|
||||
var mediaTypeData = item.MediaType ? (' data-mediatype="' + item.MediaType + '"') : '';
|
||||
var collectionTypeData = item.CollectionType ? (' data-collectiontype="' + item.CollectionType + '"') : '';
|
||||
var channelIdData = item.ChannelId ? (' data-channelid="' + item.ChannelId + '"') : '';
|
||||
const positionTicksData = item.UserData && item.UserData.PlaybackPositionTicks ? (` data-positionticks="${item.UserData.PlaybackPositionTicks}"`) : '';
|
||||
const collectionIdData = options.collectionId ? (` data-collectionid="${options.collectionId}"`) : '';
|
||||
const playlistIdData = options.playlistId ? (` data-playlistid="${options.playlistId}"`) : '';
|
||||
const mediaTypeData = item.MediaType ? (` data-mediatype="${item.MediaType}"`) : '';
|
||||
const collectionTypeData = item.CollectionType ? (` data-collectiontype="${item.CollectionType}"`) : '';
|
||||
const channelIdData = item.ChannelId ? (` data-channelid="${item.ChannelId}"`) : '';
|
||||
|
||||
if (enableContentWrapper) {
|
||||
|
||||
cssClass += ' listItem-withContentWrapper';
|
||||
}
|
||||
|
||||
html += '<' + outerTagName + ' class="' + cssClass + '"' + playlistItemId + ' data-action="' + action + '" data-isfolder="' + item.IsFolder + '" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-type="' + item.Type + '"' + mediaTypeData + collectionTypeData + channelIdData + positionTicksData + collectionIdData + playlistIdData + '>';
|
||||
html += `<${outerTagName} class="${cssClass}"${playlistItemId} data-action="${action}" data-isfolder="${item.IsFolder}" data-id="${item.Id}" data-serverid="${item.ServerId}" data-type="${item.Type}"${mediaTypeData}${collectionTypeData}${channelIdData}${positionTicksData}${collectionIdData}${playlistIdData}>`;
|
||||
|
||||
if (enableContentWrapper) {
|
||||
|
||||
html += '<div class="listItem-content">';
|
||||
}
|
||||
|
||||
if (!clickEntireItem && options.dragHandle) {
|
||||
//html += '<button is="paper-icon-button-light" class="listViewDragHandle listItemButton"><span class="material-icons drag_handle"></span></button>';
|
||||
// Firefox and Edge are not allowing the button to be draggable
|
||||
html += '<span class="listViewDragHandle material-icons listItemIcon listItemIcon-transparent drag_handle"></span>';
|
||||
}
|
||||
|
||||
@@ -267,13 +264,13 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
imageClass += ' listItemImage-large-tv';
|
||||
}
|
||||
|
||||
var playOnImageClick = options.imagePlayButton && !layoutManager.tv;
|
||||
const playOnImageClick = options.imagePlayButton && !layoutManager.tv;
|
||||
|
||||
if (!clickEntireItem) {
|
||||
imageClass += ' itemAction';
|
||||
}
|
||||
|
||||
var imageAction = playOnImageClick ? 'link' : action;
|
||||
const imageAction = playOnImageClick ? 'link' : action;
|
||||
|
||||
if (imgUrl) {
|
||||
html += '<div data-action="' + imageAction + '" class="' + imageClass + ' lazy" data-src="' + imgUrl + '" item-icon>';
|
||||
@@ -281,18 +278,18 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
html += '<div class="' + imageClass + ' cardImageContainer ' + cardBuilder.getDefaultBackgroundClass(item.Name) + '">' + cardBuilder.getDefaultText(item, options);
|
||||
}
|
||||
|
||||
var indicatorsHtml = '';
|
||||
let indicatorsHtml = '';
|
||||
indicatorsHtml += indicators.getPlayedIndicatorHtml(item);
|
||||
|
||||
if (indicatorsHtml) {
|
||||
html += '<div class="indicators listItemIndicators">' + indicatorsHtml + '</div>';
|
||||
html += `<div class="indicators listItemIndicators">${indicatorsHtml}</div>`;
|
||||
}
|
||||
|
||||
if (playOnImageClick) {
|
||||
html += '<button is="paper-icon-button-light" class="listItemImageButton itemAction" data-action="resume"><span class="material-icons listItemImageButton-icon play_arrow"></span></button>';
|
||||
}
|
||||
|
||||
var progressHtml = indicators.getProgressBarHtml(item, {
|
||||
const progressHtml = indicators.getProgressBarHtml(item, {
|
||||
containerClass: 'listItemProgressBar'
|
||||
});
|
||||
|
||||
@@ -303,13 +300,12 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
}
|
||||
|
||||
if (options.showIndexNumberLeft) {
|
||||
|
||||
html += '<div class="listItem-indexnumberleft">';
|
||||
html += (item.IndexNumber || ' ');
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
var textlines = [];
|
||||
const textlines = [];
|
||||
|
||||
if (options.showProgramDateTime) {
|
||||
textlines.push(datetime.toLocaleString(datetime.parseISO8601Date(item.StartDate), {
|
||||
@@ -332,7 +328,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
}
|
||||
}
|
||||
|
||||
var parentTitle = null;
|
||||
let parentTitle = null;
|
||||
|
||||
if (options.showParentTitle) {
|
||||
if (item.Type === 'Episode') {
|
||||
@@ -342,18 +338,16 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
}
|
||||
}
|
||||
|
||||
var displayName = itemHelper.getDisplayName(item, {
|
||||
let displayName = itemHelper.getDisplayName(item, {
|
||||
includeParentInfo: options.includeParentInfoInTitle
|
||||
});
|
||||
|
||||
if (options.showIndexNumber && item.IndexNumber != null) {
|
||||
displayName = item.IndexNumber + '. ' + displayName;
|
||||
displayName = `${item.IndexNumber}. ${displayName}`;
|
||||
}
|
||||
|
||||
if (options.showParentTitle && options.parentTitleWithTitle) {
|
||||
|
||||
if (displayName) {
|
||||
|
||||
if (parentTitle) {
|
||||
parentTitle += ' - ';
|
||||
}
|
||||
@@ -371,29 +365,25 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
|
||||
if (item.IsFolder) {
|
||||
if (options.artist !== false) {
|
||||
|
||||
if (item.AlbumArtist && item.Type === 'MusicAlbum') {
|
||||
textlines.push(item.AlbumArtist);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
var showArtist = options.artist === true;
|
||||
var artistItems = item.ArtistItems;
|
||||
let showArtist = options.artist === true;
|
||||
const artistItems = item.ArtistItems;
|
||||
|
||||
if (!showArtist && options.artist !== false) {
|
||||
|
||||
if (!artistItems || !artistItems.length) {
|
||||
showArtist = true;
|
||||
} else if (artistItems.length > 1 || containerAlbumArtistIds.indexOf(artistItems[0].Id) === -1) {
|
||||
} else if (artistItems.length > 1 || !containerAlbumArtistIds.includes(artistItems[0].Id)) {
|
||||
showArtist = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (showArtist) {
|
||||
|
||||
if (artistItems && item.Type !== 'MusicAlbum') {
|
||||
textlines.push(artistItems.map(function (a) {
|
||||
textlines.push(artistItems.map(a => {
|
||||
return a.Name;
|
||||
}).join(', '));
|
||||
}
|
||||
@@ -401,7 +391,6 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
}
|
||||
|
||||
if (item.Type === 'TvChannel') {
|
||||
|
||||
if (item.CurrentProgram) {
|
||||
textlines.push(itemHelper.getDisplayName(item.CurrentProgram));
|
||||
}
|
||||
@@ -416,21 +405,22 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
cssClass += ' listItemBody-noleftpadding';
|
||||
}
|
||||
|
||||
html += '<div class="' + cssClass + '">';
|
||||
html += `<div class="${cssClass}">`;
|
||||
|
||||
html += getTextLinesHtml(textlines, isLargeStyle);
|
||||
|
||||
if (options.mediaInfo !== false) {
|
||||
if (!enableSideMediaInfo) {
|
||||
const mediaInfoClass = 'secondary listItemMediaInfo listItemBodyText';
|
||||
|
||||
var mediaInfoClass = 'secondary listItemMediaInfo listItemBodyText';
|
||||
|
||||
html += '<div class="' + mediaInfoClass + '">' + mediaInfo.getPrimaryMediaInfoHtml(item, {
|
||||
html += `<div class="${mediaInfoClass}">`;
|
||||
html += mediaInfo.getPrimaryMediaInfoHtml(item, {
|
||||
episodeTitle: false,
|
||||
originalAirDate: false,
|
||||
subtitles: false
|
||||
|
||||
}) + '</div>';
|
||||
});
|
||||
html += '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,7 +434,8 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
|
||||
if (options.mediaInfo !== false) {
|
||||
if (enableSideMediaInfo) {
|
||||
html += '<div class="secondary listItemMediaInfo">' + mediaInfo.getPrimaryMediaInfoHtml(item, {
|
||||
html += '<div class="secondary listItemMediaInfo">';
|
||||
html += mediaInfo.getPrimaryMediaInfoHtml(item, {
|
||||
|
||||
year: false,
|
||||
container: false,
|
||||
@@ -452,7 +443,8 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
criticRating: false,
|
||||
endsAt: false
|
||||
|
||||
}) + '</div>';
|
||||
});
|
||||
html += '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,7 +455,6 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
html += '<div class="listViewUserDataButtons">';
|
||||
|
||||
if (!clickEntireItem) {
|
||||
|
||||
if (options.addToListButton) {
|
||||
html += '<button is="paper-icon-button-light" class="listItemButton itemAction" data-action="addtoplaylist"><span class="material-icons playlist_add"></span></button>';
|
||||
}
|
||||
@@ -477,9 +468,8 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
}
|
||||
|
||||
if (options.enableUserDataButtons !== false) {
|
||||
|
||||
var userData = item.UserData || {};
|
||||
var likes = userData.Likes == null ? '' : userData.Likes;
|
||||
const userData = item.UserData || {};
|
||||
const likes = userData.Likes == null ? '' : userData.Likes;
|
||||
|
||||
if (itemHelper.canMarkPlayed(item) && options.enablePlayedButton !== false) {
|
||||
html += '<button is="emby-playstatebutton" type="button" class="listItemButton paper-icon-button-light" data-id="' + item.Id + '" data-serverid="' + item.ServerId + '" data-itemtype="' + item.Type + '" data-played="' + (userData.Played) + '"><span class="material-icons check"></span></button>';
|
||||
@@ -506,7 +496,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
}
|
||||
}
|
||||
|
||||
html += '</' + outerTagName + '>';
|
||||
html += `</${outerTagName}>`;
|
||||
|
||||
outerHtml += html;
|
||||
}
|
||||
@@ -514,7 +504,7 @@ define(['itemHelper', 'mediaInfo', 'indicators', 'connectionManager', 'layoutMan
|
||||
return outerHtml;
|
||||
}
|
||||
|
||||
return {
|
||||
getListViewHtml: getListViewHtml
|
||||
};
|
||||
});
|
||||
/* eslint-enable indent */
|
||||
export default {
|
||||
getListViewHtml: getListViewHtml
|
||||
};
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
@@ -1,10 +1,6 @@
|
||||
define(['components/loading/loadingLegacy', 'browser', 'css!./loading'], function (loadingLegacy, browser) {
|
||||
define(['css!./loading'], function () {
|
||||
'use strict';
|
||||
|
||||
if (browser.tizen || browser.operaTv || browser.chromecast || browser.orsay || browser.web0s || browser.ps4) {
|
||||
return loadingLegacy;
|
||||
}
|
||||
|
||||
var loadingElem;
|
||||
var layer1;
|
||||
var layer2;
|
||||
@@ -18,7 +14,6 @@ define(['components/loading/loadingLegacy', 'browser', 'css!./loading'], functio
|
||||
var elem = loadingElem;
|
||||
|
||||
if (!elem) {
|
||||
|
||||
elem = document.createElement('div');
|
||||
loadingElem = elem;
|
||||
|
||||
@@ -60,7 +55,6 @@ define(['components/loading/loadingLegacy', 'browser', 'css!./loading'], functio
|
||||
var elem = loadingElem;
|
||||
|
||||
if (elem) {
|
||||
|
||||
elem.classList.remove('mdlSpinnerActive');
|
||||
|
||||
elem.classList.remove('mdl-spinner__layer-1-active');
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
.loading-spinner {
|
||||
margin-top: -3em;
|
||||
margin-left: -3em;
|
||||
width: 6em;
|
||||
height: 6em;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
z-index: 9999999;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
define(['require', 'css!./loadingLegacy'], function (require) {
|
||||
'use strict';
|
||||
|
||||
var loadingElem;
|
||||
|
||||
return {
|
||||
show: function () {
|
||||
var elem = loadingElem;
|
||||
if (!elem) {
|
||||
elem = document.createElement('img');
|
||||
elem.src = require.toUrl('.').split('?')[0] + '/loader.gif';
|
||||
|
||||
loadingElem = elem;
|
||||
elem.classList.add('loading-spinner');
|
||||
|
||||
document.body.appendChild(elem);
|
||||
}
|
||||
|
||||
elem.classList.remove('hide');
|
||||
},
|
||||
hide: function () {
|
||||
var elem = loadingElem;
|
||||
if (elem) {
|
||||
elem.classList.add('hide');
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -1,31 +1,17 @@
|
||||
define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom, browser, events) {
|
||||
'use strict';
|
||||
import dom from 'dom';
|
||||
import browser from 'browser';
|
||||
import events from 'events';
|
||||
import 'emby-tabs';
|
||||
import 'emby-button';
|
||||
|
||||
var tabOwnerView;
|
||||
var queryScope = document.querySelector('.skinHeader');
|
||||
var footerTabsContainer;
|
||||
var headerTabsContainer;
|
||||
var tabsElem;
|
||||
/* eslint-disable indent */
|
||||
|
||||
function enableTabsInFooter() {
|
||||
return false;
|
||||
}
|
||||
|
||||
function getTabsContainerElem() {
|
||||
}
|
||||
|
||||
function ensureElements(enableInFooter) {
|
||||
|
||||
if (enableInFooter) {
|
||||
if (!footerTabsContainer) {
|
||||
footerTabsContainer = document.createElement('div');
|
||||
footerTabsContainer.classList.add('footerTabs');
|
||||
footerTabsContainer.classList.add('sectionTabs');
|
||||
footerTabsContainer.classList.add('hide');
|
||||
//appFooter.add(footerTabsContainer);
|
||||
}
|
||||
}
|
||||
let tabOwnerView;
|
||||
const queryScope = document.querySelector('.skinHeader');
|
||||
let headerTabsContainer;
|
||||
let tabsElem;
|
||||
|
||||
function ensureElements() {
|
||||
if (!headerTabsContainer) {
|
||||
headerTabsContainer = queryScope.querySelector('.headerTabs');
|
||||
}
|
||||
@@ -37,14 +23,12 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
|
||||
}
|
||||
|
||||
function allowSwipe(target) {
|
||||
|
||||
function allowSwipeOn(elem) {
|
||||
|
||||
if (dom.parentWithTag(elem, 'input')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var classList = elem.classList;
|
||||
const classList = elem.classList;
|
||||
if (classList) {
|
||||
return !classList.contains('scrollX') && !classList.contains('animatedScrollX');
|
||||
}
|
||||
@@ -52,7 +36,7 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
|
||||
return true;
|
||||
}
|
||||
|
||||
var parent = target;
|
||||
let parent = target;
|
||||
while (parent != null) {
|
||||
if (!allowSwipeOn(parent)) {
|
||||
return false;
|
||||
@@ -64,28 +48,25 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
|
||||
}
|
||||
|
||||
function configureSwipeTabs(view, tabsElem, getTabContainersFn) {
|
||||
|
||||
if (!browser.touch) {
|
||||
return;
|
||||
}
|
||||
|
||||
// implement without hammer
|
||||
var pageCount = getTabContainersFn().length;
|
||||
var onSwipeLeft = function (e, target) {
|
||||
const onSwipeLeft = function (e, target) {
|
||||
if (allowSwipe(target) && view.contains(target)) {
|
||||
tabsElem.selectNext();
|
||||
}
|
||||
};
|
||||
|
||||
var onSwipeRight = function (e, target) {
|
||||
const onSwipeRight = function (e, target) {
|
||||
if (allowSwipe(target) && view.contains(target)) {
|
||||
tabsElem.selectPrevious();
|
||||
}
|
||||
};
|
||||
|
||||
require(['touchHelper'], function (TouchHelper) {
|
||||
|
||||
var touchHelper = new TouchHelper(view.parentNode.parentNode);
|
||||
import('touchHelper').then(({default: TouchHelper}) => {
|
||||
const touchHelper = new TouchHelper(view.parentNode.parentNode);
|
||||
|
||||
events.on(touchHelper, 'swipeleft', onSwipeLeft);
|
||||
events.on(touchHelper, 'swiperight', onSwipeRight);
|
||||
@@ -96,29 +77,20 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
|
||||
});
|
||||
}
|
||||
|
||||
function setTabs(view, selectedIndex, getTabsFn, getTabContainersFn, onBeforeTabChange, onTabChange, setSelectedIndex) {
|
||||
|
||||
var enableInFooter = enableTabsInFooter();
|
||||
|
||||
export function setTabs(view, selectedIndex, getTabsFn, getTabContainersFn, onBeforeTabChange, onTabChange, setSelectedIndex) {
|
||||
if (!view) {
|
||||
if (tabOwnerView) {
|
||||
|
||||
if (!headerTabsContainer) {
|
||||
headerTabsContainer = queryScope.querySelector('.headerTabs');
|
||||
}
|
||||
|
||||
ensureElements(enableInFooter);
|
||||
ensureElements();
|
||||
|
||||
document.body.classList.remove('withSectionTabs');
|
||||
|
||||
headerTabsContainer.innerHTML = '';
|
||||
headerTabsContainer.classList.add('hide');
|
||||
|
||||
if (footerTabsContainer) {
|
||||
footerTabsContainer.innerHTML = '';
|
||||
footerTabsContainer.classList.add('hide');
|
||||
}
|
||||
|
||||
tabOwnerView = null;
|
||||
}
|
||||
return {
|
||||
@@ -127,28 +99,26 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
|
||||
};
|
||||
}
|
||||
|
||||
ensureElements(enableInFooter);
|
||||
ensureElements();
|
||||
|
||||
var tabsContainerElem = enableInFooter ? footerTabsContainer : headerTabsContainer;
|
||||
const tabsContainerElem = headerTabsContainer;
|
||||
|
||||
if (!tabOwnerView) {
|
||||
tabsContainerElem.classList.remove('hide');
|
||||
}
|
||||
|
||||
if (tabOwnerView !== view) {
|
||||
let index = 0;
|
||||
|
||||
var index = 0;
|
||||
|
||||
var indexAttribute = selectedIndex == null ? '' : (' data-index="' + selectedIndex + '"');
|
||||
var tabsHtml = '<div is="emby-tabs"' + indexAttribute + ' class="tabs-viewmenubar"><div class="emby-tabs-slider" style="white-space:nowrap;">' + getTabsFn().map(function (t) {
|
||||
|
||||
var tabClass = 'emby-tab-button';
|
||||
const indexAttribute = selectedIndex == null ? '' : (' data-index="' + selectedIndex + '"');
|
||||
const tabsHtml = '<div is="emby-tabs"' + indexAttribute + ' class="tabs-viewmenubar"><div class="emby-tabs-slider" style="white-space:nowrap;">' + getTabsFn().map(function (t) {
|
||||
let tabClass = 'emby-tab-button';
|
||||
|
||||
if (t.enabled === false) {
|
||||
tabClass += ' hide';
|
||||
}
|
||||
|
||||
var tabHtml;
|
||||
let tabHtml;
|
||||
|
||||
if (t.cssClass) {
|
||||
tabClass += ' ' + t.cssClass;
|
||||
@@ -162,7 +132,6 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
|
||||
|
||||
index++;
|
||||
return tabHtml;
|
||||
|
||||
}).join('') + '</div></div>';
|
||||
|
||||
tabsContainerElem.innerHTML = tabsHtml;
|
||||
@@ -176,23 +145,15 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
|
||||
configureSwipeTabs(view, tabsElem, getTabContainersFn);
|
||||
|
||||
tabsElem.addEventListener('beforetabchange', function (e) {
|
||||
|
||||
var tabContainers = getTabContainersFn();
|
||||
const tabContainers = getTabContainersFn();
|
||||
if (e.detail.previousIndex != null) {
|
||||
|
||||
var previousPanel = tabContainers[e.detail.previousIndex];
|
||||
const previousPanel = tabContainers[e.detail.previousIndex];
|
||||
if (previousPanel) {
|
||||
previousPanel.classList.remove('is-active');
|
||||
}
|
||||
}
|
||||
|
||||
var newPanel = tabContainers[e.detail.selectedTabIndex];
|
||||
|
||||
//if (e.detail.previousIndex != null && e.detail.previousIndex != e.detail.selectedTabIndex) {
|
||||
// if (newPanel.animate && (animateTabs || []).indexOf(e.detail.selectedTabIndex) != -1) {
|
||||
// fadeInRight(newPanel);
|
||||
// }
|
||||
//}
|
||||
const newPanel = tabContainers[e.detail.selectedTabIndex];
|
||||
|
||||
if (newPanel) {
|
||||
newPanel.classList.add('is-active');
|
||||
@@ -210,16 +171,11 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
|
||||
if (tabsElem.selectedIndex) {
|
||||
tabsElem.selectedIndex(selectedIndex);
|
||||
} else {
|
||||
|
||||
tabsElem.readySelectedIndex = selectedIndex;
|
||||
tabsElem.addEventListener('ready', onViewTabsReady);
|
||||
}
|
||||
}
|
||||
|
||||
//if (enableSwipe !== false) {
|
||||
// libraryBrowser.configureSwipeTabs(ownerpage, tabs);
|
||||
//}
|
||||
|
||||
return {
|
||||
tabsContainer: tabsContainerElem,
|
||||
tabs: tabsContainerElem.querySelector('[is="emby-tabs"]'),
|
||||
@@ -241,9 +197,8 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
|
||||
};
|
||||
}
|
||||
|
||||
function selectedTabIndex(index) {
|
||||
|
||||
var tabsContainerElem = headerTabsContainer;
|
||||
export function selectedTabIndex(index) {
|
||||
const tabsContainerElem = headerTabsContainer;
|
||||
|
||||
if (!tabsElem) {
|
||||
tabsElem = tabsContainerElem.querySelector('[is="emby-tabs"]');
|
||||
@@ -256,13 +211,8 @@ define(['dom', 'browser', 'events', 'emby-tabs', 'emby-button'], function (dom,
|
||||
}
|
||||
}
|
||||
|
||||
function getTabsElement() {
|
||||
export function getTabsElement() {
|
||||
return document.querySelector('.tabs-viewmenubar');
|
||||
}
|
||||
|
||||
return {
|
||||
setTabs: setTabs,
|
||||
getTabsElement: getTabsElement,
|
||||
selectedTabIndex: selectedTabIndex
|
||||
};
|
||||
});
|
||||
/* eslint-enable indent */
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionseditor/libraryoptionseditor', 'globalize', 'emby-toggle', 'emby-input', 'emby-select', 'paper-icon-button-light', 'listViewStyle', 'formDialogStyle', 'emby-button', 'flexStyles'], function (loading, dialogHelper, dom, $, libraryoptionseditor, globalize) {
|
||||
'use strict';
|
||||
/* eslint-disable indent */
|
||||
|
||||
/**
|
||||
* Module for media library creator.
|
||||
* @module components/mediaLibraryCreator/mediaLibraryCreator
|
||||
*/
|
||||
|
||||
import loading from 'loading';
|
||||
import dialogHelper from 'dialogHelper';
|
||||
import dom from 'dom';
|
||||
import $ from 'jQuery';
|
||||
import libraryoptionseditor from 'components/libraryoptionseditor/libraryoptionseditor';
|
||||
import globalize from 'globalize';
|
||||
import 'emby-toggle';
|
||||
import 'emby-input';
|
||||
import 'emby-select';
|
||||
import 'paper-icon-button-light';
|
||||
import 'listViewStyle';
|
||||
import 'formDialogStyle';
|
||||
import 'emby-button';
|
||||
import 'flexStyles';
|
||||
|
||||
function onAddLibrary() {
|
||||
if (isCreating) {
|
||||
@@ -7,7 +26,7 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed
|
||||
}
|
||||
|
||||
if (pathInfos.length == 0) {
|
||||
require(['alert'], function (alert) {
|
||||
import('alert').then(({default: alert}) => {
|
||||
alert({
|
||||
text: globalize.translate('PleaseAddAtLeastOneFolder'),
|
||||
type: 'error'
|
||||
@@ -19,23 +38,23 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed
|
||||
|
||||
isCreating = true;
|
||||
loading.show();
|
||||
var dlg = dom.parentWithClass(this, 'dlg-librarycreator');
|
||||
var name = $('#txtValue', dlg).val();
|
||||
var type = $('#selectCollectionType', dlg).val();
|
||||
const dlg = dom.parentWithClass(this, 'dlg-librarycreator');
|
||||
const name = $('#txtValue', dlg).val();
|
||||
let type = $('#selectCollectionType', dlg).val();
|
||||
|
||||
if (type == 'mixed') {
|
||||
type = null;
|
||||
}
|
||||
|
||||
var libraryOptions = libraryoptionseditor.getLibraryOptions(dlg.querySelector('.libraryOptions'));
|
||||
const libraryOptions = libraryoptionseditor.getLibraryOptions(dlg.querySelector('.libraryOptions'));
|
||||
libraryOptions.PathInfos = pathInfos;
|
||||
ApiClient.addVirtualFolder(name, type, currentOptions.refresh, libraryOptions).then(function () {
|
||||
ApiClient.addVirtualFolder(name, type, currentOptions.refresh, libraryOptions).then(() => {
|
||||
hasChanges = true;
|
||||
isCreating = false;
|
||||
loading.hide();
|
||||
dialogHelper.close(dlg);
|
||||
}, function () {
|
||||
require(['toast'], function (toast) {
|
||||
}, () => {
|
||||
import('toast').then(({default: toast}) => {
|
||||
toast(globalize.translate('ErrorAddingMediaPathToVirtualFolder'));
|
||||
});
|
||||
|
||||
@@ -46,15 +65,15 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed
|
||||
}
|
||||
|
||||
function getCollectionTypeOptionsHtml(collectionTypeOptions) {
|
||||
return collectionTypeOptions.map(function (i) {
|
||||
return '<option value="' + i.value + '">' + i.name + '</option>';
|
||||
return collectionTypeOptions.map(i => {
|
||||
return `<option value="${i.value}">${i.name}</option>`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function initEditor(page, collectionTypeOptions) {
|
||||
$('#selectCollectionType', page).html(getCollectionTypeOptionsHtml(collectionTypeOptions)).val('').on('change', function () {
|
||||
var value = this.value;
|
||||
var dlg = $(this).parents('.dialog')[0];
|
||||
const value = this.value;
|
||||
const dlg = $(this).parents('.dialog')[0];
|
||||
libraryoptionseditor.setContentType(dlg.querySelector('.libraryOptions'), value == 'mixed' ? '' : value);
|
||||
|
||||
if (value) {
|
||||
@@ -64,12 +83,12 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed
|
||||
}
|
||||
|
||||
if (value != 'mixed') {
|
||||
var index = this.selectedIndex;
|
||||
const index = this.selectedIndex;
|
||||
|
||||
if (index != -1) {
|
||||
var name = this.options[index].innerHTML.replace('*', '').replace('&', '&');
|
||||
const name = this.options[index].innerHTML.replace('*', '').replace('&', '&');
|
||||
$('#txtValue', dlg).val(name);
|
||||
var folderOption = collectionTypeOptions.filter(function (i) {
|
||||
const folderOption = collectionTypeOptions.filter(i => {
|
||||
return i.value == value;
|
||||
})[0];
|
||||
$('.collectionTypeFieldDescription', dlg).html(folderOption.message || '');
|
||||
@@ -83,15 +102,15 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed
|
||||
}
|
||||
|
||||
function onToggleAdvancedChange() {
|
||||
var dlg = dom.parentWithClass(this, 'dlg-librarycreator');
|
||||
const dlg = dom.parentWithClass(this, 'dlg-librarycreator');
|
||||
libraryoptionseditor.setAdvancedVisible(dlg.querySelector('.libraryOptions'), this.checked);
|
||||
}
|
||||
|
||||
function onAddButtonClick() {
|
||||
var page = dom.parentWithClass(this, 'dlg-librarycreator');
|
||||
const page = dom.parentWithClass(this, 'dlg-librarycreator');
|
||||
|
||||
require(['directorybrowser'], function (directoryBrowser) {
|
||||
var picker = new directoryBrowser();
|
||||
import('directorybrowser').then(({default: directoryBrowser}) => {
|
||||
const picker = new directoryBrowser();
|
||||
picker.show({
|
||||
enableNetworkSharePath: true,
|
||||
callback: function (path, networkSharePath) {
|
||||
@@ -106,24 +125,24 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed
|
||||
}
|
||||
|
||||
function getFolderHtml(pathInfo, index) {
|
||||
var html = '';
|
||||
let html = '';
|
||||
html += '<div class="listItem listItem-border lnkPath" style="padding-left:.5em;">';
|
||||
html += '<div class="' + (pathInfo.NetworkPath ? 'listItemBody two-line' : 'listItemBody') + '">';
|
||||
html += '<div class="listItemBodyText">' + pathInfo.Path + '</div>';
|
||||
html += `<div class="${pathInfo.NetworkPath ? 'listItemBody two-line' : 'listItemBody'}">`;
|
||||
html += `<div class="listItemBodyText">${pathInfo.Path}</div>`;
|
||||
|
||||
if (pathInfo.NetworkPath) {
|
||||
html += '<div class="listItemBodyText secondary">' + pathInfo.NetworkPath + '</div>';
|
||||
html += `<div class="listItemBodyText secondary">${pathInfo.NetworkPath}</div>`;
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
html += '<button type="button" is="paper-icon-button-light"" class="listItemButton btnRemovePath" data-index="' + index + '"><span class="material-icons remove_circle"></span></button>';
|
||||
html += `<button type="button" is="paper-icon-button-light"" class="listItemButton btnRemovePath" data-index="${index}"><span class="material-icons remove_circle"></span></button>`;
|
||||
html += '</div>';
|
||||
return html;
|
||||
}
|
||||
|
||||
function renderPaths(page) {
|
||||
var foldersHtml = pathInfos.map(getFolderHtml).join('');
|
||||
var folderList = page.querySelector('.folderList');
|
||||
const foldersHtml = pathInfos.map(getFolderHtml).join('');
|
||||
const folderList = page.querySelector('.folderList');
|
||||
folderList.innerHTML = foldersHtml;
|
||||
|
||||
if (foldersHtml) {
|
||||
@@ -134,13 +153,13 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed
|
||||
}
|
||||
|
||||
function addMediaLocation(page, path, networkSharePath) {
|
||||
var pathLower = path.toLowerCase();
|
||||
var pathFilter = pathInfos.filter(function (p) {
|
||||
const pathLower = path.toLowerCase();
|
||||
const pathFilter = pathInfos.filter(p => {
|
||||
return p.Path.toLowerCase() == pathLower;
|
||||
});
|
||||
|
||||
if (!pathFilter.length) {
|
||||
var pathInfo = {
|
||||
const pathInfo = {
|
||||
Path: path
|
||||
};
|
||||
|
||||
@@ -154,11 +173,11 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed
|
||||
}
|
||||
|
||||
function onRemoveClick(e) {
|
||||
var button = dom.parentWithClass(e.target, 'btnRemovePath');
|
||||
var index = parseInt(button.getAttribute('data-index'));
|
||||
var location = pathInfos[index].Path;
|
||||
var locationLower = location.toLowerCase();
|
||||
pathInfos = pathInfos.filter(function (p) {
|
||||
const button = dom.parentWithClass(e.target, 'btnRemovePath');
|
||||
const index = parseInt(button.getAttribute('data-index'));
|
||||
const location = pathInfos[index].Path;
|
||||
const locationLower = location.toLowerCase();
|
||||
pathInfos = pathInfos.filter(p => {
|
||||
return p.Path.toLowerCase() != locationLower;
|
||||
});
|
||||
renderPaths(dom.parentWithClass(button, 'dlg-librarycreator'));
|
||||
@@ -169,54 +188,49 @@ define(['loading', 'dialogHelper', 'dom', 'jQuery', 'components/libraryoptionsed
|
||||
}
|
||||
|
||||
function initLibraryOptions(dlg) {
|
||||
libraryoptionseditor.embed(dlg.querySelector('.libraryOptions')).then(function () {
|
||||
libraryoptionseditor.embed(dlg.querySelector('.libraryOptions')).then(() => {
|
||||
$('#selectCollectionType', dlg).trigger('change');
|
||||
onToggleAdvancedChange.call(dlg.querySelector('.chkAdvanced'));
|
||||
});
|
||||
}
|
||||
|
||||
function editor() {
|
||||
this.show = function (options) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
currentOptions = options;
|
||||
currentResolve = resolve;
|
||||
hasChanges = false;
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', 'components/mediaLibraryCreator/mediaLibraryCreator.template.html', true);
|
||||
|
||||
xhr.onload = function (e) {
|
||||
var template = this.response;
|
||||
var dlg = dialogHelper.createDialog({
|
||||
size: 'small',
|
||||
modal: false,
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
});
|
||||
dlg.classList.add('ui-body-a');
|
||||
dlg.classList.add('background-theme-a');
|
||||
dlg.classList.add('dlg-librarycreator');
|
||||
dlg.classList.add('formDialog');
|
||||
dlg.innerHTML = globalize.translateDocument(template);
|
||||
initEditor(dlg, options.collectionTypeOptions);
|
||||
dlg.addEventListener('close', onDialogClosed);
|
||||
dialogHelper.open(dlg);
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', function () {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
pathInfos = [];
|
||||
renderPaths(dlg);
|
||||
initLibraryOptions(dlg);
|
||||
};
|
||||
|
||||
xhr.send();
|
||||
export class showEditor {
|
||||
constructor(options) {
|
||||
return new Promise((resolve) => {
|
||||
currentOptions = options;
|
||||
currentResolve = resolve;
|
||||
hasChanges = false;
|
||||
import('text!./components/mediaLibraryCreator/mediaLibraryCreator.template.html').then(({default: template}) => {
|
||||
const dlg = dialogHelper.createDialog({
|
||||
size: 'small',
|
||||
modal: false,
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
});
|
||||
dlg.classList.add('ui-body-a');
|
||||
dlg.classList.add('background-theme-a');
|
||||
dlg.classList.add('dlg-librarycreator');
|
||||
dlg.classList.add('formDialog');
|
||||
dlg.innerHTML = globalize.translateHtml(template);
|
||||
initEditor(dlg, options.collectionTypeOptions);
|
||||
dlg.addEventListener('close', onDialogClosed);
|
||||
dialogHelper.open(dlg);
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', () => {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
pathInfos = [];
|
||||
renderPaths(dlg);
|
||||
initLibraryOptions(dlg);
|
||||
});
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var pathInfos = [];
|
||||
var currentResolve;
|
||||
var currentOptions;
|
||||
var hasChanges = false;
|
||||
var isCreating = false;
|
||||
return editor;
|
||||
});
|
||||
let pathInfos = [];
|
||||
let currentResolve;
|
||||
let currentOptions;
|
||||
let hasChanges = false;
|
||||
let isCreating = false;
|
||||
|
||||
/* eslint-enable indent */
|
||||
export default showEditor;
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionseditor/libraryoptionseditor', 'globalize', 'emby-button', 'listViewStyle', 'paper-icon-button-light', 'formDialogStyle', 'emby-toggle', 'flexStyles'], function (jQuery, loading, dialogHelper, dom, libraryoptionseditor, globalize) {
|
||||
'use strict';
|
||||
/* eslint-disable indent */
|
||||
|
||||
/**
|
||||
* Module for media library editor.
|
||||
* @module components/mediaLibraryEditor/mediaLibraryEditor
|
||||
*/
|
||||
|
||||
import jQuery from 'jQuery';
|
||||
import loading from 'loading';
|
||||
import dialogHelper from 'dialogHelper';
|
||||
import dom from 'dom';
|
||||
import libraryoptionseditor from 'components/libraryoptionseditor/libraryoptionseditor';
|
||||
import globalize from 'globalize';
|
||||
import 'emby-button';
|
||||
import 'listViewStyle';
|
||||
import 'paper-icon-button-light';
|
||||
import 'formDialogStyle';
|
||||
import 'emby-toggle';
|
||||
import 'flexStyles';
|
||||
|
||||
function onEditLibrary() {
|
||||
if (isCreating) {
|
||||
@@ -8,15 +25,15 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed
|
||||
|
||||
isCreating = true;
|
||||
loading.show();
|
||||
var dlg = dom.parentWithClass(this, 'dlg-libraryeditor');
|
||||
var libraryOptions = libraryoptionseditor.getLibraryOptions(dlg.querySelector('.libraryOptions'));
|
||||
const dlg = dom.parentWithClass(this, 'dlg-libraryeditor');
|
||||
let libraryOptions = libraryoptionseditor.getLibraryOptions(dlg.querySelector('.libraryOptions'));
|
||||
libraryOptions = Object.assign(currentOptions.library.LibraryOptions || {}, libraryOptions);
|
||||
ApiClient.updateVirtualFolderOptions(currentOptions.library.ItemId, libraryOptions).then(function () {
|
||||
ApiClient.updateVirtualFolderOptions(currentOptions.library.ItemId, libraryOptions).then(() => {
|
||||
hasChanges = true;
|
||||
isCreating = false;
|
||||
loading.hide();
|
||||
dialogHelper.close(dlg);
|
||||
}, function () {
|
||||
}, () => {
|
||||
isCreating = false;
|
||||
loading.hide();
|
||||
});
|
||||
@@ -24,50 +41,50 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed
|
||||
}
|
||||
|
||||
function addMediaLocation(page, path, networkSharePath) {
|
||||
var virtualFolder = currentOptions.library;
|
||||
var refreshAfterChange = currentOptions.refresh;
|
||||
ApiClient.addMediaPath(virtualFolder.Name, path, networkSharePath, refreshAfterChange).then(function () {
|
||||
const virtualFolder = currentOptions.library;
|
||||
const refreshAfterChange = currentOptions.refresh;
|
||||
ApiClient.addMediaPath(virtualFolder.Name, path, networkSharePath, refreshAfterChange).then(() => {
|
||||
hasChanges = true;
|
||||
refreshLibraryFromServer(page);
|
||||
}, function () {
|
||||
require(['toast'], function (toast) {
|
||||
}, () => {
|
||||
import('toast').then(({default: toast}) => {
|
||||
toast(globalize.translate('ErrorAddingMediaPathToVirtualFolder'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function updateMediaLocation(page, path, networkSharePath) {
|
||||
var virtualFolder = currentOptions.library;
|
||||
const virtualFolder = currentOptions.library;
|
||||
ApiClient.updateMediaPath(virtualFolder.Name, {
|
||||
Path: path,
|
||||
NetworkPath: networkSharePath
|
||||
}).then(function () {
|
||||
}).then(() => {
|
||||
hasChanges = true;
|
||||
refreshLibraryFromServer(page);
|
||||
}, function () {
|
||||
require(['toast'], function (toast) {
|
||||
}, () => {
|
||||
import('toast').then(({default: toast}) => {
|
||||
toast(globalize.translate('ErrorAddingMediaPathToVirtualFolder'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function onRemoveClick(btnRemovePath, location) {
|
||||
var button = btnRemovePath;
|
||||
var virtualFolder = currentOptions.library;
|
||||
const button = btnRemovePath;
|
||||
const virtualFolder = currentOptions.library;
|
||||
|
||||
require(['confirm'], function (confirm) {
|
||||
import('confirm').then(({default: confirm}) => {
|
||||
confirm({
|
||||
title: globalize.translate('HeaderRemoveMediaLocation'),
|
||||
text: globalize.translate('MessageConfirmRemoveMediaLocation'),
|
||||
confirmText: globalize.translate('ButtonDelete'),
|
||||
primary: 'delete'
|
||||
}).then(function () {
|
||||
var refreshAfterChange = currentOptions.refresh;
|
||||
ApiClient.removeMediaPath(virtualFolder.Name, location, refreshAfterChange).then(function () {
|
||||
}).then(() => {
|
||||
const refreshAfterChange = currentOptions.refresh;
|
||||
ApiClient.removeMediaPath(virtualFolder.Name, location, refreshAfterChange).then(() => {
|
||||
hasChanges = true;
|
||||
refreshLibraryFromServer(dom.parentWithClass(button, 'dlg-libraryeditor'));
|
||||
}, function () {
|
||||
require(['toast'], function (toast) {
|
||||
}, () => {
|
||||
import('toast').then(({default: toast}) => {
|
||||
toast(globalize.translate('DefaultErrorMessage'));
|
||||
});
|
||||
});
|
||||
@@ -76,14 +93,14 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed
|
||||
}
|
||||
|
||||
function onListItemClick(e) {
|
||||
var listItem = dom.parentWithClass(e.target, 'listItem');
|
||||
const listItem = dom.parentWithClass(e.target, 'listItem');
|
||||
|
||||
if (listItem) {
|
||||
var index = parseInt(listItem.getAttribute('data-index'));
|
||||
var pathInfos = (currentOptions.library.LibraryOptions || {}).PathInfos || [];
|
||||
var pathInfo = null == index ? {} : pathInfos[index] || {};
|
||||
var originalPath = pathInfo.Path || (null == index ? null : currentOptions.library.Locations[index]);
|
||||
var btnRemovePath = dom.parentWithClass(e.target, 'btnRemovePath');
|
||||
const index = parseInt(listItem.getAttribute('data-index'));
|
||||
const pathInfos = (currentOptions.library.LibraryOptions || {}).PathInfos || [];
|
||||
const pathInfo = null == index ? {} : pathInfos[index] || {};
|
||||
const originalPath = pathInfo.Path || (null == index ? null : currentOptions.library.Locations[index]);
|
||||
const btnRemovePath = dom.parentWithClass(e.target, 'btnRemovePath');
|
||||
|
||||
if (btnRemovePath) {
|
||||
onRemoveClick(btnRemovePath, originalPath);
|
||||
@@ -95,26 +112,26 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed
|
||||
}
|
||||
|
||||
function getFolderHtml(pathInfo, index) {
|
||||
var html = '';
|
||||
html += '<div class="listItem listItem-border lnkPath" data-index="' + index + '" style="padding-left:.5em;">';
|
||||
html += '<div class="' + (pathInfo.NetworkPath ? 'listItemBody two-line' : 'listItemBody') + '">';
|
||||
let html = '';
|
||||
html += `<div class="listItem listItem-border lnkPath" data-index="${index}" style="padding-left:.5em;">`;
|
||||
html += `<div class="${pathInfo.NetworkPath ? 'listItemBody two-line' : 'listItemBody'}">`;
|
||||
html += '<h3 class="listItemBodyText">';
|
||||
html += pathInfo.Path;
|
||||
html += '</h3>';
|
||||
|
||||
if (pathInfo.NetworkPath) {
|
||||
html += '<div class="listItemBodyText secondary">' + pathInfo.NetworkPath + '</div>';
|
||||
html += `<div class="listItemBodyText secondary">${pathInfo.NetworkPath}</div>`;
|
||||
}
|
||||
|
||||
html += '</div>';
|
||||
html += '<button type="button" is="paper-icon-button-light" class="listItemButton btnRemovePath" data-index="' + index + '"><span class="material-icons remove_circle"></span></button>';
|
||||
html += `<button type="button" is="paper-icon-button-light" class="listItemButton btnRemovePath" data-index="${index}"><span class="material-icons remove_circle"></span></button>`;
|
||||
html += '</div>';
|
||||
return html;
|
||||
}
|
||||
|
||||
function refreshLibraryFromServer(page) {
|
||||
ApiClient.getVirtualFolders().then(function (result) {
|
||||
var library = result.filter(function (f) {
|
||||
ApiClient.getVirtualFolders().then(result => {
|
||||
const library = result.filter(f => {
|
||||
return f.Name === currentOptions.library.Name;
|
||||
})[0];
|
||||
|
||||
@@ -126,10 +143,10 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed
|
||||
}
|
||||
|
||||
function renderLibrary(page, options) {
|
||||
var pathInfos = (options.library.LibraryOptions || {}).PathInfos || [];
|
||||
let pathInfos = (options.library.LibraryOptions || {}).PathInfos || [];
|
||||
|
||||
if (!pathInfos.length) {
|
||||
pathInfos = options.library.Locations.map(function (p) {
|
||||
pathInfos = options.library.Locations.map(p => {
|
||||
return {
|
||||
Path: p
|
||||
};
|
||||
@@ -150,8 +167,8 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed
|
||||
}
|
||||
|
||||
function showDirectoryBrowser(context, originalPath, networkPath) {
|
||||
require(['directorybrowser'], function (directoryBrowser) {
|
||||
var picker = new directoryBrowser();
|
||||
import('directorybrowser').then(({default: directoryBrowser}) => {
|
||||
const picker = new directoryBrowser();
|
||||
picker.show({
|
||||
enableNetworkSharePath: true,
|
||||
pathReadOnly: null != originalPath,
|
||||
@@ -173,7 +190,7 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed
|
||||
}
|
||||
|
||||
function onToggleAdvancedChange() {
|
||||
var dlg = dom.parentWithClass(this, 'dlg-libraryeditor');
|
||||
const dlg = dom.parentWithClass(this, 'dlg-libraryeditor');
|
||||
libraryoptionseditor.setAdvancedVisible(dlg.querySelector('.libraryOptions'), this.checked);
|
||||
}
|
||||
|
||||
@@ -183,7 +200,7 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed
|
||||
dlg.querySelector('.folderList').addEventListener('click', onListItemClick);
|
||||
dlg.querySelector('.chkAdvanced').addEventListener('change', onToggleAdvancedChange);
|
||||
dlg.querySelector('.btnSubmit').addEventListener('click', onEditLibrary);
|
||||
libraryoptionseditor.embed(dlg.querySelector('.libraryOptions'), options.library.CollectionType, options.library.LibraryOptions).then(function () {
|
||||
libraryoptionseditor.embed(dlg.querySelector('.libraryOptions'), options.library.CollectionType, options.library.LibraryOptions).then(() => {
|
||||
onToggleAdvancedChange.call(dlg.querySelector('.chkAdvanced'));
|
||||
});
|
||||
}
|
||||
@@ -192,46 +209,41 @@ define(['jQuery', 'loading', 'dialogHelper', 'dom', 'components/libraryoptionsed
|
||||
currentDeferred.resolveWith(null, [hasChanges]);
|
||||
}
|
||||
|
||||
function editor() {
|
||||
this.show = function (options) {
|
||||
var deferred = jQuery.Deferred();
|
||||
currentOptions = options;
|
||||
currentDeferred = deferred;
|
||||
hasChanges = false;
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', 'components/mediaLibraryEditor/mediaLibraryEditor.template.html', true);
|
||||
|
||||
xhr.onload = function (e) {
|
||||
var template = this.response;
|
||||
var dlg = dialogHelper.createDialog({
|
||||
size: 'small',
|
||||
modal: false,
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
});
|
||||
dlg.classList.add('dlg-libraryeditor');
|
||||
dlg.classList.add('ui-body-a');
|
||||
dlg.classList.add('background-theme-a');
|
||||
dlg.classList.add('formDialog');
|
||||
dlg.innerHTML = globalize.translateDocument(template);
|
||||
dlg.querySelector('.formDialogHeaderTitle').innerHTML = options.library.Name;
|
||||
initEditor(dlg, options);
|
||||
dlg.addEventListener('close', onDialogClosed);
|
||||
dialogHelper.open(dlg);
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', function () {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
refreshLibraryFromServer(dlg);
|
||||
};
|
||||
|
||||
xhr.send();
|
||||
return deferred.promise();
|
||||
};
|
||||
export class showEditor {
|
||||
constructor(options) {
|
||||
const deferred = jQuery.Deferred();
|
||||
currentOptions = options;
|
||||
currentDeferred = deferred;
|
||||
hasChanges = false;
|
||||
import('text!./components/mediaLibraryEditor/mediaLibraryEditor.template.html').then(({default: template}) => {
|
||||
const dlg = dialogHelper.createDialog({
|
||||
size: 'small',
|
||||
modal: false,
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
});
|
||||
dlg.classList.add('dlg-libraryeditor');
|
||||
dlg.classList.add('ui-body-a');
|
||||
dlg.classList.add('background-theme-a');
|
||||
dlg.classList.add('formDialog');
|
||||
dlg.innerHTML = globalize.translateHtml(template);
|
||||
dlg.querySelector('.formDialogHeaderTitle').innerHTML = options.library.Name;
|
||||
initEditor(dlg, options);
|
||||
dlg.addEventListener('close', onDialogClosed);
|
||||
dialogHelper.open(dlg);
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', () => {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
refreshLibraryFromServer(dlg);
|
||||
});
|
||||
return deferred.promise();
|
||||
}
|
||||
}
|
||||
|
||||
var currentDeferred;
|
||||
var currentOptions;
|
||||
var hasChanges = false;
|
||||
var isCreating = false;
|
||||
return editor;
|
||||
});
|
||||
let currentDeferred;
|
||||
let currentOptions;
|
||||
let hasChanges = false;
|
||||
let isCreating = false;
|
||||
|
||||
/* eslint-enable indent */
|
||||
export default showEditor;
|
||||
|
||||
@@ -1,24 +1,29 @@
|
||||
define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'material-icons', 'css!./mediainfo.css', 'programStyles', 'emby-button'], function (datetime, globalize, appRouter, itemHelper, indicators) {
|
||||
'use strict';
|
||||
import datetime from 'datetime';
|
||||
import globalize from 'globalize';
|
||||
import appRouter from 'appRouter';
|
||||
import itemHelper from 'itemHelper';
|
||||
import indicators from 'indicators';
|
||||
import 'material-icons';
|
||||
import 'css!./mediainfo.css';
|
||||
import 'programStyles';
|
||||
import 'emby-button';
|
||||
|
||||
/* eslint-disable indent */
|
||||
|
||||
function getTimerIndicator(item) {
|
||||
|
||||
var status;
|
||||
let status;
|
||||
|
||||
if (item.Type === 'SeriesTimer') {
|
||||
return '<span class="material-icons mediaInfoItem mediaInfoIconItem mediaInfoTimerIcon fiber_smart_record"></span>';
|
||||
} else if (item.TimerId || item.SeriesTimerId) {
|
||||
|
||||
status = item.Status || 'Cancelled';
|
||||
} else if (item.Type === 'Timer') {
|
||||
|
||||
status = item.Status;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (item.SeriesTimerId) {
|
||||
|
||||
if (status !== 'Cancelled') {
|
||||
return '<span class="material-icons mediaInfoItem mediaInfoIconItem mediaInfoTimerIcon fiber_smart_record"></span>';
|
||||
}
|
||||
@@ -30,16 +35,14 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
}
|
||||
|
||||
function getProgramInfoHtml(item, options) {
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
var miscInfo = [];
|
||||
var text;
|
||||
var date;
|
||||
const miscInfo = [];
|
||||
let text;
|
||||
let date;
|
||||
|
||||
if (item.StartDate && options.programTime !== false) {
|
||||
|
||||
try {
|
||||
|
||||
text = '';
|
||||
|
||||
date = datetime.parseISO8601Date(item.StartDate);
|
||||
@@ -48,35 +51,34 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
text += datetime.toLocaleDateString(date, { weekday: 'short', month: 'short', day: 'numeric' });
|
||||
}
|
||||
|
||||
text += ' ' + datetime.getDisplayTime(date);
|
||||
text += ` ${datetime.getDisplayTime(date)}`;
|
||||
|
||||
if (item.EndDate) {
|
||||
date = datetime.parseISO8601Date(item.EndDate);
|
||||
text += ' - ' + datetime.getDisplayTime(date);
|
||||
text += ` - ${datetime.getDisplayTime(date)}`;
|
||||
}
|
||||
|
||||
miscInfo.push(text);
|
||||
} catch (e) {
|
||||
console.error('error parsing date: ' + item.StartDate);
|
||||
console.error('error parsing date:', item.StartDate);
|
||||
}
|
||||
}
|
||||
|
||||
if (item.ChannelNumber) {
|
||||
miscInfo.push('CH ' + item.ChannelNumber);
|
||||
miscInfo.push(`CH ${item.ChannelNumber}`);
|
||||
}
|
||||
|
||||
if (item.ChannelName) {
|
||||
|
||||
if (options.interactive && item.ChannelId) {
|
||||
miscInfo.push({
|
||||
html: '<a is="emby-linkbutton" class="button-flat mediaInfoItem" href="' + appRouter.getRouteUrl({
|
||||
html: `<a is="emby-linkbutton" class="button-flat mediaInfoItem" href="${appRouter.getRouteUrl({
|
||||
|
||||
ServerId: item.ServerId,
|
||||
Type: 'TvChannel',
|
||||
Name: item.ChannelName,
|
||||
Id: item.ChannelId
|
||||
|
||||
}) + '">' + item.ChannelName + '</a>'
|
||||
})}">${item.ChannelName}</a>`
|
||||
});
|
||||
} else {
|
||||
miscInfo.push(item.ChannelName);
|
||||
@@ -84,7 +86,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
}
|
||||
|
||||
if (options.timerIndicator !== false) {
|
||||
var timerHtml = getTimerIndicator(item);
|
||||
const timerHtml = getTimerIndicator(item);
|
||||
if (timerHtml) {
|
||||
miscInfo.push({
|
||||
html: timerHtml
|
||||
@@ -92,31 +94,29 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
}
|
||||
}
|
||||
|
||||
html += miscInfo.map(function (m) {
|
||||
html += miscInfo.map(m => {
|
||||
return getMediaInfoItem(m);
|
||||
}).join('');
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
function getMediaInfoHtml(item, options) {
|
||||
var html = '';
|
||||
export function getMediaInfoHtml(item, options) {
|
||||
let html = '';
|
||||
|
||||
var miscInfo = [];
|
||||
const miscInfo = [];
|
||||
options = options || {};
|
||||
var text;
|
||||
var date;
|
||||
var minutes;
|
||||
var count;
|
||||
let text;
|
||||
let date;
|
||||
let minutes;
|
||||
let count;
|
||||
|
||||
var showFolderRuntime = item.Type === 'MusicAlbum' || item.MediaType === 'MusicArtist' || item.MediaType === 'Playlist' || item.MediaType === 'MusicGenre';
|
||||
const showFolderRuntime = item.Type === 'MusicAlbum' || item.MediaType === 'MusicArtist' || item.MediaType === 'Playlist' || item.MediaType === 'MusicGenre';
|
||||
|
||||
if (showFolderRuntime) {
|
||||
|
||||
count = item.SongCount || item.ChildCount;
|
||||
|
||||
if (count) {
|
||||
|
||||
miscInfo.push(globalize.translate('TrackCount', count));
|
||||
}
|
||||
|
||||
@@ -124,33 +124,28 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
miscInfo.push(datetime.getDisplayRunningTime(item.RunTimeTicks));
|
||||
}
|
||||
} else if (item.Type === 'PhotoAlbum' || item.Type === 'BoxSet') {
|
||||
|
||||
count = item.ChildCount;
|
||||
|
||||
if (count) {
|
||||
|
||||
miscInfo.push(globalize.translate('ItemCount', count));
|
||||
}
|
||||
}
|
||||
|
||||
if ((item.Type === 'Episode' || item.MediaType === 'Photo') && options.originalAirDate !== false) {
|
||||
|
||||
if (item.PremiereDate) {
|
||||
|
||||
try {
|
||||
date = datetime.parseISO8601Date(item.PremiereDate);
|
||||
|
||||
text = datetime.toLocaleDateString(date);
|
||||
miscInfo.push(text);
|
||||
} catch (e) {
|
||||
console.error('error parsing date: ' + item.PremiereDate);
|
||||
console.error('error parsing date:', item.PremiereDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (item.Type === 'SeriesTimer') {
|
||||
if (item.RecordAnyTime) {
|
||||
|
||||
miscInfo.push(globalize.translate('Anytime'));
|
||||
} else {
|
||||
miscInfo.push(datetime.getDisplayTime(item.StartDate));
|
||||
@@ -164,7 +159,6 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
}
|
||||
|
||||
if (item.StartDate && item.Type !== 'Program' && item.Type !== 'SeriesTimer') {
|
||||
|
||||
try {
|
||||
date = datetime.parseISO8601Date(item.StartDate);
|
||||
|
||||
@@ -176,31 +170,25 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
miscInfo.push(text);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('error parsing date: ' + item.StartDate);
|
||||
console.error('error parsing date:', item.StartDate);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.year !== false && item.ProductionYear && item.Type === 'Series') {
|
||||
|
||||
if (item.Status === 'Continuing') {
|
||||
miscInfo.push(globalize.translate('SeriesYearToPresent', item.ProductionYear));
|
||||
|
||||
} else if (item.ProductionYear) {
|
||||
|
||||
text = item.ProductionYear;
|
||||
|
||||
if (item.EndDate) {
|
||||
|
||||
try {
|
||||
|
||||
var endYear = datetime.parseISO8601Date(item.EndDate).getFullYear();
|
||||
const endYear = datetime.parseISO8601Date(item.EndDate).getFullYear();
|
||||
|
||||
if (endYear !== item.ProductionYear) {
|
||||
text += '-' + datetime.parseISO8601Date(item.EndDate).getFullYear();
|
||||
text += `-${datetime.parseISO8601Date(item.EndDate).getFullYear()}`;
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.error('error parsing date: ' + item.EndDate);
|
||||
console.error('error parsing date:', item.EndDate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,29 +197,27 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
}
|
||||
|
||||
if (item.Type === 'Program') {
|
||||
|
||||
if (options.programIndicator !== false) {
|
||||
if (item.IsLive) {
|
||||
miscInfo.push({
|
||||
html: '<div class="mediaInfoProgramAttribute mediaInfoItem liveTvProgram">' + globalize.translate('Live') + '</div>'
|
||||
html: `<div class="mediaInfoProgramAttribute mediaInfoItem liveTvProgram">${globalize.translate('Live')}</div>`
|
||||
});
|
||||
} else if (item.IsPremiere) {
|
||||
miscInfo.push({
|
||||
html: '<div class="mediaInfoProgramAttribute mediaInfoItem premiereTvProgram">' + globalize.translate('Premiere') + '</div>'
|
||||
html: `<div class="mediaInfoProgramAttribute mediaInfoItem premiereTvProgram">${globalize.translate('Premiere')}</div>`
|
||||
});
|
||||
} else if (item.IsSeries && !item.IsRepeat) {
|
||||
miscInfo.push({
|
||||
html: '<div class="mediaInfoProgramAttribute mediaInfoItem newTvProgram">' + globalize.translate('AttributeNew') + '</div>'
|
||||
html: `<div class="mediaInfoProgramAttribute mediaInfoItem newTvProgram">${globalize.translate('AttributeNew')}</div>`
|
||||
});
|
||||
} else if (item.IsSeries && item.IsRepeat) {
|
||||
miscInfo.push({
|
||||
html: '<div class="mediaInfoProgramAttribute mediaInfoItem repeatTvProgram">' + globalize.translate('Repeat') + '</div>'
|
||||
html: `<div class="mediaInfoProgramAttribute mediaInfoItem repeatTvProgram">${globalize.translate('Repeat')}</div>`
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if ((item.IsSeries || item.EpisodeTitle) && options.episodeTitle !== false) {
|
||||
|
||||
text = itemHelper.getDisplayName(item, {
|
||||
includeIndexNumber: options.episodeTitleIndexNumber
|
||||
});
|
||||
@@ -242,13 +228,12 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
} else if (item.IsMovie && item.ProductionYear && options.originalAirDate !== false) {
|
||||
miscInfo.push(item.ProductionYear);
|
||||
} else if (item.PremiereDate && options.originalAirDate !== false) {
|
||||
|
||||
try {
|
||||
date = datetime.parseISO8601Date(item.PremiereDate);
|
||||
text = globalize.translate('OriginalAirDateValue', datetime.toLocaleDateString(date));
|
||||
miscInfo.push(text);
|
||||
} catch (e) {
|
||||
console.error('error parsing date: ' + item.PremiereDate);
|
||||
console.error('error parsing date:', item.PremiereDate);
|
||||
}
|
||||
} else if (item.ProductionYear) {
|
||||
miscInfo.push(item.ProductionYear);
|
||||
@@ -257,34 +242,28 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
|
||||
if (options.year !== false) {
|
||||
if (item.Type !== 'Series' && item.Type !== 'Episode' && item.Type !== 'Person' && item.MediaType !== 'Photo' && item.Type !== 'Program' && item.Type !== 'Season') {
|
||||
|
||||
if (item.ProductionYear) {
|
||||
|
||||
miscInfo.push(item.ProductionYear);
|
||||
} else if (item.PremiereDate) {
|
||||
|
||||
try {
|
||||
text = datetime.parseISO8601Date(item.PremiereDate).getFullYear();
|
||||
miscInfo.push(text);
|
||||
} catch (e) {
|
||||
console.error('error parsing date: ' + item.PremiereDate);
|
||||
console.error('error parsing date:', item.PremiereDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (item.RunTimeTicks && item.Type !== 'Series' && item.Type !== 'Program' && item.Type !== 'Book' && !showFolderRuntime && options.runtime !== false) {
|
||||
|
||||
if (item.Type === 'Audio') {
|
||||
|
||||
miscInfo.push(datetime.getDisplayRunningTime(item.RunTimeTicks));
|
||||
|
||||
} else {
|
||||
minutes = item.RunTimeTicks / 600000000;
|
||||
|
||||
minutes = minutes || 1;
|
||||
|
||||
miscInfo.push(Math.round(minutes) + ' mins');
|
||||
miscInfo.push(`${Math.round(minutes)} mins`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,14 +279,14 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
}
|
||||
|
||||
if (item.MediaType === 'Photo' && item.Width && item.Height) {
|
||||
miscInfo.push(item.Width + 'x' + item.Height);
|
||||
miscInfo.push(`${item.Width}x${item.Height}`);
|
||||
}
|
||||
|
||||
if (options.container !== false && item.Type === 'Audio' && item.Container) {
|
||||
miscInfo.push(item.Container);
|
||||
}
|
||||
|
||||
html += miscInfo.map(function (m) {
|
||||
html += miscInfo.map(m => {
|
||||
return getMediaInfoItem(m);
|
||||
}).join('');
|
||||
|
||||
@@ -318,17 +297,15 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
}
|
||||
|
||||
if (item.CriticRating && options.criticRating !== false) {
|
||||
|
||||
if (item.CriticRating >= 60) {
|
||||
html += '<div class="mediaInfoItem mediaInfoCriticRating mediaInfoCriticRatingFresh">' + item.CriticRating + '</div>';
|
||||
html += `<div class="mediaInfoItem mediaInfoCriticRating mediaInfoCriticRatingFresh">${item.CriticRating}</div>`;
|
||||
} else {
|
||||
html += '<div class="mediaInfoItem mediaInfoCriticRating mediaInfoCriticRatingRotten">' + item.CriticRating + '</div>';
|
||||
html += `<div class="mediaInfoItem mediaInfoCriticRating mediaInfoCriticRatingRotten">${item.CriticRating}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.endsAt !== false) {
|
||||
|
||||
var endsAt = getEndsAt(item);
|
||||
const endsAt = getEndsAt(item);
|
||||
if (endsAt) {
|
||||
html += getMediaInfoItem(endsAt, 'endsAt');
|
||||
}
|
||||
@@ -339,15 +316,13 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
return html;
|
||||
}
|
||||
|
||||
function getEndsAt(item) {
|
||||
|
||||
export function getEndsAt(item) {
|
||||
if (item.MediaType === 'Video' && item.RunTimeTicks) {
|
||||
|
||||
if (!item.StartDate) {
|
||||
var endDate = new Date().getTime() + (item.RunTimeTicks / 10000);
|
||||
let endDate = new Date().getTime() + (item.RunTimeTicks / 10000);
|
||||
endDate = new Date(endDate);
|
||||
|
||||
var displayTime = datetime.getDisplayTime(endDate);
|
||||
const displayTime = datetime.getDisplayTime(endDate);
|
||||
return globalize.translate('EndsAtValue', displayTime);
|
||||
}
|
||||
}
|
||||
@@ -355,12 +330,11 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
return null;
|
||||
}
|
||||
|
||||
function getEndsAtFromPosition(runtimeTicks, positionTicks, includeText) {
|
||||
|
||||
var endDate = new Date().getTime() + ((runtimeTicks - (positionTicks || 0)) / 10000);
|
||||
export function getEndsAtFromPosition(runtimeTicks, positionTicks, includeText) {
|
||||
let endDate = new Date().getTime() + ((runtimeTicks - (positionTicks || 0)) / 10000);
|
||||
endDate = new Date(endDate);
|
||||
|
||||
var displayTime = datetime.getDisplayTime(endDate);
|
||||
const displayTime = datetime.getDisplayTime(endDate);
|
||||
|
||||
if (includeText === false) {
|
||||
return displayTime;
|
||||
@@ -369,23 +343,21 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
}
|
||||
|
||||
function getMediaInfoItem(m, cssClass) {
|
||||
|
||||
cssClass = cssClass ? (cssClass + ' mediaInfoItem') : 'mediaInfoItem';
|
||||
var mediaInfoText = m;
|
||||
cssClass = cssClass ? (`${cssClass} mediaInfoItem`) : 'mediaInfoItem';
|
||||
let mediaInfoText = m;
|
||||
|
||||
if (typeof (m) !== 'string' && typeof (m) !== 'number') {
|
||||
|
||||
if (m.html) {
|
||||
return m.html;
|
||||
}
|
||||
mediaInfoText = m.text;
|
||||
cssClass += ' ' + m.cssClass;
|
||||
cssClass += ` ${m.cssClass}`;
|
||||
}
|
||||
return '<div class="' + cssClass + '">' + mediaInfoText + '</div>';
|
||||
return `<div class="${cssClass}">${mediaInfoText}</div>`;
|
||||
}
|
||||
|
||||
function getStarIconsHtml(item) {
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
if (item.CommunityRating) {
|
||||
html += '<div class="starRatingContainer mediaInfoItem">';
|
||||
@@ -399,53 +371,47 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
}
|
||||
|
||||
function dynamicEndTime(elem, item) {
|
||||
|
||||
var interval = setInterval(function () {
|
||||
|
||||
const interval = setInterval(() => {
|
||||
if (!document.body.contains(elem)) {
|
||||
|
||||
clearInterval(interval);
|
||||
return;
|
||||
}
|
||||
|
||||
elem.innerHTML = getEndsAt(item);
|
||||
|
||||
}, 60000);
|
||||
}
|
||||
|
||||
function fillPrimaryMediaInfo(elem, item, options) {
|
||||
var html = getPrimaryMediaInfoHtml(item, options);
|
||||
export function fillPrimaryMediaInfo(elem, item, options) {
|
||||
const html = getPrimaryMediaInfoHtml(item, options);
|
||||
|
||||
elem.innerHTML = html;
|
||||
afterFill(elem, item, options);
|
||||
}
|
||||
|
||||
function fillSecondaryMediaInfo(elem, item, options) {
|
||||
var html = getSecondaryMediaInfoHtml(item, options);
|
||||
export function fillSecondaryMediaInfo(elem, item, options) {
|
||||
const html = getSecondaryMediaInfoHtml(item, options);
|
||||
|
||||
elem.innerHTML = html;
|
||||
afterFill(elem, item, options);
|
||||
}
|
||||
|
||||
function afterFill(elem, item, options) {
|
||||
|
||||
if (options.endsAt !== false) {
|
||||
var endsAtElem = elem.querySelector('.endsAt');
|
||||
const endsAtElem = elem.querySelector('.endsAt');
|
||||
if (endsAtElem) {
|
||||
dynamicEndTime(endsAtElem, item);
|
||||
}
|
||||
}
|
||||
|
||||
var lnkChannel = elem.querySelector('.lnkChannel');
|
||||
const lnkChannel = elem.querySelector('.lnkChannel');
|
||||
if (lnkChannel) {
|
||||
lnkChannel.addEventListener('click', onChannelLinkClick);
|
||||
}
|
||||
}
|
||||
|
||||
function onChannelLinkClick(e) {
|
||||
|
||||
var channelId = this.getAttribute('data-id');
|
||||
var serverId = this.getAttribute('data-serverid');
|
||||
const channelId = this.getAttribute('data-id');
|
||||
const serverId = this.getAttribute('data-serverid');
|
||||
|
||||
appRouter.showItem(channelId, serverId);
|
||||
|
||||
@@ -453,8 +419,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
return false;
|
||||
}
|
||||
|
||||
function getPrimaryMediaInfoHtml(item, options) {
|
||||
|
||||
export function getPrimaryMediaInfoHtml(item, options) {
|
||||
options = options || {};
|
||||
if (options.interactive == null) {
|
||||
options.interactive = false;
|
||||
@@ -463,8 +428,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
return getMediaInfoHtml(item, options);
|
||||
}
|
||||
|
||||
function getSecondaryMediaInfoHtml(item, options) {
|
||||
|
||||
export function getSecondaryMediaInfoHtml(item, options) {
|
||||
options = options || {};
|
||||
if (options.interactive == null) {
|
||||
options.interactive = false;
|
||||
@@ -476,13 +440,11 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
return '';
|
||||
}
|
||||
|
||||
function getResolutionText(i) {
|
||||
|
||||
var width = i.Width;
|
||||
var height = i.Height;
|
||||
export function getResolutionText(i) {
|
||||
const width = i.Width;
|
||||
const height = i.Height;
|
||||
|
||||
if (width && height) {
|
||||
|
||||
if (width >= 3800 || height >= 2000) {
|
||||
return '4K';
|
||||
}
|
||||
@@ -505,45 +467,41 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
return '720p';
|
||||
}
|
||||
if (width >= 700 || height >= 400) {
|
||||
|
||||
if (i.IsInterlaced) {
|
||||
return '480i';
|
||||
}
|
||||
return '480p';
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getAudioStreamForDisplay(item) {
|
||||
|
||||
if (!item.MediaSources) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var mediaSource = item.MediaSources[0];
|
||||
const mediaSource = item.MediaSources[0];
|
||||
if (!mediaSource) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (mediaSource.MediaStreams || []).filter(function (i) {
|
||||
return (mediaSource.MediaStreams || []).filter(i => {
|
||||
return i.Type === 'Audio' && (i.Index === mediaSource.DefaultAudioStreamIndex || mediaSource.DefaultAudioStreamIndex == null);
|
||||
})[0];
|
||||
}
|
||||
|
||||
function getMediaInfoStats(item, options) {
|
||||
|
||||
export function getMediaInfoStats(item, options) {
|
||||
options = options || {};
|
||||
|
||||
var list = [];
|
||||
const list = [];
|
||||
|
||||
var mediaSource = (item.MediaSources || [])[0] || {};
|
||||
const mediaSource = (item.MediaSources || [])[0] || {};
|
||||
|
||||
var videoStream = (mediaSource.MediaStreams || []).filter(function (i) {
|
||||
const videoStream = (mediaSource.MediaStreams || []).filter(i => {
|
||||
return i.Type === 'Video';
|
||||
})[0] || {};
|
||||
var audioStream = getAudioStreamForDisplay(item) || {};
|
||||
const audioStream = getAudioStreamForDisplay(item) || {};
|
||||
|
||||
if (item.VideoType === 'Dvd') {
|
||||
list.push({
|
||||
@@ -559,11 +517,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
});
|
||||
}
|
||||
|
||||
//if (mediaSource.Container) {
|
||||
// html += '<div class="mediaInfoIcon mediaInfoText">' + mediaSource.Container + '</div>';
|
||||
//}
|
||||
|
||||
var resolutionText = getResolutionText(videoStream);
|
||||
const resolutionText = getResolutionText(videoStream);
|
||||
if (resolutionText) {
|
||||
list.push({
|
||||
type: 'mediainfo',
|
||||
@@ -578,23 +532,16 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
});
|
||||
}
|
||||
|
||||
var channels = audioStream.Channels;
|
||||
var channelText;
|
||||
const channels = audioStream.Channels;
|
||||
let channelText;
|
||||
|
||||
if (channels === 8) {
|
||||
|
||||
channelText = '7.1';
|
||||
|
||||
} else if (channels === 7) {
|
||||
|
||||
channelText = '6.1';
|
||||
|
||||
} else if (channels === 6) {
|
||||
|
||||
channelText = '5.1';
|
||||
|
||||
} else if (channels === 2) {
|
||||
|
||||
channelText = '2.0';
|
||||
}
|
||||
|
||||
@@ -605,7 +552,7 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
});
|
||||
}
|
||||
|
||||
var audioCodec = (audioStream.Codec || '').toLowerCase();
|
||||
const audioCodec = (audioStream.Codec || '').toLowerCase();
|
||||
|
||||
if ((audioCodec === 'dca' || audioCodec === 'dts') && audioStream.Profile) {
|
||||
list.push({
|
||||
@@ -620,28 +567,27 @@ define(['datetime', 'globalize', 'appRouter', 'itemHelper', 'indicators', 'mater
|
||||
}
|
||||
|
||||
if (item.DateCreated && itemHelper.enableDateAddedDisplay(item)) {
|
||||
|
||||
var dateCreated = datetime.parseISO8601Date(item.DateCreated);
|
||||
const dateCreated = datetime.parseISO8601Date(item.DateCreated);
|
||||
|
||||
list.push({
|
||||
type: 'added',
|
||||
text: globalize.translate('AddedOnValue', datetime.toLocaleDateString(dateCreated) + ' ' + datetime.getDisplayTime(dateCreated))
|
||||
text: globalize.translate('AddedOnValue', `${datetime.toLocaleDateString(dateCreated)} ${datetime.getDisplayTime(dateCreated)}`)
|
||||
});
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
return {
|
||||
getMediaInfoHtml: getPrimaryMediaInfoHtml,
|
||||
fill: fillPrimaryMediaInfo,
|
||||
getEndsAt: getEndsAt,
|
||||
getEndsAtFromPosition: getEndsAtFromPosition,
|
||||
getPrimaryMediaInfoHtml: getPrimaryMediaInfoHtml,
|
||||
getSecondaryMediaInfoHtml: getSecondaryMediaInfoHtml,
|
||||
fillPrimaryMediaInfo: fillPrimaryMediaInfo,
|
||||
fillSecondaryMediaInfo: fillSecondaryMediaInfo,
|
||||
getMediaInfoStats: getMediaInfoStats,
|
||||
getResolutionText: getResolutionText
|
||||
};
|
||||
});
|
||||
/* eslint-enable indent */
|
||||
|
||||
export default {
|
||||
getMediaInfoHtml: getPrimaryMediaInfoHtml,
|
||||
getEndsAt: getEndsAt,
|
||||
getEndsAtFromPosition: getEndsAtFromPosition,
|
||||
getPrimaryMediaInfoHtml: getPrimaryMediaInfoHtml,
|
||||
getSecondaryMediaInfoHtml: getSecondaryMediaInfoHtml,
|
||||
fillPrimaryMediaInfo: fillPrimaryMediaInfo,
|
||||
fillSecondaryMediaInfo: fillSecondaryMediaInfo,
|
||||
getMediaInfoStats: getMediaInfoStats,
|
||||
getResolutionText: getResolutionText
|
||||
};
|
||||
|
||||
@@ -1,25 +1,42 @@
|
||||
define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loading', 'focusManager', 'connectionManager', 'globalize', 'require', 'shell', 'emby-checkbox', 'emby-input', 'emby-select', 'listViewStyle', 'emby-textarea', 'emby-button', 'paper-icon-button-light', 'css!./../formdialog', 'clearButtonStyle', 'flexStyles'], function (itemHelper, dom, layoutManager, dialogHelper, datetime, loading, focusManager, connectionManager, globalize, require, shell) {
|
||||
'use strict';
|
||||
import dom from 'dom';
|
||||
import layoutManager from 'layoutManager';
|
||||
import dialogHelper from 'dialogHelper';
|
||||
import datetime from 'datetime';
|
||||
import loading from 'loading';
|
||||
import focusManager from 'focusManager';
|
||||
import connectionManager from 'connectionManager';
|
||||
import globalize from 'globalize';
|
||||
import require from 'require';
|
||||
import shell from 'shell';
|
||||
import 'emby-checkbox';
|
||||
import 'emby-input';
|
||||
import 'emby-select';
|
||||
import 'listViewStyle';
|
||||
import 'emby-textarea';
|
||||
import 'emby-button';
|
||||
import 'paper-icon-button-light';
|
||||
import 'css!./../formdialog';
|
||||
import 'clearButtonStyle';
|
||||
import 'flexStyles';
|
||||
|
||||
var currentContext;
|
||||
var metadataEditorInfo;
|
||||
var currentItem;
|
||||
/* eslint-disable indent */
|
||||
|
||||
let currentContext;
|
||||
let metadataEditorInfo;
|
||||
let currentItem;
|
||||
|
||||
function isDialog() {
|
||||
return currentContext.classList.contains('dialog');
|
||||
}
|
||||
|
||||
function closeDialog(isSubmitted) {
|
||||
|
||||
if (isDialog()) {
|
||||
dialogHelper.close(currentContext);
|
||||
}
|
||||
}
|
||||
|
||||
function submitUpdatedItem(form, item) {
|
||||
|
||||
function afterContentTypeUpdated() {
|
||||
|
||||
require(['toast'], function (toast) {
|
||||
toast(globalize.translate('MessageItemSaved'));
|
||||
});
|
||||
@@ -28,14 +45,12 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
closeDialog(true);
|
||||
}
|
||||
|
||||
var apiClient = getApiClient();
|
||||
const apiClient = getApiClient();
|
||||
|
||||
apiClient.updateItem(item).then(function () {
|
||||
|
||||
var newContentType = form.querySelector('#selectContentType').value || '';
|
||||
const newContentType = form.querySelector('#selectContentType').value || '';
|
||||
|
||||
if ((metadataEditorInfo.ContentType || '') !== newContentType) {
|
||||
|
||||
apiClient.ajax({
|
||||
|
||||
url: apiClient.getUrl('Items/' + item.Id + '/ContentType', {
|
||||
@@ -47,29 +62,23 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}).then(function () {
|
||||
afterContentTypeUpdated();
|
||||
});
|
||||
|
||||
} else {
|
||||
afterContentTypeUpdated();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function getSelectedAirDays(form) {
|
||||
var checkedItems = form.querySelectorAll('.chkAirDay:checked') || [];
|
||||
const checkedItems = form.querySelectorAll('.chkAirDay:checked') || [];
|
||||
return Array.prototype.map.call(checkedItems, function (c) {
|
||||
return c.getAttribute('data-day');
|
||||
});
|
||||
}
|
||||
|
||||
function getAlbumArtists(form) {
|
||||
|
||||
return form.querySelector('#txtAlbumArtist').value.trim().split(';').filter(function (s) {
|
||||
|
||||
return s.length > 0;
|
||||
|
||||
}).map(function (a) {
|
||||
|
||||
return {
|
||||
Name: a
|
||||
};
|
||||
@@ -77,13 +86,9 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}
|
||||
|
||||
function getArtists(form) {
|
||||
|
||||
return form.querySelector('#txtArtist').value.trim().split(';').filter(function (s) {
|
||||
|
||||
return s.length > 0;
|
||||
|
||||
}).map(function (a) {
|
||||
|
||||
return {
|
||||
Name: a
|
||||
};
|
||||
@@ -91,23 +96,20 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}
|
||||
|
||||
function getDateValue(form, element, property) {
|
||||
|
||||
var val = form.querySelector(element).value;
|
||||
let val = form.querySelector(element).value;
|
||||
|
||||
if (!val) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (currentItem[property]) {
|
||||
const date = datetime.parseISO8601Date(currentItem[property], true);
|
||||
|
||||
var date = datetime.parseISO8601Date(currentItem[property], true);
|
||||
|
||||
var parts = date.toISOString().split('T');
|
||||
const parts = date.toISOString().split('T');
|
||||
|
||||
// If the date is the same, preserve the time
|
||||
if (parts[0].indexOf(val) === 0) {
|
||||
|
||||
var iso = parts[1];
|
||||
const iso = parts[1];
|
||||
|
||||
val += 'T' + iso;
|
||||
}
|
||||
@@ -117,12 +119,11 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}
|
||||
|
||||
function onSubmit(e) {
|
||||
|
||||
loading.show();
|
||||
|
||||
var form = this;
|
||||
const form = this;
|
||||
|
||||
var item = {
|
||||
const item = {
|
||||
Id: currentItem.Id,
|
||||
Name: form.querySelector('#txtName').value,
|
||||
OriginalTitle: form.querySelector('#txtOriginalName').value,
|
||||
@@ -168,9 +169,9 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
|
||||
item.ProviderIds = Object.assign({}, currentItem.ProviderIds);
|
||||
|
||||
var idElements = form.querySelectorAll('.txtExternalId');
|
||||
const idElements = form.querySelectorAll('.txtExternalId');
|
||||
Array.prototype.map.call(idElements, function (idElem) {
|
||||
var providerKey = idElem.getAttribute('data-providerkey');
|
||||
const providerKey = idElem.getAttribute('data-providerkey');
|
||||
item.ProviderIds[providerKey] = idElem.value;
|
||||
});
|
||||
|
||||
@@ -178,20 +179,18 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
item.PreferredMetadataCountryCode = form.querySelector('#selectCountry').value;
|
||||
|
||||
if (currentItem.Type === 'Person') {
|
||||
|
||||
var placeOfBirth = form.querySelector('#txtPlaceOfBirth').value;
|
||||
const placeOfBirth = form.querySelector('#txtPlaceOfBirth').value;
|
||||
|
||||
item.ProductionLocations = placeOfBirth ? [placeOfBirth] : [];
|
||||
}
|
||||
|
||||
if (currentItem.Type === 'Series') {
|
||||
|
||||
// 600000000
|
||||
var seriesRuntime = form.querySelector('#txtSeriesRuntime').value;
|
||||
const seriesRuntime = form.querySelector('#txtSeriesRuntime').value;
|
||||
item.RunTimeTicks = seriesRuntime ? (seriesRuntime * 600000000) : null;
|
||||
}
|
||||
|
||||
var tagline = form.querySelector('#txtTagline').value;
|
||||
const tagline = form.querySelector('#txtTagline').value;
|
||||
item.Taglines = tagline ? [tagline] : [];
|
||||
|
||||
submitUpdatedItem(form, item);
|
||||
@@ -210,13 +209,12 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}
|
||||
|
||||
function addElementToList(source, sortCallback) {
|
||||
require(['prompt'], function (prompt) {
|
||||
|
||||
import('prompt').then(({default: prompt}) => {
|
||||
prompt({
|
||||
label: 'Value:'
|
||||
}).then(function (text) {
|
||||
var list = dom.parentWithClass(source, 'editableListviewContainer').querySelector('.paperList');
|
||||
var items = getListValues(list);
|
||||
const list = dom.parentWithClass(source, 'editableListviewContainer').querySelector('.paperList');
|
||||
const items = getListValues(list);
|
||||
items.push(text);
|
||||
populateListView(list, items, sortCallback);
|
||||
});
|
||||
@@ -224,17 +222,14 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}
|
||||
|
||||
function removeElementFromList(source) {
|
||||
var el = dom.parentWithClass(source, 'listItem');
|
||||
const el = dom.parentWithClass(source, 'listItem');
|
||||
el.parentNode.removeChild(el);
|
||||
}
|
||||
|
||||
function editPerson(context, person, index) {
|
||||
|
||||
require(['personEditor'], function (personEditor) {
|
||||
|
||||
personEditor.show(person).then(function (updatedPerson) {
|
||||
|
||||
var isNew = index === -1;
|
||||
const isNew = index === -1;
|
||||
|
||||
if (isNew) {
|
||||
currentItem.People.push(updatedPerson);
|
||||
@@ -245,15 +240,51 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
});
|
||||
}
|
||||
|
||||
function onEditorClick(e) {
|
||||
function afterDeleted(context, item) {
|
||||
var parentId = item.ParentId || item.SeasonId || item.SeriesId;
|
||||
|
||||
var btnRemoveFromEditorList = dom.parentWithClass(e.target, 'btnRemoveFromEditorList');
|
||||
if (parentId) {
|
||||
reload(context, parentId, item.ServerId);
|
||||
} else {
|
||||
require(['appRouter'], function (appRouter) {
|
||||
appRouter.goHome();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function showMoreMenu(context, button, user) {
|
||||
require(['itemContextMenu'], function (itemContextMenu) {
|
||||
var item = currentItem;
|
||||
|
||||
itemContextMenu.show({
|
||||
item: item,
|
||||
positionTo: button,
|
||||
edit: false,
|
||||
editImages: true,
|
||||
editSubtitles: true,
|
||||
sync: false,
|
||||
share: false,
|
||||
play: false,
|
||||
queue: false,
|
||||
user: user
|
||||
}).then(function (result) {
|
||||
if (result.deleted) {
|
||||
afterDeleted(context, item);
|
||||
} else if (result.updated) {
|
||||
reload(context, item.Id, item.ServerId);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function onEditorClick(e) {
|
||||
const btnRemoveFromEditorList = dom.parentWithClass(e.target, 'btnRemoveFromEditorList');
|
||||
if (btnRemoveFromEditorList) {
|
||||
removeElementFromList(btnRemoveFromEditorList);
|
||||
return;
|
||||
}
|
||||
|
||||
var btnAddTextItem = dom.parentWithClass(e.target, 'btnAddTextItem');
|
||||
const btnAddTextItem = dom.parentWithClass(e.target, 'btnAddTextItem');
|
||||
if (btnAddTextItem) {
|
||||
addElementToList(btnAddTextItem);
|
||||
}
|
||||
@@ -264,19 +295,18 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}
|
||||
|
||||
function bindAll(elems, eventName, fn) {
|
||||
for (var i = 0, length = elems.length; i < length; i++) {
|
||||
for (let i = 0, length = elems.length; i < length; i++) {
|
||||
elems[i].addEventListener(eventName, fn);
|
||||
}
|
||||
}
|
||||
|
||||
function init(context, apiClient) {
|
||||
|
||||
context.querySelector('.externalIds').addEventListener('click', function (e) {
|
||||
var btnOpenExternalId = dom.parentWithClass(e.target, 'btnOpenExternalId');
|
||||
const btnOpenExternalId = dom.parentWithClass(e.target, 'btnOpenExternalId');
|
||||
if (btnOpenExternalId) {
|
||||
var field = context.querySelector('#' + btnOpenExternalId.getAttribute('data-fieldid'));
|
||||
const field = context.querySelector('#' + btnOpenExternalId.getAttribute('data-fieldid'));
|
||||
|
||||
var formatString = field.getAttribute('data-formatstring');
|
||||
const formatString = field.getAttribute('data-formatstring');
|
||||
|
||||
if (field.value) {
|
||||
shell.openUrl(formatString.replace('{0}', field.value));
|
||||
@@ -294,13 +324,17 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
closeDialog(false);
|
||||
});
|
||||
|
||||
context.querySelector('.btnHeaderSave').addEventListener('click', function (e) {
|
||||
context.querySelector('.btnMore').addEventListener('click', function (e) {
|
||||
getApiClient().getCurrentUser().then(function (user) {
|
||||
showMoreMenu(context, e.target, user);
|
||||
});
|
||||
});
|
||||
|
||||
context.querySelector('.btnHeaderSave').addEventListener('click', function (e) {
|
||||
context.querySelector('.btnSave').click();
|
||||
});
|
||||
|
||||
context.querySelector('#chkLockData').addEventListener('click', function (e) {
|
||||
|
||||
if (!e.target.checked) {
|
||||
showElement('.providerSettingsContainer');
|
||||
} else {
|
||||
@@ -311,26 +345,24 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
context.removeEventListener('click', onEditorClick);
|
||||
context.addEventListener('click', onEditorClick);
|
||||
|
||||
var form = context.querySelector('form');
|
||||
const form = context.querySelector('form');
|
||||
form.removeEventListener('submit', onSubmit);
|
||||
form.addEventListener('submit', onSubmit);
|
||||
|
||||
context.querySelector('#btnAddPerson').addEventListener('click', function (event, data) {
|
||||
|
||||
editPerson(context, {}, -1);
|
||||
});
|
||||
|
||||
context.querySelector('#peopleList').addEventListener('click', function (e) {
|
||||
|
||||
var index;
|
||||
var btnDeletePerson = dom.parentWithClass(e.target, 'btnDeletePerson');
|
||||
let index;
|
||||
const btnDeletePerson = dom.parentWithClass(e.target, 'btnDeletePerson');
|
||||
if (btnDeletePerson) {
|
||||
index = parseInt(btnDeletePerson.getAttribute('data-index'));
|
||||
currentItem.People.splice(index, 1);
|
||||
populatePeople(context, currentItem.People);
|
||||
}
|
||||
|
||||
var btnEditPerson = dom.parentWithClass(e.target, 'btnEditPerson');
|
||||
const btnEditPerson = dom.parentWithClass(e.target, 'btnEditPerson');
|
||||
if (btnEditPerson) {
|
||||
index = parseInt(btnEditPerson.getAttribute('data-index'));
|
||||
editPerson(context, currentItem.People[index], index);
|
||||
@@ -339,8 +371,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}
|
||||
|
||||
function getItem(itemId, serverId) {
|
||||
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
const apiClient = connectionManager.getApiClient(serverId);
|
||||
|
||||
if (itemId) {
|
||||
return apiClient.getItem(apiClient.getCurrentUserId(), itemId);
|
||||
@@ -350,8 +381,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}
|
||||
|
||||
function getEditorConfig(itemId, serverId) {
|
||||
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
const apiClient = connectionManager.getApiClient(serverId);
|
||||
|
||||
if (itemId) {
|
||||
return apiClient.getJSON(apiClient.getUrl('Items/' + itemId + '/MetadataEditor'));
|
||||
@@ -361,14 +391,12 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}
|
||||
|
||||
function populateCountries(select, allCountries) {
|
||||
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
html += "<option value=''></option>";
|
||||
|
||||
for (var i = 0, length = allCountries.length; i < length; i++) {
|
||||
|
||||
var culture = allCountries[i];
|
||||
for (let i = 0, length = allCountries.length; i < length; i++) {
|
||||
const culture = allCountries[i];
|
||||
|
||||
html += "<option value='" + culture.TwoLetterISORegionName + "'>" + culture.DisplayName + '</option>';
|
||||
}
|
||||
@@ -377,14 +405,12 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}
|
||||
|
||||
function populateLanguages(select, languages) {
|
||||
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
html += "<option value=''></option>";
|
||||
|
||||
for (var i = 0, length = languages.length; i < length; i++) {
|
||||
|
||||
var culture = languages[i];
|
||||
for (let i = 0, length = languages.length; i < length; i++) {
|
||||
const culture = languages[i];
|
||||
|
||||
html += "<option value='" + culture.TwoLetterISOLanguageName + "'>" + culture.DisplayName + '</option>';
|
||||
}
|
||||
@@ -393,48 +419,43 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}
|
||||
|
||||
function renderContentTypeOptions(context, metadataInfo) {
|
||||
|
||||
if (!metadataInfo.ContentTypeOptions.length) {
|
||||
hideElement('#fldContentType', context);
|
||||
} else {
|
||||
showElement('#fldContentType', context);
|
||||
}
|
||||
|
||||
var html = metadataInfo.ContentTypeOptions.map(function (i) {
|
||||
|
||||
const html = metadataInfo.ContentTypeOptions.map(function (i) {
|
||||
return '<option value="' + i.Value + '">' + i.Name + '</option>';
|
||||
|
||||
}).join('');
|
||||
|
||||
var selectEl = context.querySelector('#selectContentType');
|
||||
const selectEl = context.querySelector('#selectContentType');
|
||||
selectEl.innerHTML = html;
|
||||
selectEl.value = metadataInfo.ContentType || '';
|
||||
}
|
||||
|
||||
function loadExternalIds(context, item, externalIds) {
|
||||
let html = '';
|
||||
|
||||
var html = '';
|
||||
const providerIds = item.ProviderIds || {};
|
||||
|
||||
var providerIds = item.ProviderIds || {};
|
||||
for (let i = 0, length = externalIds.length; i < length; i++) {
|
||||
const idInfo = externalIds[i];
|
||||
|
||||
for (var i = 0, length = externalIds.length; i < length; i++) {
|
||||
const id = 'txt1' + idInfo.Key;
|
||||
const formatString = idInfo.UrlFormatString || '';
|
||||
|
||||
var idInfo = externalIds[i];
|
||||
|
||||
var id = 'txt1' + idInfo.Key;
|
||||
var formatString = idInfo.UrlFormatString || '';
|
||||
|
||||
var fullName = idInfo.Name;
|
||||
let fullName = idInfo.Name;
|
||||
if (idInfo.Type) {
|
||||
fullName = idInfo.Name + ' ' + globalize.translate(idInfo.Type);
|
||||
}
|
||||
|
||||
var labelText = globalize.translate('LabelDynamicExternalId', fullName);
|
||||
const labelText = globalize.translate('LabelDynamicExternalId', fullName);
|
||||
|
||||
html += '<div class="inputContainer">';
|
||||
html += '<div class="flex align-items-center">';
|
||||
|
||||
var value = providerIds[idInfo.Key] || '';
|
||||
const value = providerIds[idInfo.Key] || '';
|
||||
|
||||
html += '<div class="flex-grow">';
|
||||
html += '<input is="emby-input" class="txtExternalId" value="' + value + '" data-providerkey="' + idInfo.Key + '" data-formatstring="' + formatString + '" id="' + id + '" label="' + labelText + '"/>';
|
||||
@@ -448,7 +469,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
var elem = context.querySelector('.externalIds', context);
|
||||
const elem = context.querySelector('.externalIds', context);
|
||||
elem.innerHTML = html;
|
||||
|
||||
if (externalIds.length) {
|
||||
@@ -464,8 +485,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
function hideElement(selector, context, multiple) {
|
||||
context = context || document;
|
||||
if (typeof selector === 'string') {
|
||||
|
||||
var elements = multiple ? context.querySelectorAll(selector) : [context.querySelector(selector)];
|
||||
const elements = multiple ? context.querySelectorAll(selector) : [context.querySelector(selector)];
|
||||
|
||||
Array.prototype.forEach.call(elements, function (el) {
|
||||
if (el) {
|
||||
@@ -483,8 +503,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
function showElement(selector, context, multiple) {
|
||||
context = context || document;
|
||||
if (typeof selector === 'string') {
|
||||
|
||||
var elements = multiple ? context.querySelectorAll(selector) : [context.querySelector(selector)];
|
||||
const elements = multiple ? context.querySelectorAll(selector) : [context.querySelector(selector)];
|
||||
|
||||
Array.prototype.forEach.call(elements, function (el) {
|
||||
if (el) {
|
||||
@@ -685,8 +704,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}
|
||||
|
||||
function fillItemInfo(context, item, parentalRatingOptions) {
|
||||
|
||||
var select = context.querySelector('#selectOfficialRating');
|
||||
let select = context.querySelector('#selectOfficialRating');
|
||||
|
||||
populateRatings(parentalRatingOptions, select, item.OfficialRating);
|
||||
|
||||
@@ -698,7 +716,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
|
||||
select.value = item.CustomRating || '';
|
||||
|
||||
var selectStatus = context.querySelector('#selectStatus');
|
||||
const selectStatus = context.querySelector('#selectStatus');
|
||||
populateStatus(selectStatus);
|
||||
selectStatus.value = item.Status || '';
|
||||
|
||||
@@ -717,8 +735,8 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
|
||||
populateListView(context.querySelector('#listTags'), item.Tags);
|
||||
|
||||
var lockData = (item.LockData || false);
|
||||
var chkLockData = context.querySelector('#chkLockData');
|
||||
const lockData = (item.LockData || false);
|
||||
const chkLockData = context.querySelector('#chkLockData');
|
||||
chkLockData.checked = lockData;
|
||||
if (chkLockData.checked) {
|
||||
hideElement('.providerSettingsContainer', context);
|
||||
@@ -756,7 +774,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
return a.Name;
|
||||
}).join(';');
|
||||
|
||||
var date;
|
||||
let date;
|
||||
|
||||
if (item.DateCreated) {
|
||||
try {
|
||||
@@ -798,7 +816,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
|
||||
context.querySelector('#txtAirTime').value = item.AirTime || '';
|
||||
|
||||
var placeofBirth = item.ProductionLocations && item.ProductionLocations.length ? item.ProductionLocations[0] : '';
|
||||
const placeofBirth = item.ProductionLocations && item.ProductionLocations.length ? item.ProductionLocations[0] : '';
|
||||
context.querySelector('#txtPlaceOfBirth').value = placeofBirth;
|
||||
|
||||
context.querySelector('#txtOriginalAspectRatio').value = item.AspectRatio || '';
|
||||
@@ -807,8 +825,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
context.querySelector('#selectCountry').value = item.PreferredMetadataCountryCode || '';
|
||||
|
||||
if (item.RunTimeTicks) {
|
||||
|
||||
var minutes = item.RunTimeTicks / 600000000;
|
||||
const minutes = item.RunTimeTicks / 600000000;
|
||||
|
||||
context.querySelector('#txtSeriesRuntime').value = Math.round(minutes);
|
||||
} else {
|
||||
@@ -817,20 +834,16 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}
|
||||
|
||||
function populateRatings(allParentalRatings, select, currentValue) {
|
||||
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
html += "<option value=''></option>";
|
||||
|
||||
var ratings = [];
|
||||
var i;
|
||||
var length;
|
||||
var rating;
|
||||
const ratings = [];
|
||||
let rating;
|
||||
|
||||
var currentValueFound = false;
|
||||
|
||||
for (i = 0, length = allParentalRatings.length; i < length; i++) {
|
||||
let currentValueFound = false;
|
||||
|
||||
for (let i = 0, length = allParentalRatings.length; i < length; i++) {
|
||||
rating = allParentalRatings[i];
|
||||
|
||||
ratings.push({ Name: rating.Name, Value: rating.Name });
|
||||
@@ -844,8 +857,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
ratings.push({ Name: currentValue, Value: currentValue });
|
||||
}
|
||||
|
||||
for (i = 0, length = ratings.length; i < length; i++) {
|
||||
|
||||
for (let i = 0, length = ratings.length; i < length; i++) {
|
||||
rating = ratings[i];
|
||||
|
||||
html += "<option value='" + rating.Value + "'>" + rating.Name + '</option>';
|
||||
@@ -855,7 +867,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}
|
||||
|
||||
function populateStatus(select) {
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
html += "<option value=''></option>";
|
||||
html += "<option value='Continuing'>" + globalize.translate('Continuing') + '</option>';
|
||||
@@ -864,7 +876,6 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}
|
||||
|
||||
function populateListView(list, items, sortCallback) {
|
||||
|
||||
items = items || [];
|
||||
if (typeof (sortCallback) === 'undefined') {
|
||||
items.sort(function (a, b) {
|
||||
@@ -873,8 +884,8 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
} else {
|
||||
items = sortCallback(items);
|
||||
}
|
||||
var html = '';
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
let html = '';
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
html += '<div class="listItem">';
|
||||
|
||||
html += '<span class="material-icons listItemIcon live_tv" style="background-color:#333;"></span>';
|
||||
@@ -896,15 +907,13 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}
|
||||
|
||||
function populatePeople(context, people) {
|
||||
let lastType = '';
|
||||
let html = '';
|
||||
|
||||
var lastType = '';
|
||||
var html = '';
|
||||
const elem = context.querySelector('#peopleList');
|
||||
|
||||
var elem = context.querySelector('#peopleList');
|
||||
|
||||
for (var i = 0, length = people.length; i < length; i++) {
|
||||
|
||||
var person = people[i];
|
||||
for (let i = 0, length = people.length; i < length; i++) {
|
||||
const person = people[i];
|
||||
|
||||
html += '<div class="listItem">';
|
||||
|
||||
@@ -933,14 +942,12 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}
|
||||
|
||||
function getLockedFieldsHtml(fields, currentFields) {
|
||||
|
||||
var html = '';
|
||||
for (var i = 0; i < fields.length; i++) {
|
||||
|
||||
var field = fields[i];
|
||||
var name = field.name;
|
||||
var value = field.value || field.name;
|
||||
var checkedHtml = currentFields.indexOf(value) === -1 ? ' checked' : '';
|
||||
let html = '';
|
||||
for (let i = 0; i < fields.length; i++) {
|
||||
const field = fields[i];
|
||||
const name = field.name;
|
||||
const value = field.value || field.name;
|
||||
const checkedHtml = currentFields.indexOf(value) === -1 ? ' checked' : '';
|
||||
html += '<label>';
|
||||
html += '<input type="checkbox" is="emby-checkbox" class="selectLockedField" data-value="' + value + '"' + checkedHtml + '/>';
|
||||
html += '<span>' + name + '</span>';
|
||||
@@ -950,10 +957,10 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}
|
||||
|
||||
function fillMetadataSettings(context, item, lockedFields) {
|
||||
var container = context.querySelector('.providerSettingsContainer');
|
||||
const container = context.querySelector('.providerSettingsContainer');
|
||||
lockedFields = lockedFields || [];
|
||||
|
||||
var lockedFieldsList = [
|
||||
const lockedFieldsList = [
|
||||
{ name: globalize.translate('Name'), value: 'Name' },
|
||||
{ name: globalize.translate('Overview'), value: 'Overview' },
|
||||
{ name: globalize.translate('Genres'), value: 'Genres' },
|
||||
@@ -974,7 +981,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
lockedFieldsList.push({ name: globalize.translate('Studios'), value: 'Studios' });
|
||||
lockedFieldsList.push({ name: globalize.translate('Tags'), value: 'Tags' });
|
||||
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
html += '<h2>' + globalize.translate('HeaderEnabledFields') + '</h2>';
|
||||
html += '<p>' + globalize.translate('HeaderEnabledFieldsHelp') + '</p>';
|
||||
@@ -983,18 +990,16 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}
|
||||
|
||||
function reload(context, itemId, serverId) {
|
||||
|
||||
loading.show();
|
||||
|
||||
Promise.all([getItem(itemId, serverId), getEditorConfig(itemId, serverId)]).then(function (responses) {
|
||||
|
||||
var item = responses[0];
|
||||
const item = responses[0];
|
||||
metadataEditorInfo = responses[1];
|
||||
|
||||
currentItem = item;
|
||||
|
||||
var languages = metadataEditorInfo.Cultures;
|
||||
var countries = metadataEditorInfo.Countries;
|
||||
const languages = metadataEditorInfo.Cultures;
|
||||
const countries = metadataEditorInfo.Countries;
|
||||
|
||||
renderContentTypeOptions(context, metadataEditorInfo);
|
||||
|
||||
@@ -1017,8 +1022,8 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
}
|
||||
|
||||
function centerFocus(elem, horiz, on) {
|
||||
require(['scrollHelper'], function (scrollHelper) {
|
||||
var fn = on ? 'on' : 'off';
|
||||
import('scrollHelper').then(({default: scrollHelper}) => {
|
||||
const fn = on ? 'on' : 'off';
|
||||
scrollHelper.centerFocus[fn](elem, horiz);
|
||||
});
|
||||
}
|
||||
@@ -1026,9 +1031,8 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
function show(itemId, serverId, resolve, reject) {
|
||||
loading.show();
|
||||
|
||||
require(['text!./metadataEditor.template.html'], function (template) {
|
||||
|
||||
var dialogOptions = {
|
||||
import('text!./metadataEditor.template.html').then(({default: template}) => {
|
||||
const dialogOptions = {
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
};
|
||||
@@ -1039,13 +1043,13 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
dialogOptions.size = 'small';
|
||||
}
|
||||
|
||||
var dlg = dialogHelper.createDialog(dialogOptions);
|
||||
const dlg = dialogHelper.createDialog(dialogOptions);
|
||||
|
||||
dlg.classList.add('formDialog');
|
||||
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
html += globalize.translateDocument(template, 'core');
|
||||
html += globalize.translateHtml(template, 'core');
|
||||
|
||||
dlg.innerHTML = html;
|
||||
|
||||
@@ -1071,7 +1075,7 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
export default {
|
||||
show: function (itemId, serverId) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
return show(itemId, serverId, resolve, reject);
|
||||
@@ -1080,14 +1084,13 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
|
||||
embed: function (elem, itemId, serverId) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
loading.show();
|
||||
|
||||
require(['text!./metadataEditor.template.html'], function (template) {
|
||||
|
||||
elem.innerHTML = globalize.translateDocument(template, 'core');
|
||||
import('text!./metadataEditor.template.html').then(({default: template}) => {
|
||||
elem.innerHTML = globalize.translateHtml(template, 'core');
|
||||
|
||||
elem.querySelector('.formDialogFooter').classList.remove('formDialogFooter');
|
||||
elem.querySelector('.btnClose').classList.add('hide');
|
||||
elem.querySelector('.btnHeaderSave').classList.remove('hide');
|
||||
elem.querySelector('.btnCancel').classList.add('hide');
|
||||
|
||||
@@ -1101,4 +1104,5 @@ define(['itemHelper', 'dom', 'layoutManager', 'dialogHelper', 'datetime', 'loadi
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
/* eslint-enable indent */
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
<span class="material-icons check"></span>
|
||||
<span>${Save}</span>
|
||||
</button>
|
||||
<button is="paper-icon-button-light" class="btnMore autoSize" tabindex="-1">
|
||||
<span class="material-icons more_vert"></span>
|
||||
</button>
|
||||
<button is="paper-icon-button-light" class="btnCancel btnClose autoSize" tabindex="-1">
|
||||
<span class="material-icons close"></span>
|
||||
</button>
|
||||
|
||||
@@ -1,19 +1,24 @@
|
||||
define(['dialogHelper', 'layoutManager', 'globalize', 'require', 'paper-icon-button-light', 'emby-input', 'emby-select', 'css!./../formdialog'], function (dialogHelper, layoutManager, globalize, require) {
|
||||
'use strict';
|
||||
import dialogHelper from 'dialogHelper';
|
||||
import layoutManager from 'layoutManager';
|
||||
import globalize from 'globalize';
|
||||
import 'paper-icon-button-light';
|
||||
import 'emby-input';
|
||||
import 'emby-select';
|
||||
import 'css!./../formdialog';
|
||||
|
||||
/* eslint-disable indent */
|
||||
|
||||
function centerFocus(elem, horiz, on) {
|
||||
require(['scrollHelper'], function (scrollHelper) {
|
||||
var fn = on ? 'on' : 'off';
|
||||
import('scrollHelper').then(({default: scrollHelper}) => {
|
||||
const fn = on ? 'on' : 'off';
|
||||
scrollHelper.centerFocus[fn](elem, horiz);
|
||||
});
|
||||
}
|
||||
|
||||
function show(person) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
require(['text!./personEditor.template.html'], function (template) {
|
||||
|
||||
var dialogOptions = {
|
||||
import('text!./personEditor.template.html').then(({default: template}) => {
|
||||
const dialogOptions = {
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
};
|
||||
@@ -24,14 +29,14 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'require', 'paper-icon-but
|
||||
dialogOptions.size = 'small';
|
||||
}
|
||||
|
||||
var dlg = dialogHelper.createDialog(dialogOptions);
|
||||
const dlg = dialogHelper.createDialog(dialogOptions);
|
||||
|
||||
dlg.classList.add('formDialog');
|
||||
|
||||
var html = '';
|
||||
var submitted = false;
|
||||
let html = '';
|
||||
let submitted = false;
|
||||
|
||||
html += globalize.translateDocument(template, 'core');
|
||||
html += globalize.translateHtml(template, 'core');
|
||||
|
||||
dlg.innerHTML = html;
|
||||
|
||||
@@ -46,7 +51,6 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'require', 'paper-icon-but
|
||||
dialogHelper.open(dlg);
|
||||
|
||||
dlg.addEventListener('close', function () {
|
||||
|
||||
if (layoutManager.tv) {
|
||||
centerFocus(dlg.querySelector('.formDialogContent'), false, false);
|
||||
}
|
||||
@@ -59,7 +63,6 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'require', 'paper-icon-but
|
||||
});
|
||||
|
||||
dlg.querySelector('.selectPersonType').addEventListener('change', function (e) {
|
||||
|
||||
if (this.value === 'Actor') {
|
||||
dlg.querySelector('.fldRole').classList.remove('hide');
|
||||
} else {
|
||||
@@ -68,12 +71,10 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'require', 'paper-icon-but
|
||||
});
|
||||
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', function (e) {
|
||||
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
|
||||
dlg.querySelector('form').addEventListener('submit', function (e) {
|
||||
|
||||
submitted = true;
|
||||
|
||||
person.Name = dlg.querySelector('.txtPersonName', dlg).value;
|
||||
@@ -93,7 +94,8 @@ define(['dialogHelper', 'layoutManager', 'globalize', 'require', 'paper-icon-but
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
show: show
|
||||
};
|
||||
});
|
||||
export default {
|
||||
show: show
|
||||
};
|
||||
|
||||
/* eslint-enable indent */
|
||||
|
||||
@@ -1,24 +1,28 @@
|
||||
define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'globalize', 'appRouter', 'dom', 'css!./multiSelect'], function (browser, appStorage, appHost, loading, connectionManager, globalize, appRouter, dom) {
|
||||
'use strict';
|
||||
import browser from 'browser';
|
||||
import appHost from 'apphost';
|
||||
import loading from 'loading';
|
||||
import connectionManager from 'connectionManager';
|
||||
import globalize from 'globalize';
|
||||
import dom from 'dom';
|
||||
import 'css!./multiSelect';
|
||||
|
||||
var selectedItems = [];
|
||||
var selectedElements = [];
|
||||
var currentSelectionCommandsPanel;
|
||||
/* eslint-disable indent */
|
||||
|
||||
let selectedItems = [];
|
||||
let selectedElements = [];
|
||||
let currentSelectionCommandsPanel;
|
||||
|
||||
function hideSelections() {
|
||||
|
||||
var selectionCommandsPanel = currentSelectionCommandsPanel;
|
||||
const selectionCommandsPanel = currentSelectionCommandsPanel;
|
||||
if (selectionCommandsPanel) {
|
||||
|
||||
selectionCommandsPanel.parentNode.removeChild(selectionCommandsPanel);
|
||||
currentSelectionCommandsPanel = null;
|
||||
|
||||
selectedItems = [];
|
||||
selectedElements = [];
|
||||
var elems = document.querySelectorAll('.itemSelectionPanel');
|
||||
for (var i = 0, length = elems.length; i < length; i++) {
|
||||
|
||||
var parent = elems[i].parentNode;
|
||||
const elems = document.querySelectorAll('.itemSelectionPanel');
|
||||
for (let i = 0, length = elems.length; i < length; i++) {
|
||||
const parent = elems[i].parentNode;
|
||||
parent.removeChild(elems[i]);
|
||||
parent.classList.remove('withMultiSelect');
|
||||
}
|
||||
@@ -26,17 +30,15 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
}
|
||||
|
||||
function onItemSelectionPanelClick(e, itemSelectionPanel) {
|
||||
|
||||
// toggle the checkbox, if it wasn't clicked on
|
||||
if (!dom.parentWithClass(e.target, 'chkItemSelect')) {
|
||||
var chkItemSelect = itemSelectionPanel.querySelector('.chkItemSelect');
|
||||
const chkItemSelect = itemSelectionPanel.querySelector('.chkItemSelect');
|
||||
|
||||
if (chkItemSelect) {
|
||||
|
||||
if (chkItemSelect.classList.contains('checkedInitial')) {
|
||||
chkItemSelect.classList.remove('checkedInitial');
|
||||
} else {
|
||||
var newValue = !chkItemSelect.checked;
|
||||
const newValue = !chkItemSelect.checked;
|
||||
chkItemSelect.checked = newValue;
|
||||
updateItemSelection(chkItemSelect, newValue);
|
||||
}
|
||||
@@ -49,12 +51,10 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
}
|
||||
|
||||
function updateItemSelection(chkItemSelect, selected) {
|
||||
|
||||
var id = dom.parentWithAttribute(chkItemSelect, 'data-id').getAttribute('data-id');
|
||||
const id = dom.parentWithAttribute(chkItemSelect, 'data-id').getAttribute('data-id');
|
||||
|
||||
if (selected) {
|
||||
|
||||
var current = selectedItems.filter(function (i) {
|
||||
const current = selectedItems.filter(i => {
|
||||
return i === id;
|
||||
});
|
||||
|
||||
@@ -62,18 +62,17 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
selectedItems.push(id);
|
||||
selectedElements.push(chkItemSelect);
|
||||
}
|
||||
|
||||
} else {
|
||||
selectedItems = selectedItems.filter(function (i) {
|
||||
selectedItems = selectedItems.filter(i => {
|
||||
return i !== id;
|
||||
});
|
||||
selectedElements = selectedElements.filter(function (i) {
|
||||
selectedElements = selectedElements.filter(i => {
|
||||
return i !== chkItemSelect;
|
||||
});
|
||||
}
|
||||
|
||||
if (selectedItems.length) {
|
||||
var itemSelectionCount = document.querySelector('.itemSelectionCount');
|
||||
const itemSelectionCount = document.querySelector('.itemSelectionCount');
|
||||
if (itemSelectionCount) {
|
||||
itemSelectionCount.innerHTML = selectedItems.length;
|
||||
}
|
||||
@@ -87,107 +86,94 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
}
|
||||
|
||||
function showSelection(item, isChecked) {
|
||||
|
||||
var itemSelectionPanel = item.querySelector('.itemSelectionPanel');
|
||||
let itemSelectionPanel = item.querySelector('.itemSelectionPanel');
|
||||
|
||||
if (!itemSelectionPanel) {
|
||||
|
||||
itemSelectionPanel = document.createElement('div');
|
||||
itemSelectionPanel.classList.add('itemSelectionPanel');
|
||||
|
||||
var parent = item.querySelector('.cardBox') || item.querySelector('.cardContent');
|
||||
const parent = item.querySelector('.cardBox') || item.querySelector('.cardContent');
|
||||
parent.classList.add('withMultiSelect');
|
||||
parent.appendChild(itemSelectionPanel);
|
||||
|
||||
var cssClass = 'chkItemSelect';
|
||||
let cssClass = 'chkItemSelect';
|
||||
if (isChecked && !browser.firefox) {
|
||||
// In firefox, the initial tap hold doesnt' get treated as a click
|
||||
// In other browsers it does, so we need to make sure that initial click is ignored
|
||||
cssClass += ' checkedInitial';
|
||||
}
|
||||
var checkedAttribute = isChecked ? ' checked' : '';
|
||||
itemSelectionPanel.innerHTML = '<label class="checkboxContainer"><input type="checkbox" is="emby-checkbox" data-outlineclass="multiSelectCheckboxOutline" class="' + cssClass + '"' + checkedAttribute + '/><span></span></label>';
|
||||
var chkItemSelect = itemSelectionPanel.querySelector('.chkItemSelect');
|
||||
const checkedAttribute = isChecked ? ' checked' : '';
|
||||
itemSelectionPanel.innerHTML = `<label class="checkboxContainer"><input type="checkbox" is="emby-checkbox" data-outlineclass="multiSelectCheckboxOutline" class="${cssClass}"${checkedAttribute}/><span></span></label>`;
|
||||
const chkItemSelect = itemSelectionPanel.querySelector('.chkItemSelect');
|
||||
chkItemSelect.addEventListener('change', onSelectionChange);
|
||||
}
|
||||
}
|
||||
|
||||
function showSelectionCommands() {
|
||||
|
||||
var selectionCommandsPanel = currentSelectionCommandsPanel;
|
||||
let selectionCommandsPanel = currentSelectionCommandsPanel;
|
||||
|
||||
if (!selectionCommandsPanel) {
|
||||
|
||||
selectionCommandsPanel = document.createElement('div');
|
||||
selectionCommandsPanel.classList.add('selectionCommandsPanel');
|
||||
|
||||
document.body.appendChild(selectionCommandsPanel);
|
||||
currentSelectionCommandsPanel = selectionCommandsPanel;
|
||||
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
html += '<button is="paper-icon-button-light" class="btnCloseSelectionPanel autoSize"><span class="material-icons close"></span></button>';
|
||||
html += '<h1 class="itemSelectionCount"></h1>';
|
||||
|
||||
const moreIcon = 'more_vert';
|
||||
html += '<button is="paper-icon-button-light" class="btnSelectionPanelOptions autoSize" style="margin-left:auto;"><span class="material-icons ' + moreIcon + '"></span></button>';
|
||||
html += `<button is="paper-icon-button-light" class="btnSelectionPanelOptions autoSize" style="margin-left:auto;"><span class="material-icons ${moreIcon}"></span></button>`;
|
||||
|
||||
selectionCommandsPanel.innerHTML = html;
|
||||
|
||||
selectionCommandsPanel.querySelector('.btnCloseSelectionPanel').addEventListener('click', hideSelections);
|
||||
|
||||
var btnSelectionPanelOptions = selectionCommandsPanel.querySelector('.btnSelectionPanelOptions');
|
||||
const btnSelectionPanelOptions = selectionCommandsPanel.querySelector('.btnSelectionPanelOptions');
|
||||
|
||||
dom.addEventListener(btnSelectionPanelOptions, 'click', showMenuForSelectedItems, { passive: true });
|
||||
}
|
||||
}
|
||||
|
||||
function alertText(options) {
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
require(['alert'], function (alert) {
|
||||
return new Promise((resolve, reject) => {
|
||||
import('alert').then(({default: alert}) => {
|
||||
alert(options).then(resolve, resolve);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function deleteItems(apiClient, itemIds) {
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
var msg = globalize.translate('ConfirmDeleteItem');
|
||||
var title = globalize.translate('HeaderDeleteItem');
|
||||
return new Promise((resolve, reject) => {
|
||||
let msg = globalize.translate('ConfirmDeleteItem');
|
||||
let title = globalize.translate('HeaderDeleteItem');
|
||||
|
||||
if (itemIds.length > 1) {
|
||||
msg = globalize.translate('ConfirmDeleteItems');
|
||||
title = globalize.translate('HeaderDeleteItems');
|
||||
}
|
||||
|
||||
require(['confirm'], function (confirm) {
|
||||
|
||||
confirm(msg, title).then(function () {
|
||||
var promises = itemIds.map(function (itemId) {
|
||||
import('confirm').then(({default: confirm}) => {
|
||||
confirm(msg, title).then(() => {
|
||||
const promises = itemIds.map(itemId => {
|
||||
apiClient.deleteItem(itemId);
|
||||
});
|
||||
|
||||
Promise.all(promises).then(resolve, function () {
|
||||
|
||||
Promise.all(promises).then(resolve, () => {
|
||||
alertText(globalize.translate('ErrorDeletingItem')).then(reject, reject);
|
||||
});
|
||||
}, reject);
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function showMenuForSelectedItems(e) {
|
||||
const apiClient = connectionManager.currentApiClient();
|
||||
|
||||
var apiClient = connectionManager.currentApiClient();
|
||||
|
||||
apiClient.getCurrentUser().then(function (user) {
|
||||
|
||||
var menuItems = [];
|
||||
apiClient.getCurrentUser().then(user => {
|
||||
const menuItems = [];
|
||||
|
||||
menuItems.push({
|
||||
name: globalize.translate('AddToCollection'),
|
||||
@@ -244,18 +230,18 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
icon: 'refresh'
|
||||
});
|
||||
|
||||
require(['actionsheet'], function (actionsheet) {
|
||||
import('actionsheet').then(({default: actionsheet}) => {
|
||||
actionsheet.show({
|
||||
items: menuItems,
|
||||
positionTo: e.target,
|
||||
callback: function (id) {
|
||||
var items = selectedItems.slice(0);
|
||||
var serverId = apiClient.serverInfo().Id;
|
||||
const items = selectedItems.slice(0);
|
||||
const serverId = apiClient.serverInfo().Id;
|
||||
|
||||
switch (id) {
|
||||
case 'addtocollection':
|
||||
require(['collectionEditor'], function (collectionEditor) {
|
||||
new collectionEditor().show({
|
||||
import('collectionEditor').then(({default: collectionEditor}) => {
|
||||
new collectionEditor({
|
||||
items: items,
|
||||
serverId: serverId
|
||||
});
|
||||
@@ -264,8 +250,8 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
dispatchNeedsRefresh();
|
||||
break;
|
||||
case 'playlist':
|
||||
require(['playlistEditor'], function (playlistEditor) {
|
||||
new playlistEditor().show({
|
||||
import('playlistEditor').then(({default: playlistEditor}) => {
|
||||
new playlistEditor({
|
||||
items: items,
|
||||
serverId: serverId
|
||||
});
|
||||
@@ -282,21 +268,21 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
combineVersions(apiClient, items);
|
||||
break;
|
||||
case 'markplayed':
|
||||
items.forEach(function (itemId) {
|
||||
items.forEach(itemId => {
|
||||
apiClient.markPlayed(apiClient.getCurrentUserId(), itemId);
|
||||
});
|
||||
hideSelections();
|
||||
dispatchNeedsRefresh();
|
||||
break;
|
||||
case 'markunplayed':
|
||||
items.forEach(function (itemId) {
|
||||
items.forEach(itemId => {
|
||||
apiClient.markUnplayed(apiClient.getCurrentUserId(), itemId);
|
||||
});
|
||||
hideSelections();
|
||||
dispatchNeedsRefresh();
|
||||
break;
|
||||
case 'refresh':
|
||||
require(['refreshDialog'], function (refreshDialog) {
|
||||
import('refreshDialog').then(({default: refreshDialog}) => {
|
||||
new refreshDialog({
|
||||
itemIds: items,
|
||||
serverId: serverId
|
||||
@@ -310,35 +296,31 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function dispatchNeedsRefresh() {
|
||||
const elems = [];
|
||||
|
||||
var elems = [];
|
||||
[].forEach.call(selectedElements, i => {
|
||||
const container = dom.parentWithAttribute(i, 'is', 'emby-itemscontainer');
|
||||
|
||||
[].forEach.call(selectedElements, function (i) {
|
||||
|
||||
var container = dom.parentWithAttribute(i, 'is', 'emby-itemscontainer');
|
||||
|
||||
if (container && elems.indexOf(container) === -1) {
|
||||
if (container && !elems.includes(container)) {
|
||||
elems.push(container);
|
||||
}
|
||||
});
|
||||
|
||||
for (var i = 0, length = elems.length; i < length; i++) {
|
||||
for (let i = 0, length = elems.length; i < length; i++) {
|
||||
elems[i].notifyRefreshNeeded(true);
|
||||
}
|
||||
}
|
||||
|
||||
function combineVersions(apiClient, selection) {
|
||||
|
||||
if (selection.length < 2) {
|
||||
|
||||
require(['alert'], function (alert) {
|
||||
import('alert').then(({default: alert}) => {
|
||||
alert({
|
||||
|
||||
text: globalize.translate('PleaseSelectTwoItems')
|
||||
});
|
||||
});
|
||||
@@ -352,8 +334,7 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
type: 'POST',
|
||||
url: apiClient.getUrl('Videos/MergeVersions', { Ids: selection.join(',') })
|
||||
|
||||
}).then(function () {
|
||||
|
||||
}).then(() => {
|
||||
loading.hide();
|
||||
hideSelections();
|
||||
dispatchNeedsRefresh();
|
||||
@@ -361,10 +342,9 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
}
|
||||
|
||||
function showSelections(initialCard) {
|
||||
|
||||
require(['emby-checkbox'], function () {
|
||||
var cards = document.querySelectorAll('.card');
|
||||
for (var i = 0, length = cards.length; i < length; i++) {
|
||||
import('emby-checkbox').then(() => {
|
||||
const cards = document.querySelectorAll('.card');
|
||||
for (let i = 0, length = cards.length; i < length; i++) {
|
||||
showSelection(cards[i], initialCard === cards[i]);
|
||||
}
|
||||
|
||||
@@ -374,14 +354,12 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
}
|
||||
|
||||
function onContainerClick(e) {
|
||||
|
||||
var target = e.target;
|
||||
const target = e.target;
|
||||
|
||||
if (selectedItems.length) {
|
||||
|
||||
var card = dom.parentWithClass(target, 'card');
|
||||
const card = dom.parentWithClass(target, 'card');
|
||||
if (card) {
|
||||
var itemSelectionPanel = card.querySelector('.itemSelectionPanel');
|
||||
const itemSelectionPanel = card.querySelector('.itemSelectionPanel');
|
||||
if (itemSelectionPanel) {
|
||||
return onItemSelectionPanelClick(e, itemSelectionPanel);
|
||||
}
|
||||
@@ -395,18 +373,15 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
|
||||
document.addEventListener('viewbeforehide', hideSelections);
|
||||
|
||||
return function (options) {
|
||||
export default function (options) {
|
||||
const self = this;
|
||||
|
||||
var self = this;
|
||||
|
||||
var container = options.container;
|
||||
const container = options.container;
|
||||
|
||||
function onTapHold(e) {
|
||||
|
||||
var card = dom.parentWithClass(e.target, 'card');
|
||||
const card = dom.parentWithClass(e.target, 'card');
|
||||
|
||||
if (card) {
|
||||
|
||||
showSelections(card);
|
||||
}
|
||||
|
||||
@@ -419,17 +394,15 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
}
|
||||
|
||||
function getTouches(e) {
|
||||
|
||||
return e.changedTouches || e.targetTouches || e.touches;
|
||||
}
|
||||
|
||||
var touchTarget;
|
||||
var touchStartTimeout;
|
||||
var touchStartX;
|
||||
var touchStartY;
|
||||
let touchTarget;
|
||||
let touchStartTimeout;
|
||||
let touchStartX;
|
||||
let touchStartY;
|
||||
function onTouchStart(e) {
|
||||
|
||||
var touch = getTouches(e)[0];
|
||||
const touch = getTouches(e)[0];
|
||||
touchTarget = null;
|
||||
touchStartX = 0;
|
||||
touchStartY = 0;
|
||||
@@ -437,13 +410,12 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
if (touch) {
|
||||
touchStartX = touch.clientX;
|
||||
touchStartY = touch.clientY;
|
||||
var element = touch.target;
|
||||
const element = touch.target;
|
||||
|
||||
if (element) {
|
||||
var card = dom.parentWithClass(element, 'card');
|
||||
const card = dom.parentWithClass(element, 'card');
|
||||
|
||||
if (card) {
|
||||
|
||||
if (touchStartTimeout) {
|
||||
clearTimeout(touchStartTimeout);
|
||||
touchStartTimeout = null;
|
||||
@@ -457,15 +429,14 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
}
|
||||
|
||||
function onTouchMove(e) {
|
||||
|
||||
if (touchTarget) {
|
||||
var touch = getTouches(e)[0];
|
||||
var deltaX;
|
||||
var deltaY;
|
||||
const touch = getTouches(e)[0];
|
||||
let deltaX;
|
||||
let deltaY;
|
||||
|
||||
if (touch) {
|
||||
var touchEndX = touch.clientX || 0;
|
||||
var touchEndY = touch.clientY || 0;
|
||||
const touchEndX = touch.clientX || 0;
|
||||
const touchEndY = touch.clientY || 0;
|
||||
deltaX = Math.abs(touchEndX - (touchStartX || 0));
|
||||
deltaY = Math.abs(touchEndY - (touchStartY || 0));
|
||||
} else {
|
||||
@@ -479,12 +450,10 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
}
|
||||
|
||||
function onTouchEnd(e) {
|
||||
|
||||
onMouseOut(e);
|
||||
}
|
||||
|
||||
function onMouseDown(e) {
|
||||
|
||||
if (touchStartTimeout) {
|
||||
clearTimeout(touchStartTimeout);
|
||||
touchStartTimeout = null;
|
||||
@@ -495,7 +464,6 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
}
|
||||
|
||||
function onMouseOut(e) {
|
||||
|
||||
if (touchStartTimeout) {
|
||||
clearTimeout(touchStartTimeout);
|
||||
touchStartTimeout = null;
|
||||
@@ -504,22 +472,19 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
}
|
||||
|
||||
function onTouchStartTimerFired() {
|
||||
|
||||
if (!touchTarget) {
|
||||
return;
|
||||
}
|
||||
|
||||
var card = dom.parentWithClass(touchTarget, 'card');
|
||||
const card = dom.parentWithClass(touchTarget, 'card');
|
||||
touchTarget = null;
|
||||
|
||||
if (card) {
|
||||
|
||||
showSelections(card);
|
||||
}
|
||||
}
|
||||
|
||||
function initTapHold(element) {
|
||||
|
||||
// mobile safari doesn't allow contextmenu override
|
||||
if (browser.touch && !browser.safari) {
|
||||
element.addEventListener('contextmenu', onTapHold);
|
||||
@@ -556,12 +521,11 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
|
||||
self.onContainerClick = onContainerClick;
|
||||
|
||||
self.destroy = function () {
|
||||
|
||||
self.destroy = () => {
|
||||
container.removeEventListener('click', onContainerClick);
|
||||
container.removeEventListener('contextmenu', onTapHold);
|
||||
|
||||
var element = container;
|
||||
const element = container;
|
||||
|
||||
dom.removeEventListener(element, 'touchstart', onTouchStart, {
|
||||
passive: true
|
||||
@@ -572,10 +536,6 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
dom.removeEventListener(element, 'touchend', onTouchEnd, {
|
||||
passive: true
|
||||
});
|
||||
// this fires in safari due to magnifying class
|
||||
//dom.removeEventListener(element, "touchcancel", onTouchEnd, {
|
||||
// passive: true
|
||||
//});
|
||||
dom.removeEventListener(element, 'mousedown', onMouseDown, {
|
||||
passive: true
|
||||
});
|
||||
@@ -586,5 +546,6 @@ define(['browser', 'appStorage', 'apphost', 'loading', 'connectionManager', 'glo
|
||||
passive: true
|
||||
});
|
||||
};
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/* eslint-enable indent */
|
||||
|
||||
@@ -44,7 +44,6 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir
|
||||
}
|
||||
|
||||
function showNonPersistentNotification(title, options, timeoutMs) {
|
||||
|
||||
try {
|
||||
var notif = new Notification(title, options); /* eslint-disable-line compat/compat */
|
||||
|
||||
@@ -66,7 +65,6 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir
|
||||
}
|
||||
|
||||
function showNotification(options, timeoutMs, apiClient) {
|
||||
|
||||
var title = options.title;
|
||||
|
||||
options.data = options.data || {};
|
||||
@@ -85,7 +83,6 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir
|
||||
}
|
||||
|
||||
function showNewItemNotification(item, apiClient) {
|
||||
|
||||
if (playbackManager.isPlayingLocally(['Video'])) {
|
||||
return;
|
||||
}
|
||||
@@ -101,17 +98,12 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir
|
||||
body: body,
|
||||
vibrate: true,
|
||||
tag: 'newItem' + item.Id,
|
||||
data: {
|
||||
//options: {
|
||||
// url: LibraryBrowser.getHref(item)
|
||||
//}
|
||||
}
|
||||
data: {}
|
||||
};
|
||||
|
||||
var imageTags = item.ImageTags || {};
|
||||
|
||||
if (imageTags.Primary) {
|
||||
|
||||
notification.icon = apiClient.getScaledImageUrl(item.Id, {
|
||||
width: 80,
|
||||
tag: imageTags.Primary,
|
||||
@@ -123,7 +115,6 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir
|
||||
}
|
||||
|
||||
function onLibraryChanged(data, apiClient) {
|
||||
|
||||
var newItems = data.ItemsAdded;
|
||||
|
||||
if (!newItems.length) {
|
||||
@@ -147,11 +138,9 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir
|
||||
EnableTotalRecordCount: false
|
||||
|
||||
}).then(function (result) {
|
||||
|
||||
var items = result.Items;
|
||||
|
||||
for (var i = 0, length = items.length ; i < length; i++) {
|
||||
|
||||
showNewItemNotification(items[i], apiClient);
|
||||
}
|
||||
});
|
||||
@@ -163,9 +152,7 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir
|
||||
}
|
||||
|
||||
function showPackageInstallNotification(apiClient, installation, status) {
|
||||
|
||||
apiClient.getCurrentUser().then(function (user) {
|
||||
|
||||
if (!user.Policy.IsAdministrator) {
|
||||
return;
|
||||
}
|
||||
@@ -199,7 +186,6 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir
|
||||
}
|
||||
|
||||
if (status === 'progress') {
|
||||
|
||||
var percentComplete = Math.round(installation.PercentComplete || 0);
|
||||
|
||||
notification.body = percentComplete + '% complete.';
|
||||
@@ -250,7 +236,6 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir
|
||||
});
|
||||
|
||||
events.on(serverNotifications, 'RestartRequired', function (e, apiClient) {
|
||||
|
||||
var serverId = apiClient.serverInfo().Id;
|
||||
var notification = {
|
||||
tag: 'restart' + serverId,
|
||||
|
||||
@@ -1,31 +1,43 @@
|
||||
define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader', 'layoutManager', 'playbackManager', 'nowPlayingHelper', 'apphost', 'dom', 'connectionManager', 'itemContextMenu', 'paper-icon-button-light', 'emby-ratingbutton'], function (require, datetime, itemHelper, events, browser, imageLoader, layoutManager, playbackManager, nowPlayingHelper, appHost, dom, connectionManager, itemContextMenu) {
|
||||
'use strict';
|
||||
import datetime from 'datetime';
|
||||
import events from 'events';
|
||||
import browser from 'browser';
|
||||
import imageLoader from 'imageLoader';
|
||||
import layoutManager from 'layoutManager';
|
||||
import playbackManager from 'playbackManager';
|
||||
import nowPlayingHelper from 'nowPlayingHelper';
|
||||
import appHost from 'apphost';
|
||||
import dom from 'dom';
|
||||
import connectionManager from 'connectionManager';
|
||||
import itemContextMenu from 'itemContextMenu';
|
||||
import 'paper-icon-button-light';
|
||||
import 'emby-ratingbutton';
|
||||
|
||||
var currentPlayer;
|
||||
var currentPlayerSupportedCommands = [];
|
||||
/* eslint-disable indent */
|
||||
|
||||
var currentTimeElement;
|
||||
var nowPlayingImageElement;
|
||||
var nowPlayingTextElement;
|
||||
var nowPlayingUserData;
|
||||
var muteButton;
|
||||
var volumeSlider;
|
||||
var volumeSliderContainer;
|
||||
var playPauseButtons;
|
||||
var positionSlider;
|
||||
var toggleRepeatButton;
|
||||
var toggleRepeatButtonIcon;
|
||||
let currentPlayer;
|
||||
let currentPlayerSupportedCommands = [];
|
||||
|
||||
var lastUpdateTime = 0;
|
||||
var lastPlayerState = {};
|
||||
var isEnabled;
|
||||
var currentRuntimeTicks = 0;
|
||||
let currentTimeElement;
|
||||
let nowPlayingImageElement;
|
||||
let nowPlayingTextElement;
|
||||
let nowPlayingUserData;
|
||||
let muteButton;
|
||||
let volumeSlider;
|
||||
let volumeSliderContainer;
|
||||
let playPauseButtons;
|
||||
let positionSlider;
|
||||
let toggleRepeatButton;
|
||||
let toggleRepeatButtonIcon;
|
||||
|
||||
var isVisibilityAllowed = true;
|
||||
let lastUpdateTime = 0;
|
||||
let lastPlayerState = {};
|
||||
let isEnabled;
|
||||
let currentRuntimeTicks = 0;
|
||||
|
||||
let isVisibilityAllowed = true;
|
||||
|
||||
function getNowPlayingBarHtml() {
|
||||
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
html += '<div class="nowPlayingBar hide nowPlayingBar-hidden">';
|
||||
|
||||
@@ -84,12 +96,10 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
}
|
||||
|
||||
function onSlideDownComplete() {
|
||||
|
||||
this.classList.add('hide');
|
||||
}
|
||||
|
||||
function slideDown(elem) {
|
||||
|
||||
// trigger reflow
|
||||
void elem.offsetWidth;
|
||||
|
||||
@@ -101,7 +111,6 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
}
|
||||
|
||||
function slideUp(elem) {
|
||||
|
||||
dom.removeEventListener(elem, dom.whichTransitionEvent(), onSlideDownComplete, {
|
||||
once: true
|
||||
});
|
||||
@@ -119,7 +128,6 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
}
|
||||
|
||||
function bindEvents(elem) {
|
||||
|
||||
currentTimeElement = elem.querySelector('.nowPlayingBarCurrentTime');
|
||||
nowPlayingImageElement = elem.querySelector('.nowPlayingImage');
|
||||
nowPlayingTextElement = elem.querySelector('.nowPlayingBarText');
|
||||
@@ -132,15 +140,12 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
volumeSliderContainer = elem.querySelector('.nowPlayingBarVolumeSliderContainer');
|
||||
|
||||
muteButton.addEventListener('click', function () {
|
||||
|
||||
if (currentPlayer) {
|
||||
playbackManager.toggleMute(currentPlayer);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
elem.querySelector('.stopButton').addEventListener('click', function () {
|
||||
|
||||
if (currentPlayer) {
|
||||
playbackManager.stop(currentPlayer);
|
||||
}
|
||||
@@ -151,7 +156,6 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
});
|
||||
|
||||
elem.querySelector('.nextTrackButton').addEventListener('click', function () {
|
||||
|
||||
if (currentPlayer) {
|
||||
playbackManager.nextTrack(currentPlayer);
|
||||
}
|
||||
@@ -211,25 +215,21 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
});
|
||||
|
||||
positionSlider.addEventListener('change', function () {
|
||||
|
||||
if (currentPlayer) {
|
||||
|
||||
var newPercent = parseFloat(this.value);
|
||||
const newPercent = parseFloat(this.value);
|
||||
|
||||
playbackManager.seekPercent(newPercent, currentPlayer);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
positionSlider.getBubbleText = function (value) {
|
||||
|
||||
var state = lastPlayerState;
|
||||
const state = lastPlayerState;
|
||||
|
||||
if (!state || !state.NowPlayingItem || !currentRuntimeTicks) {
|
||||
return '--:--';
|
||||
}
|
||||
|
||||
var ticks = currentRuntimeTicks;
|
||||
let ticks = currentRuntimeTicks;
|
||||
ticks /= 100;
|
||||
ticks *= value;
|
||||
|
||||
@@ -237,7 +237,6 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
};
|
||||
|
||||
elem.addEventListener('click', function (e) {
|
||||
|
||||
if (!dom.parentWithTag(e.target, ['BUTTON', 'INPUT'])) {
|
||||
showRemoteControl();
|
||||
}
|
||||
@@ -245,24 +244,26 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
}
|
||||
|
||||
function showRemoteControl() {
|
||||
|
||||
require(['appRouter'], function (appRouter) {
|
||||
import('appRouter').then(({default: appRouter}) => {
|
||||
appRouter.showNowPlaying();
|
||||
});
|
||||
}
|
||||
|
||||
var nowPlayingBarElement;
|
||||
let nowPlayingBarElement;
|
||||
function getNowPlayingBar() {
|
||||
|
||||
if (nowPlayingBarElement) {
|
||||
return Promise.resolve(nowPlayingBarElement);
|
||||
}
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
require(['appFooter-shared', 'itemShortcuts', 'css!./nowPlayingBar.css', 'emby-slider'], function (appfooter, itemShortcuts) {
|
||||
|
||||
var parentContainer = appfooter.element;
|
||||
Promise.all([
|
||||
import('appFooter-shared'),
|
||||
import('itemShortcuts'),
|
||||
import('css!./nowPlayingBar.css'),
|
||||
import('emby-slider')
|
||||
])
|
||||
.then(([appfooter, itemShortcuts]) => {
|
||||
const parentContainer = appfooter.element;
|
||||
nowPlayingBarElement = parentContainer.querySelector('.nowPlayingBar');
|
||||
|
||||
if (nowPlayingBarElement) {
|
||||
@@ -310,18 +311,17 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
}
|
||||
|
||||
function updatePlayerStateInternal(event, state, player) {
|
||||
|
||||
showNowPlayingBar();
|
||||
|
||||
lastPlayerState = state;
|
||||
|
||||
var playerInfo = playbackManager.getPlayerInfo();
|
||||
const playerInfo = playbackManager.getPlayerInfo();
|
||||
|
||||
var playState = state.PlayState || {};
|
||||
const playState = state.PlayState || {};
|
||||
|
||||
updatePlayPauseState(playState.IsPaused);
|
||||
|
||||
var supportedCommands = playerInfo.supportedCommands;
|
||||
const supportedCommands = playerInfo.supportedCommands;
|
||||
currentPlayerSupportedCommands = supportedCommands;
|
||||
|
||||
if (supportedCommands.indexOf('SetRepeatMode') === -1) {
|
||||
@@ -339,11 +339,11 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
positionSlider.disabled = !playState.CanSeek;
|
||||
|
||||
// determines if both forward and backward buffer progress will be visible
|
||||
var isProgressClear = state.MediaSource && state.MediaSource.RunTimeTicks == null;
|
||||
const isProgressClear = state.MediaSource && state.MediaSource.RunTimeTicks == null;
|
||||
positionSlider.setIsClear(isProgressClear);
|
||||
}
|
||||
|
||||
var nowPlayingItem = state.NowPlayingItem || {};
|
||||
const nowPlayingItem = state.NowPlayingItem || {};
|
||||
updateTimeDisplay(playState.PositionTicks, nowPlayingItem.RunTimeTicks, playbackManager.getBufferedRanges(player));
|
||||
|
||||
updateNowPlayingInfo(state);
|
||||
@@ -374,7 +374,7 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
// See bindEvents for why this is necessary
|
||||
if (positionSlider && !positionSlider.dragging) {
|
||||
if (runtimeTicks) {
|
||||
var pct = positionTicks / runtimeTicks;
|
||||
let pct = positionTicks / runtimeTicks;
|
||||
pct *= 100;
|
||||
|
||||
positionSlider.value = pct;
|
||||
@@ -388,7 +388,7 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
}
|
||||
|
||||
if (currentTimeElement) {
|
||||
var timeText = positionTicks == null ? '--:--' : datetime.getDisplayRunningTime(positionTicks);
|
||||
let timeText = positionTicks == null ? '--:--' : datetime.getDisplayRunningTime(positionTicks);
|
||||
if (runtimeTicks) {
|
||||
timeText += ' / ' + datetime.getDisplayRunningTime(runtimeTicks);
|
||||
}
|
||||
@@ -398,11 +398,10 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
}
|
||||
|
||||
function updatePlayerVolumeState(isMuted, volumeLevel) {
|
||||
const supportedCommands = currentPlayerSupportedCommands;
|
||||
|
||||
var supportedCommands = currentPlayerSupportedCommands;
|
||||
|
||||
var showMuteButton = true;
|
||||
var showVolumeSlider = true;
|
||||
let showMuteButton = true;
|
||||
let showVolumeSlider = true;
|
||||
|
||||
if (supportedCommands.indexOf('ToggleMute') === -1) {
|
||||
showMuteButton = false;
|
||||
@@ -429,7 +428,6 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
|
||||
// See bindEvents for why this is necessary
|
||||
if (volumeSlider) {
|
||||
|
||||
volumeSliderContainer.classList.toggle('hide', !showVolumeSlider);
|
||||
|
||||
if (!volumeSlider.dragging) {
|
||||
@@ -439,7 +437,6 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
}
|
||||
|
||||
function seriesImageUrl(item, options) {
|
||||
|
||||
if (!item) {
|
||||
throw new Error('item cannot be null!');
|
||||
}
|
||||
@@ -452,9 +449,7 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
options.type = options.type || 'Primary';
|
||||
|
||||
if (options.type === 'Primary') {
|
||||
|
||||
if (item.SeriesPrimaryImageTag) {
|
||||
|
||||
options.tag = item.SeriesPrimaryImageTag;
|
||||
|
||||
return connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options);
|
||||
@@ -462,15 +457,12 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
}
|
||||
|
||||
if (options.type === 'Thumb') {
|
||||
|
||||
if (item.SeriesThumbImageTag) {
|
||||
|
||||
options.tag = item.SeriesThumbImageTag;
|
||||
|
||||
return connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options);
|
||||
}
|
||||
if (item.ParentThumbImageTag) {
|
||||
|
||||
options.tag = item.ParentThumbImageTag;
|
||||
|
||||
return connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.ParentThumbItemId, options);
|
||||
@@ -481,7 +473,6 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
}
|
||||
|
||||
function imageUrl(item, options) {
|
||||
|
||||
if (!item) {
|
||||
throw new Error('item cannot be null!');
|
||||
}
|
||||
@@ -490,13 +481,11 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
options.type = options.type || 'Primary';
|
||||
|
||||
if (item.ImageTags && item.ImageTags[options.type]) {
|
||||
|
||||
options.tag = item.ImageTags[options.type];
|
||||
return connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.PrimaryImageItemId || item.Id, options);
|
||||
}
|
||||
|
||||
if (item.AlbumId && item.AlbumPrimaryImageTag) {
|
||||
|
||||
options.tag = item.AlbumPrimaryImageTag;
|
||||
return connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.AlbumId, options);
|
||||
}
|
||||
@@ -504,12 +493,11 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
return null;
|
||||
}
|
||||
|
||||
var currentImgUrl;
|
||||
let currentImgUrl;
|
||||
function updateNowPlayingInfo(state) {
|
||||
const nowPlayingItem = state.NowPlayingItem;
|
||||
|
||||
var nowPlayingItem = state.NowPlayingItem;
|
||||
|
||||
var textLines = nowPlayingItem ? nowPlayingHelper.getNowPlayingNames(nowPlayingItem) : [];
|
||||
const textLines = nowPlayingItem ? nowPlayingHelper.getNowPlayingNames(nowPlayingItem) : [];
|
||||
nowPlayingTextElement.innerHTML = '';
|
||||
if (textLines) {
|
||||
let itemText = document.createElement('div');
|
||||
@@ -533,15 +521,15 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
nowPlayingTextElement.appendChild(secondaryText);
|
||||
}
|
||||
|
||||
var imgHeight = 70;
|
||||
const imgHeight = 70;
|
||||
|
||||
var url = nowPlayingItem ? (seriesImageUrl(nowPlayingItem, {
|
||||
const url = nowPlayingItem ? (seriesImageUrl(nowPlayingItem, {
|
||||
height: imgHeight
|
||||
}) || imageUrl(nowPlayingItem, {
|
||||
height: imgHeight
|
||||
})) : null;
|
||||
|
||||
var isRefreshing = false;
|
||||
let isRefreshing = false;
|
||||
|
||||
if (url !== currentImgUrl) {
|
||||
currentImgUrl = url;
|
||||
@@ -560,11 +548,10 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
|
||||
if (nowPlayingItem.Id) {
|
||||
if (isRefreshing) {
|
||||
|
||||
var apiClient = connectionManager.getApiClient(nowPlayingItem.ServerId);
|
||||
const apiClient = connectionManager.getApiClient(nowPlayingItem.ServerId);
|
||||
apiClient.getItem(apiClient.getCurrentUserId(), nowPlayingItem.Id).then(function (item) {
|
||||
var userData = item.UserData || {};
|
||||
var likes = userData.Likes == null ? '' : userData.Likes;
|
||||
const userData = item.UserData || {};
|
||||
const likes = userData.Likes == null ? '' : userData.Likes;
|
||||
if (!layoutManager.mobile) {
|
||||
let contextButton = nowPlayingBarElement.querySelector('.btnToggleContextMenu');
|
||||
// We remove the previous event listener by replacing the item in each update event
|
||||
@@ -638,24 +625,21 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
}
|
||||
|
||||
function hideNowPlayingBar() {
|
||||
|
||||
isEnabled = false;
|
||||
|
||||
// Use a timeout to prevent the bar from hiding and showing quickly
|
||||
// in the event of a stop->play command
|
||||
|
||||
// Don't call getNowPlayingBar here because we don't want to end up creating it just to hide it
|
||||
var elem = document.getElementsByClassName('nowPlayingBar')[0];
|
||||
const elem = document.getElementsByClassName('nowPlayingBar')[0];
|
||||
if (elem) {
|
||||
|
||||
slideDown(elem);
|
||||
}
|
||||
}
|
||||
|
||||
function onPlaybackStopped(e, state) {
|
||||
|
||||
console.debug('nowplaying event: ' + e.type);
|
||||
var player = this;
|
||||
const player = this;
|
||||
|
||||
if (player.isLocalPlayer) {
|
||||
if (state.NextMediaType !== 'Audio') {
|
||||
@@ -669,19 +653,17 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
}
|
||||
|
||||
function onPlayPauseStateChanged(e) {
|
||||
|
||||
if (!isEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
var player = this;
|
||||
const player = this;
|
||||
updatePlayPauseState(player.paused());
|
||||
}
|
||||
|
||||
function onStateChanged(event, state) {
|
||||
|
||||
console.debug('nowplaying event: ' + event.type);
|
||||
var player = this;
|
||||
const player = this;
|
||||
|
||||
if (!state.NowPlayingItem || layoutManager.tv) {
|
||||
hideNowPlayingBar();
|
||||
@@ -706,27 +688,24 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
}
|
||||
|
||||
function onTimeUpdate(e) {
|
||||
|
||||
if (!isEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to avoid hammering the document with changes
|
||||
var now = new Date().getTime();
|
||||
const now = new Date().getTime();
|
||||
if ((now - lastUpdateTime) < 700) {
|
||||
|
||||
return;
|
||||
}
|
||||
lastUpdateTime = now;
|
||||
|
||||
var player = this;
|
||||
const player = this;
|
||||
currentRuntimeTicks = playbackManager.duration(player);
|
||||
updateTimeDisplay(playbackManager.currentTime(player), currentRuntimeTicks, playbackManager.getBufferedRanges(player));
|
||||
}
|
||||
|
||||
function releaseCurrentPlayer() {
|
||||
|
||||
var player = currentPlayer;
|
||||
const player = currentPlayer;
|
||||
|
||||
if (player) {
|
||||
events.off(player, 'playbackstart', onPlaybackStart);
|
||||
@@ -745,25 +724,22 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
}
|
||||
|
||||
function onVolumeChanged(e) {
|
||||
|
||||
if (!isEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
var player = this;
|
||||
const player = this;
|
||||
|
||||
updatePlayerVolumeState(player.isMuted(), player.getVolume());
|
||||
}
|
||||
|
||||
function refreshFromPlayer(player) {
|
||||
|
||||
var state = playbackManager.getPlayerState(player);
|
||||
const state = playbackManager.getPlayerState(player);
|
||||
|
||||
onStateChanged.call(player, { type: 'init' }, state);
|
||||
}
|
||||
|
||||
function bindToPlayer(player) {
|
||||
|
||||
if (player === currentPlayer) {
|
||||
return;
|
||||
}
|
||||
@@ -796,16 +772,12 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
bindToPlayer(playbackManager.getCurrentPlayer());
|
||||
|
||||
document.addEventListener('viewbeforeshow', function (e) {
|
||||
|
||||
if (!e.detail.options.enableMediaControl) {
|
||||
|
||||
if (isVisibilityAllowed) {
|
||||
isVisibilityAllowed = false;
|
||||
hideNowPlayingBar();
|
||||
}
|
||||
|
||||
} else if (!isVisibilityAllowed) {
|
||||
|
||||
isVisibilityAllowed = true;
|
||||
if (currentPlayer) {
|
||||
refreshFromPlayer(currentPlayer);
|
||||
@@ -814,4 +786,5 @@ define(['require', 'datetime', 'itemHelper', 'events', 'browser', 'imageLoader',
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/* eslint-enable indent */
|
||||
|
||||
@@ -4,9 +4,7 @@ define(['appSettings', 'pluginManager'], function (appSettings, pluginManager) {
|
||||
var settingsKey = 'installedpackages1';
|
||||
|
||||
function addPackage(packageManager, pkg) {
|
||||
|
||||
packageManager.packagesList = packageManager.packagesList.filter(function (p) {
|
||||
|
||||
return p.name !== pkg.name;
|
||||
});
|
||||
|
||||
@@ -14,7 +12,6 @@ define(['appSettings', 'pluginManager'], function (appSettings, pluginManager) {
|
||||
}
|
||||
|
||||
function removeUrl(url) {
|
||||
|
||||
var manifestUrls = JSON.parse(appSettings.get(settingsKey) || '[]');
|
||||
|
||||
manifestUrls = manifestUrls.filter(function (i) {
|
||||
@@ -25,9 +22,7 @@ define(['appSettings', 'pluginManager'], function (appSettings, pluginManager) {
|
||||
}
|
||||
|
||||
function loadPackage(packageManager, url, throwError) {
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
var originalUrl = url;
|
||||
url += url.indexOf('?') === -1 ? '?' : '&';
|
||||
@@ -36,7 +31,6 @@ define(['appSettings', 'pluginManager'], function (appSettings, pluginManager) {
|
||||
xhr.open('GET', url, true);
|
||||
|
||||
var onError = function () {
|
||||
|
||||
if (throwError === true) {
|
||||
reject();
|
||||
} else {
|
||||
@@ -47,7 +41,6 @@ define(['appSettings', 'pluginManager'], function (appSettings, pluginManager) {
|
||||
|
||||
xhr.onload = function (e) {
|
||||
if (this.status < 400) {
|
||||
|
||||
var pkg = JSON.parse(this.response);
|
||||
pkg.url = originalUrl;
|
||||
|
||||
@@ -61,7 +54,6 @@ define(['appSettings', 'pluginManager'], function (appSettings, pluginManager) {
|
||||
return pluginManager.loadPlugin(packageManager.mapPath(pkg, pluginUrl));
|
||||
});
|
||||
Promise.all(promises).then(resolve, resolve);
|
||||
|
||||
} else {
|
||||
onError();
|
||||
}
|
||||
@@ -74,7 +66,6 @@ define(['appSettings', 'pluginManager'], function (appSettings, pluginManager) {
|
||||
}
|
||||
|
||||
function PackageManager() {
|
||||
|
||||
this.packagesList = [];
|
||||
}
|
||||
|
||||
@@ -83,9 +74,7 @@ define(['appSettings', 'pluginManager'], function (appSettings, pluginManager) {
|
||||
|
||||
var instance = this;
|
||||
return Promise.all(manifestUrls.map(function (u) {
|
||||
|
||||
return loadPackage(instance, u);
|
||||
|
||||
})).then(function () {
|
||||
return Promise.resolve();
|
||||
}, function () {
|
||||
@@ -98,9 +87,7 @@ define(['appSettings', 'pluginManager'], function (appSettings, pluginManager) {
|
||||
};
|
||||
|
||||
PackageManager.prototype.install = function (url) {
|
||||
|
||||
return loadPackage(this, url, true).then(function (pkg) {
|
||||
|
||||
var manifestUrls = JSON.parse(appSettings.get(settingsKey) || '[]');
|
||||
|
||||
if (manifestUrls.indexOf(url) === -1) {
|
||||
@@ -113,16 +100,12 @@ define(['appSettings', 'pluginManager'], function (appSettings, pluginManager) {
|
||||
};
|
||||
|
||||
PackageManager.prototype.uninstall = function (name) {
|
||||
|
||||
var pkg = this.packagesList.filter(function (p) {
|
||||
|
||||
return p.name === name;
|
||||
})[0];
|
||||
|
||||
if (pkg) {
|
||||
|
||||
this.packagesList = this.packagesList.filter(function (p) {
|
||||
|
||||
return p.name !== name;
|
||||
});
|
||||
|
||||
@@ -133,7 +116,6 @@ define(['appSettings', 'pluginManager'], function (appSettings, pluginManager) {
|
||||
};
|
||||
|
||||
PackageManager.prototype.mapPath = function (pkg, pluginUrl) {
|
||||
|
||||
var urlLower = pluginUrl.toLowerCase();
|
||||
if (urlLower.indexOf('http:') === 0 || urlLower.indexOf('https:') === 0 || urlLower.indexOf('file:') === 0) {
|
||||
return pluginUrl;
|
||||
|
||||
@@ -23,10 +23,8 @@ function getOsdElementHtml() {
|
||||
}
|
||||
|
||||
function ensureOsdElement() {
|
||||
|
||||
var elem = osdElement;
|
||||
if (!elem) {
|
||||
|
||||
enableAnimation = browser.supportsCssAnimation();
|
||||
|
||||
elem = document.createElement('div');
|
||||
@@ -50,7 +48,6 @@ function onHideComplete() {
|
||||
|
||||
var hideTimeout;
|
||||
function showOsd() {
|
||||
|
||||
clearHideTimeout();
|
||||
|
||||
var elem = osdElement;
|
||||
@@ -79,12 +76,10 @@ function clearHideTimeout() {
|
||||
}
|
||||
|
||||
function hideOsd() {
|
||||
|
||||
clearHideTimeout();
|
||||
|
||||
var elem = osdElement;
|
||||
if (elem) {
|
||||
|
||||
if (enableAnimation) {
|
||||
// trigger reflow
|
||||
void elem.offsetWidth;
|
||||
@@ -108,7 +103,6 @@ function setIcon(iconElement, icon) {
|
||||
}
|
||||
|
||||
function updateElementsFromPlayer(brightness) {
|
||||
|
||||
if (iconElement) {
|
||||
if (brightness >= 80) {
|
||||
setIcon(iconElement, 'brightness_high');
|
||||
@@ -124,7 +118,6 @@ function updateElementsFromPlayer(brightness) {
|
||||
}
|
||||
|
||||
function releaseCurrentPlayer() {
|
||||
|
||||
var player = currentPlayer;
|
||||
|
||||
if (player) {
|
||||
@@ -135,7 +128,6 @@ function releaseCurrentPlayer() {
|
||||
}
|
||||
|
||||
function onBrightnessChanged(e) {
|
||||
|
||||
var player = this;
|
||||
|
||||
ensureOsdElement();
|
||||
@@ -146,7 +138,6 @@ function onBrightnessChanged(e) {
|
||||
}
|
||||
|
||||
function bindToPlayer(player) {
|
||||
|
||||
if (player === currentPlayer) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
export function getNowPlayingNames(nowPlayingItem, includeNonNameInfo) {
|
||||
|
||||
var topItem = nowPlayingItem;
|
||||
var bottomItem = null;
|
||||
var topText = nowPlayingItem.Name;
|
||||
@@ -25,7 +24,6 @@ export function getNowPlayingNames(nowPlayingItem, includeNonNameInfo) {
|
||||
var bottomText = '';
|
||||
|
||||
if (nowPlayingItem.ArtistItems && nowPlayingItem.ArtistItems.length) {
|
||||
|
||||
bottomItem = {
|
||||
Id: nowPlayingItem.ArtistItems[0].Id,
|
||||
Name: nowPlayingItem.ArtistItems[0].Name,
|
||||
@@ -36,9 +34,7 @@ export function getNowPlayingNames(nowPlayingItem, includeNonNameInfo) {
|
||||
bottomText = nowPlayingItem.ArtistItems.map(function (a) {
|
||||
return a.Name;
|
||||
}).join(', ');
|
||||
|
||||
} else if (nowPlayingItem.Artists && nowPlayingItem.Artists.length) {
|
||||
|
||||
bottomText = nowPlayingItem.Artists.join(', ');
|
||||
} else if (nowPlayingItem.SeriesName || nowPlayingItem.Album) {
|
||||
bottomText = topText;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,6 @@ function onOrientationChangeError(err) {
|
||||
}
|
||||
|
||||
events.on(playbackManager, 'playbackstart', function (e, player, state) {
|
||||
|
||||
var isLocalVideo = player.isLocalPlayer && !player.isExternalPlayer && playbackManager.isPlayingVideo(player);
|
||||
|
||||
if (isLocalVideo && layoutManager.mobile) {
|
||||
@@ -22,7 +21,6 @@ events.on(playbackManager, 'playbackstart', function (e, player, state) {
|
||||
var lockOrientation = screen.lockOrientation || screen.mozLockOrientation || screen.msLockOrientation || (screen.orientation && screen.orientation.lock);
|
||||
|
||||
if (lockOrientation) {
|
||||
|
||||
try {
|
||||
var promise = lockOrientation('landscape');
|
||||
if (promise.then) {
|
||||
@@ -39,9 +37,7 @@ events.on(playbackManager, 'playbackstart', function (e, player, state) {
|
||||
});
|
||||
|
||||
events.on(playbackManager, 'playbackstop', function (e, playbackStopInfo) {
|
||||
|
||||
if (orientationLocked && !playbackStopInfo.nextMediaType) {
|
||||
|
||||
/* eslint-disable-next-line compat/compat */
|
||||
var unlockOrientation = screen.unlockOrientation || screen.mozUnlockOrientation || screen.msUnlockOrientation || (screen.orientation && screen.orientation.unlock);
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import globalize from 'globalize';
|
||||
import appHost from 'apphost';
|
||||
|
||||
function mirrorItem(info, player) {
|
||||
|
||||
var item = info.item;
|
||||
|
||||
playbackManager.displayContent({
|
||||
@@ -21,9 +20,7 @@ function mirrorItem(info, player) {
|
||||
}
|
||||
|
||||
function mirrorIfEnabled(info) {
|
||||
|
||||
if (info && playbackManager.enableDisplayMirroring()) {
|
||||
|
||||
var getPlayerInfo = playbackManager.getPlayerInfo();
|
||||
|
||||
if (getPlayerInfo) {
|
||||
@@ -39,9 +36,7 @@ function emptyCallback() {
|
||||
}
|
||||
|
||||
function getTargetSecondaryText(target) {
|
||||
|
||||
if (target.user) {
|
||||
|
||||
return target.user.Name;
|
||||
}
|
||||
|
||||
@@ -49,7 +44,6 @@ function getTargetSecondaryText(target) {
|
||||
}
|
||||
|
||||
function getIcon(target) {
|
||||
|
||||
var deviceType = target.deviceType;
|
||||
|
||||
if (!deviceType && target.isLocalPlayer) {
|
||||
@@ -67,7 +61,6 @@ function getIcon(target) {
|
||||
}
|
||||
|
||||
switch (deviceType) {
|
||||
|
||||
case 'smartphone':
|
||||
return 'smartphone';
|
||||
case 'tablet':
|
||||
@@ -84,7 +77,6 @@ function getIcon(target) {
|
||||
}
|
||||
|
||||
export function show(button) {
|
||||
|
||||
var currentPlayerInfo = playbackManager.getPlayerInfo();
|
||||
|
||||
if (currentPlayerInfo) {
|
||||
@@ -99,9 +91,7 @@ export function show(button) {
|
||||
loading.show();
|
||||
|
||||
playbackManager.getTargets().then(function (targets) {
|
||||
|
||||
var menuItems = targets.map(function (t) {
|
||||
|
||||
var name = t.name;
|
||||
|
||||
if (t.appName && t.appName !== t.name) {
|
||||
@@ -115,11 +105,9 @@ export function show(button) {
|
||||
secondaryText: getTargetSecondaryText(t),
|
||||
icon: getIcon(t)
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
require(['actionsheet'], function (actionsheet) {
|
||||
|
||||
import('actionsheet').then(({default: actionsheet}) => {
|
||||
loading.hide();
|
||||
|
||||
var menuOptions = {
|
||||
@@ -133,12 +121,11 @@ export function show(button) {
|
||||
|
||||
// Unfortunately we can't allow the url to change or chromecast will throw a security error
|
||||
// Might be able to solve this in the future by moving the dialogs to hashbangs
|
||||
if (!(!browser.chrome || appHost.supports('castmenuhashchange'))) {
|
||||
if (!(!browser.chrome && !browser.edgeChromium || appHost.supports('castmenuhashchange'))) {
|
||||
menuOptions.enableHistory = false;
|
||||
}
|
||||
|
||||
actionsheet.show(menuOptions).then(function (id) {
|
||||
|
||||
var target = targets.filter(function (t) {
|
||||
return t.id === id;
|
||||
})[0];
|
||||
@@ -146,25 +133,25 @@ export function show(button) {
|
||||
playbackManager.trySetActivePlayer(target.playerName, target);
|
||||
|
||||
mirrorIfEnabled();
|
||||
|
||||
}, emptyCallback);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function showActivePlayerMenu(playerInfo) {
|
||||
|
||||
require(['dialogHelper', 'dialog', 'emby-checkbox', 'emby-button'], function (dialogHelper) {
|
||||
Promise.all([
|
||||
import('dialogHelper'),
|
||||
import('dialog'),
|
||||
import('emby-checkbox'),
|
||||
import('emby-button')
|
||||
]).then(([dialogHelper]) => {
|
||||
showActivePlayerMenuInternal(dialogHelper, playerInfo);
|
||||
});
|
||||
}
|
||||
|
||||
function disconnectFromPlayer(currentDeviceName) {
|
||||
|
||||
if (playbackManager.getSupportedCommands().indexOf('EndSession') !== -1) {
|
||||
|
||||
require(['dialog'], function (dialog) {
|
||||
|
||||
import('dialog').then(({default: dialog}) => {
|
||||
var menuItems = [];
|
||||
|
||||
menuItems.push({
|
||||
@@ -178,12 +165,10 @@ function disconnectFromPlayer(currentDeviceName) {
|
||||
|
||||
dialog({
|
||||
buttons: menuItems,
|
||||
//positionTo: positionTo,
|
||||
text: globalize.translate('ConfirmEndPlayerSession', currentDeviceName)
|
||||
|
||||
}).then(function (id) {
|
||||
switch (id) {
|
||||
|
||||
case 'yes':
|
||||
playbackManager.getCurrentPlayer().endSession();
|
||||
playbackManager.setDefaultPlayerActive();
|
||||
@@ -195,17 +180,13 @@ function disconnectFromPlayer(currentDeviceName) {
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
playbackManager.setDefaultPlayerActive();
|
||||
}
|
||||
}
|
||||
|
||||
function showActivePlayerMenuInternal(dialogHelper, playerInfo) {
|
||||
|
||||
var html = '';
|
||||
|
||||
var dialogOptions = {
|
||||
@@ -231,7 +212,6 @@ function showActivePlayerMenuInternal(dialogHelper, playerInfo) {
|
||||
html += '<div>';
|
||||
|
||||
if (playerInfo.supportedCommands.indexOf('DisplayContent') !== -1) {
|
||||
|
||||
html += '<label class="checkboxContainer">';
|
||||
var checkedHtml = playbackManager.enableDisplayMirroring() ? ' checked' : '';
|
||||
html += '<input type="checkbox" is="emby-checkbox" class="chkMirror"' + checkedHtml + '/>';
|
||||
@@ -290,7 +270,6 @@ function onMirrorChange() {
|
||||
}
|
||||
|
||||
document.addEventListener('viewshow', function (e) {
|
||||
|
||||
var state = e.detail.state || {};
|
||||
var item = state.item;
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import globalize from 'globalize';
|
||||
import qualityoptions from 'qualityoptions';
|
||||
|
||||
function showQualityMenu(player, btn) {
|
||||
|
||||
var videoStream = playbackManager.currentMediaSource(player).MediaStreams.filter(function (stream) {
|
||||
return stream.Type === 'Video';
|
||||
})[0];
|
||||
@@ -88,8 +87,6 @@ function showRepeatModeMenu(player, btn) {
|
||||
|
||||
function getQualitySecondaryText(player) {
|
||||
var state = playbackManager.getPlayerState(player);
|
||||
var isAutoEnabled = playbackManager.enableAutomaticBitrateDetection(player);
|
||||
var currentMaxBitrate = playbackManager.getMaxStreamingBitrate(player);
|
||||
|
||||
var videoStream = playbackManager.currentMediaSource(player).MediaStreams.filter(function (stream) {
|
||||
return stream.Type === 'Video';
|
||||
@@ -106,20 +103,6 @@ function getQualitySecondaryText(player) {
|
||||
enableAuto: true
|
||||
});
|
||||
|
||||
var menuItems = options.map(function (o) {
|
||||
var opt = {
|
||||
name: o.name,
|
||||
id: o.bitrate,
|
||||
asideText: o.secondaryText
|
||||
};
|
||||
|
||||
if (o.selected) {
|
||||
opt.selected = true;
|
||||
}
|
||||
|
||||
return opt;
|
||||
});
|
||||
|
||||
var selectedOption = options.filter(function (o) {
|
||||
return o.selected;
|
||||
});
|
||||
@@ -168,7 +151,6 @@ function showAspectRatioMenu(player, btn) {
|
||||
|
||||
function showWithUser(options, player, user) {
|
||||
var supportedCommands = playbackManager.getSupportedCommands(player);
|
||||
var mediaType = options.mediaType;
|
||||
|
||||
var menuItems = [];
|
||||
if (supportedCommands.indexOf('SetAspectRatio') !== -1) {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
export function getDisplayPlayMethod(session) {
|
||||
|
||||
if (!session.NowPlayingItem) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -3,16 +3,13 @@ define([], function () {
|
||||
|
||||
var currentId = 0;
|
||||
function addUniquePlaylistItemId(item) {
|
||||
|
||||
if (!item.PlaylistItemId) {
|
||||
|
||||
item.PlaylistItemId = 'playlistItem' + currentId;
|
||||
currentId++;
|
||||
}
|
||||
}
|
||||
|
||||
function findPlaylistIndex(playlistItemId, list) {
|
||||
|
||||
for (var i = 0, length = list.length; i < length; i++) {
|
||||
if (list[i].PlaylistItemId === playlistItemId) {
|
||||
return i;
|
||||
@@ -23,7 +20,6 @@ define([], function () {
|
||||
}
|
||||
|
||||
function PlayQueueManager() {
|
||||
|
||||
this._sortedPlaylist = [];
|
||||
this._playlist = [];
|
||||
this._repeatMode = 'RepeatNone';
|
||||
@@ -35,11 +31,9 @@ define([], function () {
|
||||
};
|
||||
|
||||
PlayQueueManager.prototype.setPlaylist = function (items) {
|
||||
|
||||
items = items.slice(0);
|
||||
|
||||
for (var i = 0, length = items.length; i < length; i++) {
|
||||
|
||||
addUniquePlaylistItemId(items[i]);
|
||||
}
|
||||
|
||||
@@ -49,9 +43,7 @@ define([], function () {
|
||||
};
|
||||
|
||||
PlayQueueManager.prototype.queue = function (items) {
|
||||
|
||||
for (var i = 0, length = items.length; i < length; i++) {
|
||||
|
||||
addUniquePlaylistItemId(items[i]);
|
||||
|
||||
this._playlist.push(items[i]);
|
||||
@@ -105,7 +97,6 @@ define([], function () {
|
||||
var length;
|
||||
|
||||
for (i = 0, length = items.length; i < length; i++) {
|
||||
|
||||
addUniquePlaylistItemId(items[i]);
|
||||
}
|
||||
|
||||
@@ -121,12 +112,10 @@ define([], function () {
|
||||
};
|
||||
|
||||
PlayQueueManager.prototype.getCurrentPlaylistIndex = function () {
|
||||
|
||||
return findPlaylistIndex(this.getCurrentPlaylistItemId(), this._playlist);
|
||||
};
|
||||
|
||||
PlayQueueManager.prototype.getCurrentItem = function () {
|
||||
|
||||
var index = findPlaylistIndex(this.getCurrentPlaylistItemId(), this._playlist);
|
||||
|
||||
return index === -1 ? null : this._playlist[index];
|
||||
@@ -137,12 +126,10 @@ define([], function () {
|
||||
};
|
||||
|
||||
PlayQueueManager.prototype.setPlaylistState = function (playlistItemId, playlistIndex) {
|
||||
|
||||
this._currentPlaylistItemId = playlistItemId;
|
||||
};
|
||||
|
||||
PlayQueueManager.prototype.setPlaylistIndex = function (playlistIndex) {
|
||||
|
||||
if (playlistIndex < 0) {
|
||||
this.setPlaylistState(null);
|
||||
} else {
|
||||
@@ -151,7 +138,6 @@ define([], function () {
|
||||
};
|
||||
|
||||
PlayQueueManager.prototype.removeFromPlaylist = function (playlistItemIds) {
|
||||
|
||||
if (this._playlist.length <= playlistItemIds.length) {
|
||||
return {
|
||||
result: 'empty'
|
||||
@@ -180,7 +166,6 @@ define([], function () {
|
||||
}
|
||||
|
||||
PlayQueueManager.prototype.movePlaylistItem = function (playlistItemId, newIndex) {
|
||||
|
||||
var playlist = this.getPlaylist();
|
||||
|
||||
var oldIndex;
|
||||
@@ -213,7 +198,6 @@ define([], function () {
|
||||
};
|
||||
|
||||
PlayQueueManager.prototype.reset = function () {
|
||||
|
||||
this._sortedPlaylist = [];
|
||||
this._playlist = [];
|
||||
this._currentPlaylistItemId = null;
|
||||
@@ -265,13 +249,11 @@ define([], function () {
|
||||
};
|
||||
|
||||
PlayQueueManager.prototype.getNextItemInfo = function () {
|
||||
|
||||
var newIndex;
|
||||
var playlist = this.getPlaylist();
|
||||
var playlistLength = playlist.length;
|
||||
|
||||
switch (this.getRepeatMode()) {
|
||||
|
||||
case 'RepeatOne':
|
||||
newIndex = this.getCurrentPlaylistIndex();
|
||||
break;
|
||||
|
||||
@@ -23,10 +23,8 @@ function getOsdElementHtml() {
|
||||
}
|
||||
|
||||
function ensureOsdElement() {
|
||||
|
||||
var elem = osdElement;
|
||||
if (!elem) {
|
||||
|
||||
enableAnimation = browser.supportsCssAnimation();
|
||||
|
||||
elem = document.createElement('div');
|
||||
@@ -50,7 +48,6 @@ function onHideComplete() {
|
||||
|
||||
var hideTimeout;
|
||||
function showOsd() {
|
||||
|
||||
clearHideTimeout();
|
||||
|
||||
var elem = osdElement;
|
||||
@@ -79,12 +76,10 @@ function clearHideTimeout() {
|
||||
}
|
||||
|
||||
function hideOsd() {
|
||||
|
||||
clearHideTimeout();
|
||||
|
||||
var elem = osdElement;
|
||||
if (elem) {
|
||||
|
||||
if (enableAnimation) {
|
||||
// trigger reflow
|
||||
void elem.offsetWidth;
|
||||
@@ -103,7 +98,6 @@ function hideOsd() {
|
||||
}
|
||||
|
||||
function updatePlayerVolumeState(isMuted, volume) {
|
||||
|
||||
if (iconElement) {
|
||||
iconElement.classList.remove('volume_off', 'volume_up');
|
||||
iconElement.classList.add(isMuted ? 'volume_off' : 'volume_up');
|
||||
@@ -114,7 +108,6 @@ function updatePlayerVolumeState(isMuted, volume) {
|
||||
}
|
||||
|
||||
function releaseCurrentPlayer() {
|
||||
|
||||
var player = currentPlayer;
|
||||
|
||||
if (player) {
|
||||
@@ -125,7 +118,6 @@ function releaseCurrentPlayer() {
|
||||
}
|
||||
|
||||
function onVolumeChanged(e) {
|
||||
|
||||
var player = this;
|
||||
|
||||
ensureOsdElement();
|
||||
@@ -136,7 +128,6 @@ function onVolumeChanged(e) {
|
||||
}
|
||||
|
||||
function bindToPlayer(player) {
|
||||
|
||||
if (player === currentPlayer) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,39 +1,46 @@
|
||||
define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'qualityoptions', 'globalize', 'loading', 'connectionManager', 'dom', 'events', 'emby-select', 'emby-checkbox'], function (require, browser, appSettings, appHost, focusManager, qualityoptions, globalize, loading, connectionManager, dom, events) {
|
||||
'use strict';
|
||||
import browser from 'browser';
|
||||
import appSettings from 'appSettings';
|
||||
import appHost from 'apphost';
|
||||
import focusManager from 'focusManager';
|
||||
import qualityoptions from 'qualityoptions';
|
||||
import globalize from 'globalize';
|
||||
import loading from 'loading';
|
||||
import connectionManager from 'connectionManager';
|
||||
import events from 'events';
|
||||
import 'emby-select';
|
||||
import 'emby-checkbox';
|
||||
|
||||
/* eslint-disable indent */
|
||||
|
||||
function fillSkipLengths(select) {
|
||||
const options = [5, 10, 15, 20, 25, 30];
|
||||
|
||||
var options = [5, 10, 15, 20, 25, 30];
|
||||
|
||||
select.innerHTML = options.map(function (option) {
|
||||
select.innerHTML = options.map(option => {
|
||||
return {
|
||||
name: globalize.translate('ValueSeconds', option),
|
||||
value: option * 1000
|
||||
};
|
||||
}).map(function (o) {
|
||||
return '<option value="' + o.value + '">' + o.name + '</option>';
|
||||
}).map(o => {
|
||||
return `<option value="${o.value}">${o.name}</option>`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function populateLanguages(select, languages) {
|
||||
let html = '';
|
||||
|
||||
var html = '';
|
||||
html += `<option value=''>${globalize.translate('AnyLanguage')}</option>`;
|
||||
|
||||
html += "<option value=''>" + globalize.translate('AnyLanguage') + '</option>';
|
||||
for (let i = 0, length = languages.length; i < length; i++) {
|
||||
const culture = languages[i];
|
||||
|
||||
for (var i = 0, length = languages.length; i < length; i++) {
|
||||
|
||||
var culture = languages[i];
|
||||
|
||||
html += "<option value='" + culture.ThreeLetterISOLanguageName + "'>" + culture.DisplayName + '</option>';
|
||||
html += `<option value='${culture.ThreeLetterISOLanguageName}'>${culture.DisplayName}</option>`;
|
||||
}
|
||||
|
||||
select.innerHTML = html;
|
||||
}
|
||||
|
||||
function setMaxBitrateIntoField(select, isInNetwork, mediatype) {
|
||||
|
||||
var options = mediatype === 'Audio' ? qualityoptions.getAudioQualityOptions({
|
||||
const options = mediatype === 'Audio' ? qualityoptions.getAudioQualityOptions({
|
||||
|
||||
currentMaxBitrate: appSettings.maxStreamingBitrate(isInNetwork, mediatype),
|
||||
isAutomaticBitrateEnabled: appSettings.enableAutomaticBitrateDetection(isInNetwork, mediatype),
|
||||
@@ -47,10 +54,9 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
|
||||
|
||||
});
|
||||
|
||||
select.innerHTML = options.map(function (i) {
|
||||
|
||||
select.innerHTML = options.map(i => {
|
||||
// render empty string instead of 0 for the auto option
|
||||
return '<option value="' + (i.bitrate || '') + '">' + i.name + '</option>';
|
||||
return `<option value="${i.bitrate || ''}">${i.name}</option>`;
|
||||
}).join('');
|
||||
|
||||
if (appSettings.enableAutomaticBitrateDetection(isInNetwork, mediatype)) {
|
||||
@@ -61,25 +67,22 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
|
||||
}
|
||||
|
||||
function fillChromecastQuality(select) {
|
||||
|
||||
var options = qualityoptions.getVideoQualityOptions({
|
||||
const options = qualityoptions.getVideoQualityOptions({
|
||||
|
||||
currentMaxBitrate: appSettings.maxChromecastBitrate(),
|
||||
isAutomaticBitrateEnabled: !appSettings.maxChromecastBitrate(),
|
||||
enableAuto: true
|
||||
});
|
||||
|
||||
select.innerHTML = options.map(function (i) {
|
||||
|
||||
select.innerHTML = options.map(i => {
|
||||
// render empty string instead of 0 for the auto option
|
||||
return '<option value="' + (i.bitrate || '') + '">' + i.name + '</option>';
|
||||
return `<option value="${i.bitrate || ''}">${i.name}</option>`;
|
||||
}).join('');
|
||||
|
||||
select.value = appSettings.maxChromecastBitrate() || '';
|
||||
}
|
||||
|
||||
function setMaxBitrateFromField(select, isInNetwork, mediatype, value) {
|
||||
|
||||
function setMaxBitrateFromField(select, isInNetwork, mediatype) {
|
||||
if (select.value) {
|
||||
appSettings.maxStreamingBitrate(isInNetwork, mediatype, select.value);
|
||||
appSettings.enableAutomaticBitrateDetection(isInNetwork, mediatype, false);
|
||||
@@ -89,7 +92,6 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
|
||||
}
|
||||
|
||||
function showHideQualityFields(context, user, apiClient) {
|
||||
|
||||
if (user.Policy.EnableVideoPlaybackTranscoding) {
|
||||
context.querySelector('.videoQualitySection').classList.remove('hide');
|
||||
} else {
|
||||
@@ -97,7 +99,6 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
|
||||
}
|
||||
|
||||
if (appHost.supports('multiserver')) {
|
||||
|
||||
context.querySelector('.fldVideoInNetworkQuality').classList.remove('hide');
|
||||
context.querySelector('.fldVideoInternetQuality').classList.remove('hide');
|
||||
|
||||
@@ -110,16 +111,13 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
|
||||
return;
|
||||
}
|
||||
|
||||
apiClient.getEndpointInfo().then(function (endpointInfo) {
|
||||
|
||||
apiClient.getEndpointInfo().then(endpointInfo => {
|
||||
if (endpointInfo.IsInNetwork) {
|
||||
|
||||
context.querySelector('.fldVideoInNetworkQuality').classList.remove('hide');
|
||||
|
||||
context.querySelector('.fldVideoInternetQuality').classList.add('hide');
|
||||
context.querySelector('.musicQualitySection').classList.add('hide');
|
||||
} else {
|
||||
|
||||
context.querySelector('.fldVideoInNetworkQuality').classList.add('hide');
|
||||
|
||||
context.querySelector('.fldVideoInternetQuality').classList.remove('hide');
|
||||
@@ -133,8 +131,7 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
|
||||
});
|
||||
}
|
||||
|
||||
function showOrHideEpisodesField(context, user, apiClient) {
|
||||
|
||||
function showOrHideEpisodesField(context) {
|
||||
if (browser.tizen || browser.web0s) {
|
||||
context.querySelector('.fldEpisodeAutoPlay').classList.add('hide');
|
||||
return;
|
||||
@@ -144,14 +141,12 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
|
||||
}
|
||||
|
||||
function loadForm(context, user, userSettings, apiClient) {
|
||||
|
||||
var loggedInUserId = apiClient.getCurrentUserId();
|
||||
var userId = user.Id;
|
||||
const loggedInUserId = apiClient.getCurrentUserId();
|
||||
const userId = user.Id;
|
||||
|
||||
showHideQualityFields(context, user, apiClient);
|
||||
|
||||
apiClient.getCultures().then(function (allCultures) {
|
||||
|
||||
apiClient.getCultures().then(allCultures => {
|
||||
populateLanguages(context.querySelector('#selectAudioLanguage'), allCultures);
|
||||
|
||||
context.querySelector('#selectAudioLanguage', context).value = user.Configuration.AudioLanguagePreference || '';
|
||||
@@ -159,8 +154,7 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
|
||||
});
|
||||
|
||||
// hide cinema mode options if disabled at server level
|
||||
apiClient.getNamedConfiguration('cinemamode').then(function (cinemaConfig) {
|
||||
|
||||
apiClient.getNamedConfiguration('cinemamode').then(cinemaConfig => {
|
||||
if (cinemaConfig.EnableIntrosForMovies || cinemaConfig.EnableIntrosForEpisodes) {
|
||||
context.querySelector('.cinemaModeOptions').classList.remove('hide');
|
||||
} else {
|
||||
@@ -204,24 +198,23 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
|
||||
|
||||
fillChromecastQuality(context.querySelector('.selectChromecastVideoQuality'));
|
||||
|
||||
var selectChromecastVersion = context.querySelector('.selectChromecastVersion');
|
||||
const selectChromecastVersion = context.querySelector('.selectChromecastVersion');
|
||||
selectChromecastVersion.value = userSettings.chromecastVersion();
|
||||
|
||||
var selectSkipForwardLength = context.querySelector('.selectSkipForwardLength');
|
||||
const selectSkipForwardLength = context.querySelector('.selectSkipForwardLength');
|
||||
fillSkipLengths(selectSkipForwardLength);
|
||||
selectSkipForwardLength.value = userSettings.skipForwardLength();
|
||||
|
||||
var selectSkipBackLength = context.querySelector('.selectSkipBackLength');
|
||||
const selectSkipBackLength = context.querySelector('.selectSkipBackLength');
|
||||
fillSkipLengths(selectSkipBackLength);
|
||||
selectSkipBackLength.value = userSettings.skipBackLength();
|
||||
|
||||
showOrHideEpisodesField(context, user, apiClient);
|
||||
showOrHideEpisodesField(context);
|
||||
|
||||
loading.hide();
|
||||
}
|
||||
|
||||
function saveUser(context, user, userSettingsInstance, apiClient) {
|
||||
|
||||
appSettings.enableSystemExternalPlayers(context.querySelector('.chkExternalVideoPlayer').checked);
|
||||
|
||||
appSettings.maxChromecastBitrate(context.querySelector('.selectChromecastVideoQuality').value);
|
||||
@@ -245,38 +238,32 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
|
||||
}
|
||||
|
||||
function save(instance, context, userId, userSettings, apiClient, enableSaveConfirmation) {
|
||||
|
||||
loading.show();
|
||||
|
||||
apiClient.getUser(userId).then(function (user) {
|
||||
|
||||
saveUser(context, user, userSettings, apiClient).then(function () {
|
||||
|
||||
apiClient.getUser(userId).then(user => {
|
||||
saveUser(context, user, userSettings, apiClient).then(() => {
|
||||
loading.hide();
|
||||
if (enableSaveConfirmation) {
|
||||
require(['toast'], function (toast) {
|
||||
import('toast').then(({default: toast}) => {
|
||||
toast(globalize.translate('SettingsSaved'));
|
||||
});
|
||||
}
|
||||
|
||||
events.trigger(instance, 'saved');
|
||||
|
||||
}, function () {
|
||||
}, () => {
|
||||
loading.hide();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function onSubmit(e) {
|
||||
const self = this;
|
||||
const apiClient = connectionManager.getApiClient(self.options.serverId);
|
||||
const userId = self.options.userId;
|
||||
const userSettings = self.options.userSettings;
|
||||
|
||||
var self = this;
|
||||
var apiClient = connectionManager.getApiClient(self.options.serverId);
|
||||
var userId = self.options.userId;
|
||||
var userSettings = self.options.userSettings;
|
||||
|
||||
userSettings.setUserInfo(userId, apiClient).then(function () {
|
||||
|
||||
var enableSaveConfirmation = self.options.enableSaveConfirmation;
|
||||
userSettings.setUserInfo(userId, apiClient).then(() => {
|
||||
const enableSaveConfirmation = self.options.enableSaveConfirmation;
|
||||
save(self, self.options.element, userId, userSettings, apiClient, enableSaveConfirmation);
|
||||
});
|
||||
|
||||
@@ -288,10 +275,8 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
|
||||
}
|
||||
|
||||
function embed(options, self) {
|
||||
|
||||
require(['text!./playbackSettings.template.html'], function (template) {
|
||||
|
||||
options.element.innerHTML = globalize.translateDocument(template, 'core');
|
||||
return import('text!./playbackSettings.template.html').then(({default: template}) => {
|
||||
options.element.innerHTML = globalize.translateHtml(template, 'core');
|
||||
|
||||
options.element.querySelector('form').addEventListener('submit', onSubmit.bind(self));
|
||||
|
||||
@@ -307,43 +292,39 @@ define(['require', 'browser', 'appSettings', 'apphost', 'focusManager', 'quality
|
||||
});
|
||||
}
|
||||
|
||||
function PlaybackSettings(options) {
|
||||
class PlaybackSettings {
|
||||
constructor(options) {
|
||||
this.options = options;
|
||||
embed(options, this);
|
||||
}
|
||||
|
||||
this.options = options;
|
||||
loadData() {
|
||||
const self = this;
|
||||
const context = self.options.element;
|
||||
|
||||
embed(options, this);
|
||||
loading.show();
|
||||
|
||||
const userId = self.options.userId;
|
||||
const apiClient = connectionManager.getApiClient(self.options.serverId);
|
||||
const userSettings = self.options.userSettings;
|
||||
|
||||
apiClient.getUser(userId).then(user => {
|
||||
userSettings.setUserInfo(userId, apiClient).then(() => {
|
||||
self.dataLoaded = true;
|
||||
|
||||
loadForm(context, user, userSettings, apiClient);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
submit() {
|
||||
onSubmit.call(this);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.options = null;
|
||||
}
|
||||
}
|
||||
|
||||
PlaybackSettings.prototype.loadData = function () {
|
||||
|
||||
var self = this;
|
||||
var context = self.options.element;
|
||||
|
||||
loading.show();
|
||||
|
||||
var userId = self.options.userId;
|
||||
var apiClient = connectionManager.getApiClient(self.options.serverId);
|
||||
var userSettings = self.options.userSettings;
|
||||
|
||||
apiClient.getUser(userId).then(function (user) {
|
||||
|
||||
userSettings.setUserInfo(userId, apiClient).then(function () {
|
||||
|
||||
self.dataLoaded = true;
|
||||
|
||||
loadForm(context, user, userSettings, apiClient);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
PlaybackSettings.prototype.submit = function () {
|
||||
onSubmit.call(this);
|
||||
};
|
||||
|
||||
PlaybackSettings.prototype.destroy = function () {
|
||||
|
||||
this.options = null;
|
||||
};
|
||||
|
||||
return PlaybackSettings;
|
||||
});
|
||||
/* eslint-enable indent */
|
||||
export default PlaybackSettings;
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlayManager', 'playMethodHelper', 'layoutManager', 'serverNotifications', 'paper-icon-button-light', 'css!./playerstats'], function (events, globalize, playbackManager, connectionManager, syncPlayManager, playMethodHelper, layoutManager, serverNotifications) {
|
||||
'use strict';
|
||||
import events from 'events';
|
||||
import globalize from 'globalize';
|
||||
import playbackManager from 'playbackManager';
|
||||
import connectionManager from 'connectionManager';
|
||||
import syncPlayManager from 'syncPlayManager';
|
||||
import playMethodHelper from 'playMethodHelper';
|
||||
import layoutManager from 'layoutManager';
|
||||
import 'paper-icon-button-light';
|
||||
import 'css!./playerstats';
|
||||
|
||||
/* eslint-disable indent */
|
||||
|
||||
function init(instance) {
|
||||
|
||||
var parent = document.createElement('div');
|
||||
const parent = document.createElement('div');
|
||||
|
||||
parent.classList.add('playerStats');
|
||||
|
||||
@@ -13,7 +21,7 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
|
||||
parent.classList.add('hide');
|
||||
|
||||
var button;
|
||||
let button;
|
||||
|
||||
if (layoutManager.tv) {
|
||||
button = '';
|
||||
@@ -21,7 +29,7 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
button = '<button type="button" is="paper-icon-button-light" class="playerStats-closeButton"><span class="material-icons close"></span></button>';
|
||||
}
|
||||
|
||||
var contentClass = layoutManager.tv ? 'playerStats-content playerStats-content-tv' : 'playerStats-content';
|
||||
const contentClass = layoutManager.tv ? 'playerStats-content playerStats-content-tv' : 'playerStats-content';
|
||||
|
||||
parent.innerHTML = '<div class="' + contentClass + '">' + button + '<div class="playerStats-stats"></div></div>';
|
||||
|
||||
@@ -41,12 +49,10 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
}
|
||||
|
||||
function renderStats(elem, categories) {
|
||||
|
||||
elem.querySelector('.playerStats-stats').innerHTML = categories.map(function (category) {
|
||||
let categoryHtml = '';
|
||||
|
||||
var categoryHtml = '';
|
||||
|
||||
var stats = category.stats;
|
||||
const stats = category.stats;
|
||||
|
||||
if (stats.length && category.name) {
|
||||
categoryHtml += '<div class="playerStats-stat playerStats-stat-header">';
|
||||
@@ -62,11 +68,10 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
categoryHtml += '</div>';
|
||||
}
|
||||
|
||||
for (var i = 0, length = stats.length; i < length; i++) {
|
||||
|
||||
for (let i = 0, length = stats.length; i < length; i++) {
|
||||
categoryHtml += '<div class="playerStats-stat">';
|
||||
|
||||
var stat = stats[i];
|
||||
const stat = stats[i];
|
||||
|
||||
categoryHtml += '<div class="playerStats-stat-label">';
|
||||
categoryHtml += stat.label;
|
||||
@@ -80,49 +85,43 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
}
|
||||
|
||||
return categoryHtml;
|
||||
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function getSession(instance, player) {
|
||||
|
||||
var now = new Date().getTime();
|
||||
const now = new Date().getTime();
|
||||
|
||||
if ((now - (instance.lastSessionTime || 0)) < 10000) {
|
||||
return Promise.resolve(instance.lastSession);
|
||||
}
|
||||
|
||||
var apiClient = connectionManager.getApiClient(playbackManager.currentItem(player).ServerId);
|
||||
const apiClient = connectionManager.getApiClient(playbackManager.currentItem(player).ServerId);
|
||||
|
||||
return apiClient.getSessions({
|
||||
deviceId: apiClient.deviceId()
|
||||
}).then(function (sessions) {
|
||||
|
||||
instance.lastSession = sessions[0] || {};
|
||||
instance.lastSessionTime = new Date().getTime();
|
||||
|
||||
return Promise.resolve(instance.lastSession);
|
||||
|
||||
}, function () {
|
||||
return Promise.resolve({});
|
||||
});
|
||||
}
|
||||
|
||||
function translateReason(reason) {
|
||||
|
||||
return globalize.translate('' + reason);
|
||||
}
|
||||
|
||||
function getTranscodingStats(session, player, displayPlayMethod) {
|
||||
var sessionStats = [];
|
||||
const sessionStats = [];
|
||||
|
||||
var videoCodec;
|
||||
var audioCodec;
|
||||
var totalBitrate;
|
||||
var audioChannels;
|
||||
let videoCodec;
|
||||
let audioCodec;
|
||||
let totalBitrate;
|
||||
let audioChannels;
|
||||
|
||||
if (session.TranscodingInfo) {
|
||||
|
||||
videoCodec = session.TranscodingInfo.VideoCodec;
|
||||
audioCodec = session.TranscodingInfo.AudioCodec;
|
||||
totalBitrate = session.TranscodingInfo.Bitrate;
|
||||
@@ -130,7 +129,6 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
}
|
||||
|
||||
if (videoCodec) {
|
||||
|
||||
sessionStats.push({
|
||||
label: globalize.translate('LabelVideoCodec'),
|
||||
value: session.TranscodingInfo.IsVideoDirect ? (videoCodec.toUpperCase() + ' (direct)') : videoCodec.toUpperCase()
|
||||
@@ -138,45 +136,39 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
}
|
||||
|
||||
if (audioCodec) {
|
||||
|
||||
sessionStats.push({
|
||||
label: globalize.translate('LabelAudioCodec'),
|
||||
value: session.TranscodingInfo.IsAudioDirect ? (audioCodec.toUpperCase() + ' (direct)') : audioCodec.toUpperCase()
|
||||
});
|
||||
}
|
||||
|
||||
//if (audioChannels) {
|
||||
|
||||
// sessionStats.push({
|
||||
// label: 'Audio channels:',
|
||||
// value: audioChannels
|
||||
// });
|
||||
//}
|
||||
if (audioChannels) {
|
||||
sessionStats.push({
|
||||
label: globalize.translate('LabelAudioChannels'),
|
||||
value: audioChannels
|
||||
});
|
||||
}
|
||||
|
||||
if (displayPlayMethod === 'Transcode') {
|
||||
if (totalBitrate) {
|
||||
|
||||
sessionStats.push({
|
||||
label: globalize.translate('LabelBitrate'),
|
||||
value: getDisplayBitrate(totalBitrate)
|
||||
});
|
||||
}
|
||||
if (session.TranscodingInfo.CompletionPercentage) {
|
||||
|
||||
sessionStats.push({
|
||||
label: globalize.translate('LabelTranscodingProgress'),
|
||||
value: session.TranscodingInfo.CompletionPercentage.toFixed(1) + '%'
|
||||
});
|
||||
}
|
||||
if (session.TranscodingInfo.Framerate) {
|
||||
|
||||
sessionStats.push({
|
||||
label: globalize.translate('LabelTranscodingFramerate'),
|
||||
value: session.TranscodingInfo.Framerate + ' fps'
|
||||
});
|
||||
}
|
||||
if (session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo.TranscodeReasons.length) {
|
||||
|
||||
sessionStats.push({
|
||||
label: globalize.translate('LabelReasonForTranscoding'),
|
||||
value: session.TranscodingInfo.TranscodeReasons.map(translateReason).join('<br/>')
|
||||
@@ -188,7 +180,6 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
}
|
||||
|
||||
function getDisplayBitrate(bitrate) {
|
||||
|
||||
if (bitrate > 1000000) {
|
||||
return (bitrate / 1000000).toFixed(1) + ' Mbps';
|
||||
} else {
|
||||
@@ -207,12 +198,11 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
}
|
||||
|
||||
function getMediaSourceStats(session, player, displayPlayMethod) {
|
||||
const sessionStats = [];
|
||||
|
||||
var sessionStats = [];
|
||||
|
||||
var mediaSource = playbackManager.currentMediaSource(player) || {};
|
||||
var totalBitrate = mediaSource.Bitrate;
|
||||
var mediaFileSize = mediaSource.Size;
|
||||
const mediaSource = playbackManager.currentMediaSource(player) || {};
|
||||
const totalBitrate = mediaSource.Bitrate;
|
||||
const mediaFileSize = mediaSource.Size;
|
||||
|
||||
if (mediaSource.Container) {
|
||||
sessionStats.push({
|
||||
@@ -229,33 +219,28 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
}
|
||||
|
||||
if (totalBitrate) {
|
||||
|
||||
sessionStats.push({
|
||||
label: globalize.translate('LabelBitrate'),
|
||||
value: getDisplayBitrate(totalBitrate)
|
||||
});
|
||||
}
|
||||
|
||||
var mediaStreams = mediaSource.MediaStreams || [];
|
||||
var videoStream = mediaStreams.filter(function (s) {
|
||||
|
||||
const mediaStreams = mediaSource.MediaStreams || [];
|
||||
const videoStream = mediaStreams.filter(function (s) {
|
||||
return s.Type === 'Video';
|
||||
|
||||
})[0] || {};
|
||||
|
||||
var videoCodec = videoStream.Codec;
|
||||
|
||||
var audioStreamIndex = playbackManager.getAudioStreamIndex(player);
|
||||
var audioStream = playbackManager.audioTracks(player).filter(function (s) {
|
||||
const videoCodec = videoStream.Codec;
|
||||
|
||||
const audioStreamIndex = playbackManager.getAudioStreamIndex(player);
|
||||
const audioStream = playbackManager.audioTracks(player).filter(function (s) {
|
||||
return s.Type === 'Audio' && s.Index === audioStreamIndex;
|
||||
|
||||
})[0] || {};
|
||||
|
||||
var audioCodec = audioStream.Codec;
|
||||
var audioChannels = audioStream.Channels;
|
||||
const audioCodec = audioStream.Codec;
|
||||
const audioChannels = audioStream.Channels;
|
||||
|
||||
var videoInfos = [];
|
||||
const videoInfos = [];
|
||||
|
||||
if (videoCodec) {
|
||||
videoInfos.push(videoCodec.toUpperCase());
|
||||
@@ -279,7 +264,7 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
});
|
||||
}
|
||||
|
||||
var audioInfos = [];
|
||||
const audioInfos = [];
|
||||
|
||||
if (audioCodec) {
|
||||
audioInfos.push(audioCodec.toUpperCase());
|
||||
@@ -328,8 +313,8 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
}
|
||||
|
||||
function getSyncPlayStats() {
|
||||
var syncStats = [];
|
||||
var stats = syncPlayManager.getStats();
|
||||
const syncStats = [];
|
||||
const stats = syncPlayManager.getStats();
|
||||
|
||||
syncStats.push({
|
||||
label: globalize.translate('LabelSyncPlayTimeOffset'),
|
||||
@@ -350,19 +335,17 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
}
|
||||
|
||||
function getStats(instance, player) {
|
||||
|
||||
var statsPromise = player.getStats ? player.getStats() : Promise.resolve({});
|
||||
var sessionPromise = getSession(instance, player);
|
||||
const statsPromise = player.getStats ? player.getStats() : Promise.resolve({});
|
||||
const sessionPromise = getSession(instance, player);
|
||||
|
||||
return Promise.all([statsPromise, sessionPromise]).then(function (responses) {
|
||||
const playerStatsResult = responses[0];
|
||||
const playerStats = playerStatsResult.categories || [];
|
||||
const session = responses[1];
|
||||
|
||||
var playerStatsResult = responses[0];
|
||||
var playerStats = playerStatsResult.categories || [];
|
||||
var session = responses[1];
|
||||
const displayPlayMethod = playMethodHelper.getDisplayPlayMethod(session);
|
||||
|
||||
var displayPlayMethod = playMethodHelper.getDisplayPlayMethod(session);
|
||||
|
||||
var baseCategory = {
|
||||
const baseCategory = {
|
||||
stats: [],
|
||||
name: 'Playback Info'
|
||||
};
|
||||
@@ -377,13 +360,12 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
value: player.name
|
||||
});
|
||||
|
||||
var categories = [];
|
||||
const categories = [];
|
||||
|
||||
categories.push(baseCategory);
|
||||
|
||||
for (var i = 0, length = playerStats.length; i < length; i++) {
|
||||
|
||||
var category = playerStats[i];
|
||||
for (let i = 0, length = playerStats.length; i < length; i++) {
|
||||
const category = playerStats[i];
|
||||
if (category.type === 'audio') {
|
||||
category.name = 'Audio Info';
|
||||
} else if (category.type === 'video') {
|
||||
@@ -393,7 +375,6 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
}
|
||||
|
||||
if (session.TranscodingInfo) {
|
||||
|
||||
categories.push({
|
||||
stats: getTranscodingStats(session, player, displayPlayMethod),
|
||||
name: displayPlayMethod === 'Transcode' ? 'Transcoding Info' : 'Direct Stream Info'
|
||||
@@ -405,7 +386,8 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
name: 'Original Media Info'
|
||||
});
|
||||
|
||||
if (syncPlayManager.isSyncPlayEnabled()) {
|
||||
var apiClient = connectionManager.getApiClient(playbackManager.currentItem(player).ServerId);
|
||||
if (syncPlayManager.isSyncPlayEnabled() && apiClient.isMinServerVersion('10.6.0')) {
|
||||
categories.push({
|
||||
stats: getSyncPlayStats(),
|
||||
name: 'SyncPlay Info'
|
||||
@@ -417,8 +399,7 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
}
|
||||
|
||||
function renderPlayerStats(instance, player) {
|
||||
|
||||
var now = new Date().getTime();
|
||||
const now = new Date().getTime();
|
||||
|
||||
if ((now - (instance.lastRender || 0)) < 700) {
|
||||
return;
|
||||
@@ -427,8 +408,7 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
instance.lastRender = now;
|
||||
|
||||
getStats(instance, player).then(function (stats) {
|
||||
|
||||
var elem = instance.element;
|
||||
const elem = instance.element;
|
||||
if (!elem) {
|
||||
return;
|
||||
}
|
||||
@@ -438,8 +418,7 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
}
|
||||
|
||||
function bindEvents(instance, player) {
|
||||
|
||||
var localOnTimeUpdate = function () {
|
||||
const localOnTimeUpdate = function () {
|
||||
renderPlayerStats(instance, player);
|
||||
};
|
||||
|
||||
@@ -448,16 +427,15 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
}
|
||||
|
||||
function unbindEvents(instance, player) {
|
||||
|
||||
var localOnTimeUpdate = instance.onTimeUpdate;
|
||||
const localOnTimeUpdate = instance.onTimeUpdate;
|
||||
|
||||
if (localOnTimeUpdate) {
|
||||
events.off(player, 'timeupdate', localOnTimeUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
function PlayerStats(options) {
|
||||
|
||||
class PlayerStats {
|
||||
constructor(options) {
|
||||
this.options = options;
|
||||
|
||||
init(this);
|
||||
@@ -465,13 +443,12 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
this.enabled(true);
|
||||
}
|
||||
|
||||
PlayerStats.prototype.enabled = function (enabled) {
|
||||
|
||||
enabled(enabled) {
|
||||
if (enabled == null) {
|
||||
return this._enabled;
|
||||
}
|
||||
|
||||
var options = this.options;
|
||||
const options = this.options;
|
||||
|
||||
if (!options) {
|
||||
return;
|
||||
@@ -485,28 +462,28 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
|
||||
this.element.classList.add('hide');
|
||||
unbindEvents(this, options.player);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
PlayerStats.prototype.toggle = function () {
|
||||
toggle() {
|
||||
this.enabled(!this.enabled());
|
||||
};
|
||||
}
|
||||
|
||||
PlayerStats.prototype.destroy = function () {
|
||||
|
||||
var options = this.options;
|
||||
destroy() {
|
||||
const options = this.options;
|
||||
|
||||
if (options) {
|
||||
|
||||
this.options = null;
|
||||
unbindEvents(this, options.player);
|
||||
}
|
||||
|
||||
var elem = this.element;
|
||||
const elem = this.element;
|
||||
if (elem) {
|
||||
elem.parentNode.removeChild(elem);
|
||||
this.element = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return PlayerStats;
|
||||
});
|
||||
/* eslint-enable indent */
|
||||
|
||||
export default PlayerStats;
|
||||
|
||||
@@ -1,13 +1,28 @@
|
||||
define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackManager', 'connectionManager', 'userSettings', 'appRouter', 'globalize', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button'], function (dom, shell, dialogHelper, loading, layoutManager, playbackManager, connectionManager, userSettings, appRouter, globalize) {
|
||||
'use strict';
|
||||
import dom from 'dom';
|
||||
import dialogHelper from 'dialogHelper';
|
||||
import loading from 'loading';
|
||||
import layoutManager from 'layoutManager';
|
||||
import playbackManager from 'playbackManager';
|
||||
import connectionManager from 'connectionManager';
|
||||
import * as userSettings from 'userSettings';
|
||||
import appRouter from 'appRouter';
|
||||
import globalize from 'globalize';
|
||||
import 'emby-input';
|
||||
import 'paper-icon-button-light';
|
||||
import 'emby-select';
|
||||
import 'material-icons';
|
||||
import 'css!./../formdialog';
|
||||
import 'emby-button';
|
||||
|
||||
var currentServerId;
|
||||
/* eslint-disable indent */
|
||||
|
||||
let currentServerId;
|
||||
|
||||
function onSubmit(e) {
|
||||
var panel = dom.parentWithClass(this, 'dialog');
|
||||
const panel = dom.parentWithClass(this, 'dialog');
|
||||
|
||||
var playlistId = panel.querySelector('#selectPlaylistToAddTo').value;
|
||||
var apiClient = connectionManager.getApiClient(currentServerId);
|
||||
const playlistId = panel.querySelector('#selectPlaylistToAddTo').value;
|
||||
const apiClient = connectionManager.getApiClient(currentServerId);
|
||||
|
||||
if (playlistId) {
|
||||
userSettings.set('playlisteditor-lastplaylistid', playlistId);
|
||||
@@ -23,7 +38,7 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
|
||||
function createPlaylist(apiClient, dlg) {
|
||||
loading.show();
|
||||
|
||||
var url = apiClient.getUrl('Playlists', {
|
||||
const url = apiClient.getUrl('Playlists', {
|
||||
Name: dlg.querySelector('#txtNewPlaylistName').value,
|
||||
Ids: dlg.querySelector('.fldSelectedItemIds').value || '',
|
||||
userId: apiClient.getCurrentUserId()
|
||||
@@ -34,10 +49,10 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
|
||||
type: 'POST',
|
||||
url: url,
|
||||
dataType: 'json'
|
||||
}).then(function (result) {
|
||||
}).then(result => {
|
||||
loading.hide();
|
||||
|
||||
var id = result.Id;
|
||||
const id = result.Id;
|
||||
dlg.submitted = true;
|
||||
dialogHelper.close(dlg);
|
||||
redirectToPlaylist(apiClient, id);
|
||||
@@ -49,7 +64,7 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
|
||||
}
|
||||
|
||||
function addToPlaylist(apiClient, dlg, id) {
|
||||
var itemIds = dlg.querySelector('.fldSelectedItemIds').value || '';
|
||||
const itemIds = dlg.querySelector('.fldSelectedItemIds').value || '';
|
||||
|
||||
if (id === 'queue') {
|
||||
playbackManager.queue({
|
||||
@@ -63,7 +78,7 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
|
||||
|
||||
loading.show();
|
||||
|
||||
var url = apiClient.getUrl('Playlists/' + id + '/Items', {
|
||||
const url = apiClient.getUrl(`Playlists/${id}/Items`, {
|
||||
Ids: itemIds,
|
||||
userId: apiClient.getCurrentUserId()
|
||||
});
|
||||
@@ -72,7 +87,7 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
|
||||
type: 'POST',
|
||||
url: url
|
||||
|
||||
}).then(function () {
|
||||
}).then(() => {
|
||||
loading.hide();
|
||||
|
||||
dlg.submitted = true;
|
||||
@@ -85,36 +100,36 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
|
||||
}
|
||||
|
||||
function populatePlaylists(editorOptions, panel) {
|
||||
var select = panel.querySelector('#selectPlaylistToAddTo');
|
||||
const select = panel.querySelector('#selectPlaylistToAddTo');
|
||||
|
||||
loading.hide();
|
||||
|
||||
panel.querySelector('.newPlaylistInfo').classList.add('hide');
|
||||
|
||||
var options = {
|
||||
const options = {
|
||||
Recursive: true,
|
||||
IncludeItemTypes: 'Playlist',
|
||||
SortBy: 'SortName',
|
||||
EnableTotalRecordCount: false
|
||||
};
|
||||
|
||||
var apiClient = connectionManager.getApiClient(currentServerId);
|
||||
apiClient.getItems(apiClient.getCurrentUserId(), options).then(function (result) {
|
||||
var html = '';
|
||||
const apiClient = connectionManager.getApiClient(currentServerId);
|
||||
apiClient.getItems(apiClient.getCurrentUserId(), options).then(result => {
|
||||
let html = '';
|
||||
|
||||
if (editorOptions.enableAddToPlayQueue !== false && playbackManager.isPlaying()) {
|
||||
html += '<option value="queue">' + globalize.translate('AddToPlayQueue') + '</option>';
|
||||
html += `<option value="queue">${globalize.translate('AddToPlayQueue')}</option>`;
|
||||
}
|
||||
|
||||
html += '<option value="">' + globalize.translate('OptionNew') + '</option>';
|
||||
html += `<option value="">${globalize.translate('OptionNew')}</option>`;
|
||||
|
||||
html += result.Items.map(function (i) {
|
||||
return '<option value="' + i.Id + '">' + i.Name + '</option>';
|
||||
html += result.Items.map(i => {
|
||||
return `<option value="${i.Id}">${i.Name}</option>`;
|
||||
});
|
||||
|
||||
select.innerHTML = html;
|
||||
|
||||
var defaultValue = editorOptions.defaultValue;
|
||||
let defaultValue = editorOptions.defaultValue;
|
||||
if (!defaultValue) {
|
||||
defaultValue = userSettings.get('playlisteditor-lastplaylistid') || '';
|
||||
}
|
||||
@@ -132,29 +147,29 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
|
||||
}
|
||||
|
||||
function getEditorHtml(items) {
|
||||
var html = '';
|
||||
let html = '';
|
||||
|
||||
html += '<div class="formDialogContent smoothScrollY" style="padding-top:2em;">';
|
||||
html += '<div class="dialogContentInner dialog-content-centered">';
|
||||
html += '<form style="margin:auto;">';
|
||||
|
||||
html += '<div class="fldSelectPlaylist selectContainer">';
|
||||
var autoFocus = items.length ? ' autofocus' : '';
|
||||
html += '<select is="emby-select" id="selectPlaylistToAddTo" label="' + globalize.translate('LabelPlaylist') + '"' + autoFocus + '></select>';
|
||||
let autoFocus = items.length ? ' autofocus' : '';
|
||||
html += `<select is="emby-select" id="selectPlaylistToAddTo" label="${globalize.translate('LabelPlaylist')}"${autoFocus}></select>`;
|
||||
html += '</div>';
|
||||
|
||||
html += '<div class="newPlaylistInfo">';
|
||||
|
||||
html += '<div class="inputContainer">';
|
||||
autoFocus = items.length ? '' : ' autofocus';
|
||||
html += '<input is="emby-input" type="text" id="txtNewPlaylistName" required="required" label="' + globalize.translate('LabelName') + '"' + autoFocus + ' />';
|
||||
html += `<input is="emby-input" type="text" id="txtNewPlaylistName" required="required" label="${globalize.translate('LabelName')}"${autoFocus} />`;
|
||||
html += '</div>';
|
||||
|
||||
// newPlaylistInfo
|
||||
html += '</div>';
|
||||
|
||||
html += '<div class="formDialogFooter">';
|
||||
html += '<button is="emby-button" type="submit" class="raised btnSubmit block formDialogFooterItem button-submit">' + globalize.translate('Add') + '</button>';
|
||||
html += `<button is="emby-button" type="submit" class="raised btnSubmit block formDialogFooterItem button-submit">${globalize.translate('Add')}</button>`;
|
||||
html += '</div>';
|
||||
|
||||
html += '<input type="hidden" class="fldSelectedItemIds" />';
|
||||
@@ -187,7 +202,7 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
|
||||
} else {
|
||||
content.querySelector('.fldSelectPlaylist').classList.add('hide');
|
||||
|
||||
var selectPlaylistToAddTo = content.querySelector('#selectPlaylistToAddTo');
|
||||
const selectPlaylistToAddTo = content.querySelector('#selectPlaylistToAddTo');
|
||||
selectPlaylistToAddTo.innerHTML = '';
|
||||
selectPlaylistToAddTo.value = '';
|
||||
triggerChange(selectPlaylistToAddTo);
|
||||
@@ -195,72 +210,70 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'playbackMan
|
||||
}
|
||||
|
||||
function centerFocus(elem, horiz, on) {
|
||||
require(['scrollHelper'], function (scrollHelper) {
|
||||
var fn = on ? 'on' : 'off';
|
||||
import('scrollHelper').then(scrollHelper => {
|
||||
const fn = on ? 'on' : 'off';
|
||||
scrollHelper.centerFocus[fn](elem, horiz);
|
||||
});
|
||||
}
|
||||
|
||||
function PlaylistEditor() {
|
||||
export class showEditor {
|
||||
constructor(options) {
|
||||
const items = options.items || {};
|
||||
currentServerId = options.serverId;
|
||||
|
||||
const dialogOptions = {
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
};
|
||||
|
||||
if (layoutManager.tv) {
|
||||
dialogOptions.size = 'fullscreen';
|
||||
} else {
|
||||
dialogOptions.size = 'small';
|
||||
}
|
||||
|
||||
const dlg = dialogHelper.createDialog(dialogOptions);
|
||||
|
||||
dlg.classList.add('formDialog');
|
||||
|
||||
let html = '';
|
||||
const title = globalize.translate('HeaderAddToPlaylist');
|
||||
|
||||
html += '<div class="formDialogHeader">';
|
||||
html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
|
||||
html += '<h3 class="formDialogHeaderTitle">';
|
||||
html += title;
|
||||
html += '</h3>';
|
||||
|
||||
html += '</div>';
|
||||
|
||||
html += getEditorHtml(items);
|
||||
|
||||
dlg.innerHTML = html;
|
||||
|
||||
initEditor(dlg, options, items);
|
||||
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', () => {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
|
||||
if (layoutManager.tv) {
|
||||
centerFocus(dlg.querySelector('.formDialogContent'), false, true);
|
||||
}
|
||||
|
||||
return dialogHelper.open(dlg).then(() => {
|
||||
if (layoutManager.tv) {
|
||||
centerFocus(dlg.querySelector('.formDialogContent'), false, false);
|
||||
}
|
||||
|
||||
if (dlg.submitted) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return Promise.reject();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
PlaylistEditor.prototype.show = function (options) {
|
||||
var items = options.items || {};
|
||||
currentServerId = options.serverId;
|
||||
|
||||
var dialogOptions = {
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
};
|
||||
|
||||
if (layoutManager.tv) {
|
||||
dialogOptions.size = 'fullscreen';
|
||||
} else {
|
||||
dialogOptions.size = 'small';
|
||||
}
|
||||
|
||||
var dlg = dialogHelper.createDialog(dialogOptions);
|
||||
|
||||
dlg.classList.add('formDialog');
|
||||
|
||||
var html = '';
|
||||
var title = globalize.translate('HeaderAddToPlaylist');
|
||||
|
||||
html += '<div class="formDialogHeader">';
|
||||
html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
|
||||
html += '<h3 class="formDialogHeaderTitle">';
|
||||
html += title;
|
||||
html += '</h3>';
|
||||
|
||||
html += '</div>';
|
||||
|
||||
html += getEditorHtml(items);
|
||||
|
||||
dlg.innerHTML = html;
|
||||
|
||||
initEditor(dlg, options, items);
|
||||
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', function () {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
|
||||
if (layoutManager.tv) {
|
||||
centerFocus(dlg.querySelector('.formDialogContent'), false, true);
|
||||
}
|
||||
|
||||
return dialogHelper.open(dlg).then(function () {
|
||||
if (layoutManager.tv) {
|
||||
centerFocus(dlg.querySelector('.formDialogContent'), false, false);
|
||||
}
|
||||
|
||||
if (dlg.submitted) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return Promise.reject();
|
||||
});
|
||||
};
|
||||
|
||||
return PlaylistEditor;
|
||||
});
|
||||
/* eslint-enable indent */
|
||||
export default showEditor;
|
||||
|
||||
@@ -4,7 +4,6 @@ import playbackManager from 'playbackManager';
|
||||
import globalize from 'globalize';
|
||||
|
||||
export function show(options) {
|
||||
|
||||
var item = options.item;
|
||||
|
||||
var resumePositionTicks = item.UserData ? item.UserData.PlaybackPositionTicks : null;
|
||||
@@ -38,7 +37,6 @@ export function show(options) {
|
||||
|
||||
}).then(function (id) {
|
||||
switch (id) {
|
||||
|
||||
case 'play':
|
||||
playbackManager.play({
|
||||
ids: [playableItemId],
|
||||
|
||||
@@ -13,7 +13,6 @@ define(['events', 'globalize'], function (events, globalize) {
|
||||
}
|
||||
|
||||
function definePluginRoute(pluginManager, route, plugin) {
|
||||
|
||||
route.contentPath = pluginManager.mapPath(plugin, route.path);
|
||||
route.path = pluginManager.mapRoute(plugin, route);
|
||||
|
||||
@@ -21,12 +20,10 @@ define(['events', 'globalize'], function (events, globalize) {
|
||||
}
|
||||
|
||||
function PluginManager() {
|
||||
|
||||
this.pluginsList = [];
|
||||
}
|
||||
|
||||
PluginManager.prototype.loadPlugin = function(pluginSpec) {
|
||||
|
||||
var instance = this;
|
||||
|
||||
function registerPlugin(plugin) {
|
||||
@@ -39,7 +36,6 @@ define(['events', 'globalize'], function (events, globalize) {
|
||||
}
|
||||
|
||||
if (plugin.type === 'skin') {
|
||||
|
||||
// translations won't be loaded for skins until needed
|
||||
return Promise.resolve(plugin);
|
||||
} else {
|
||||
@@ -104,13 +100,11 @@ define(['events', 'globalize'], function (events, globalize) {
|
||||
// name
|
||||
// type (skin, screensaver, etc)
|
||||
PluginManager.prototype.register = function (obj) {
|
||||
|
||||
this.pluginsList.push(obj);
|
||||
events.trigger(this, 'registered', [obj]);
|
||||
};
|
||||
|
||||
PluginManager.prototype.ofType = function (type) {
|
||||
|
||||
return this.pluginsList.filter(function (o) {
|
||||
return o.type === type;
|
||||
});
|
||||
@@ -121,7 +115,6 @@ define(['events', 'globalize'], function (events, globalize) {
|
||||
};
|
||||
|
||||
PluginManager.prototype.mapRoute = function (plugin, route) {
|
||||
|
||||
if (typeof plugin === 'string') {
|
||||
plugin = this.pluginsList.filter(function (p) {
|
||||
return (p.id || p.packageName) === plugin;
|
||||
@@ -138,7 +131,6 @@ define(['events', 'globalize'], function (events, globalize) {
|
||||
};
|
||||
|
||||
PluginManager.prototype.mapPath = function (plugin, path, addCacheParam) {
|
||||
|
||||
if (typeof plugin === 'string') {
|
||||
plugin = this.pluginsList.filter(function (p) {
|
||||
return (p.id || p.packageName) === plugin;
|
||||
|
||||
@@ -1,12 +1,23 @@
|
||||
define(['browser', 'dialogHelper', 'layoutManager', 'scrollHelper', 'globalize', 'dom', 'require', 'material-icons', 'emby-button', 'paper-icon-button-light', 'emby-input', 'formDialogStyle'], function(browser, dialogHelper, layoutManager, scrollHelper, globalize, dom, require) {
|
||||
'use strict';
|
||||
import browser from 'browser';
|
||||
import dialogHelper from 'dialogHelper';
|
||||
import layoutManager from 'layoutManager';
|
||||
import scrollHelper from 'scrollHelper';
|
||||
import globalize from 'globalize';
|
||||
import dom from 'dom';
|
||||
import 'material-icons';
|
||||
import 'emby-button';
|
||||
import 'paper-icon-button-light';
|
||||
import 'emby-input';
|
||||
import 'formDialogStyle';
|
||||
|
||||
/* eslint-disable indent */
|
||||
export default (() => {
|
||||
function replaceAll(str, find, replace) {
|
||||
return str.split(find).join(replace);
|
||||
}
|
||||
|
||||
function setInputProperties(dlg, options) {
|
||||
var txtInput = dlg.querySelector('#txtInput');
|
||||
const txtInput = dlg.querySelector('#txtInput');
|
||||
|
||||
if (txtInput.label) {
|
||||
txtInput.label(options.label || '');
|
||||
@@ -17,7 +28,7 @@ define(['browser', 'dialogHelper', 'layoutManager', 'scrollHelper', 'globalize',
|
||||
}
|
||||
|
||||
function showDialog(options, template) {
|
||||
var dialogOptions = {
|
||||
const dialogOptions = {
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
};
|
||||
@@ -26,7 +37,7 @@ define(['browser', 'dialogHelper', 'layoutManager', 'scrollHelper', 'globalize',
|
||||
dialogOptions.size = 'fullscreen';
|
||||
}
|
||||
|
||||
var dlg = dialogHelper.createDialog(dialogOptions);
|
||||
const dlg = dialogHelper.createDialog(dialogOptions);
|
||||
|
||||
dlg.classList.add('formDialog');
|
||||
|
||||
@@ -39,7 +50,7 @@ define(['browser', 'dialogHelper', 'layoutManager', 'scrollHelper', 'globalize',
|
||||
dlg.classList.add('dialog-fullscreen-lowres');
|
||||
}
|
||||
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', function (e) {
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', () => {
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
|
||||
@@ -53,16 +64,15 @@ define(['browser', 'dialogHelper', 'layoutManager', 'scrollHelper', 'globalize',
|
||||
|
||||
setInputProperties(dlg, options);
|
||||
|
||||
var submitValue;
|
||||
|
||||
dlg.querySelector('form').addEventListener('submit', function (e) {
|
||||
let submitValue;
|
||||
|
||||
dlg.querySelector('form').addEventListener('submit', e => {
|
||||
submitValue = dlg.querySelector('#txtInput').value;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// Important, don't close the dialog until after the form has completed submitting, or it will cause an error in Chrome
|
||||
setTimeout(function () {
|
||||
setTimeout(() => {
|
||||
dialogHelper.close(dlg);
|
||||
}, 300);
|
||||
|
||||
@@ -71,9 +81,9 @@ define(['browser', 'dialogHelper', 'layoutManager', 'scrollHelper', 'globalize',
|
||||
|
||||
dlg.querySelector('.submitText').innerHTML = options.confirmText || globalize.translate('ButtonOk');
|
||||
|
||||
dlg.style.minWidth = (Math.min(400, dom.getWindowSize().innerWidth - 50)) + 'px';
|
||||
dlg.style.minWidth = `${Math.min(400, dom.getWindowSize().innerWidth - 50)}px`;
|
||||
|
||||
return dialogHelper.open(dlg).then(function () {
|
||||
return dialogHelper.open(dlg).then(() => {
|
||||
if (layoutManager.tv) {
|
||||
scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false);
|
||||
}
|
||||
@@ -87,7 +97,7 @@ define(['browser', 'dialogHelper', 'layoutManager', 'scrollHelper', 'globalize',
|
||||
}
|
||||
|
||||
if ((browser.tv || browser.xboxOne) && window.confirm) {
|
||||
return function (options) {
|
||||
return options => {
|
||||
if (typeof options === 'string') {
|
||||
options = {
|
||||
label: '',
|
||||
@@ -95,8 +105,8 @@ define(['browser', 'dialogHelper', 'layoutManager', 'scrollHelper', 'globalize',
|
||||
};
|
||||
}
|
||||
|
||||
var label = replaceAll(options.label || '', '<br/>', '\n');
|
||||
var result = prompt(label, options.text || '');
|
||||
const label = replaceAll(options.label || '', '<br/>', '\n');
|
||||
const result = prompt(label, options.text || '');
|
||||
|
||||
if (result) {
|
||||
return Promise.resolve(result);
|
||||
@@ -105,9 +115,9 @@ define(['browser', 'dialogHelper', 'layoutManager', 'scrollHelper', 'globalize',
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return function (options) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
require(['text!./prompt.template.html'], function (template) {
|
||||
return options => {
|
||||
return new Promise((resolve, reject) => {
|
||||
import('text!./prompt.template.html').then(({default: template}) => {
|
||||
if (typeof options === 'string') {
|
||||
options = {
|
||||
title: '',
|
||||
@@ -119,4 +129,5 @@ define(['browser', 'dialogHelper', 'layoutManager', 'scrollHelper', 'globalize',
|
||||
});
|
||||
};
|
||||
}
|
||||
});
|
||||
})();
|
||||
/* eslint-enable indent */
|
||||
|
||||
@@ -2,7 +2,6 @@ define(['globalize'], function (globalize) {
|
||||
'use strict';
|
||||
|
||||
function getVideoQualityOptions(options) {
|
||||
|
||||
var maxStreamingBitrate = options.currentMaxBitrate;
|
||||
var videoWidth = options.videoWidth;
|
||||
var videoHeight = options.videoHeight;
|
||||
@@ -14,7 +13,6 @@ define(['globalize'], function (globalize) {
|
||||
}
|
||||
|
||||
var maxAllowedWidth = videoWidth || 4096;
|
||||
//var maxAllowedHeight = videoHeight || 2304;
|
||||
|
||||
var qualityOptions = [];
|
||||
|
||||
@@ -26,7 +24,6 @@ define(['globalize'], function (globalize) {
|
||||
|
||||
// Some 1080- videos are reported as 1912?
|
||||
if (maxAllowedWidth >= 1900) {
|
||||
|
||||
qualityOptions.push({ name: '1080p - 60 Mbps', maxHeight: 1080, bitrate: 60000000 });
|
||||
qualityOptions.push({ name: '1080p - 50 Mbps', maxHeight: 1080, bitrate: 50000000 });
|
||||
qualityOptions.push({ name: '1080p - 40 Mbps', maxHeight: 1080, bitrate: 40000000 });
|
||||
@@ -39,13 +36,11 @@ define(['globalize'], function (globalize) {
|
||||
qualityOptions.push({ name: '1080p - 6 Mbps', maxHeight: 1080, bitrate: 6000001 });
|
||||
qualityOptions.push({ name: '1080p - 5 Mbps', maxHeight: 1080, bitrate: 5000001 });
|
||||
qualityOptions.push({ name: '1080p - 4 Mbps', maxHeight: 1080, bitrate: 4000002 });
|
||||
|
||||
} else if (maxAllowedWidth >= 1260) {
|
||||
qualityOptions.push({ name: '720p - 10 Mbps', maxHeight: 720, bitrate: 10000000 });
|
||||
qualityOptions.push({ name: '720p - 8 Mbps', maxHeight: 720, bitrate: 8000000 });
|
||||
qualityOptions.push({ name: '720p - 6 Mbps', maxHeight: 720, bitrate: 6000000 });
|
||||
qualityOptions.push({ name: '720p - 5 Mbps', maxHeight: 720, bitrate: 5000000 });
|
||||
|
||||
} else if (maxAllowedWidth >= 620) {
|
||||
qualityOptions.push({ name: '480p - 4 Mbps', maxHeight: 480, bitrate: 4000001 });
|
||||
qualityOptions.push({ name: '480p - 3 Mbps', maxHeight: 480, bitrate: 3000001 });
|
||||
@@ -84,7 +79,6 @@ define(['globalize'], function (globalize) {
|
||||
if (maxStreamingBitrate) {
|
||||
var selectedIndex = -1;
|
||||
for (var i = 0, length = qualityOptions.length; i < length; i++) {
|
||||
|
||||
var option = qualityOptions[i];
|
||||
|
||||
if (selectedIndex === -1 && option.bitrate <= maxStreamingBitrate) {
|
||||
@@ -93,7 +87,6 @@ define(['globalize'], function (globalize) {
|
||||
}
|
||||
|
||||
if (selectedIndex === -1) {
|
||||
|
||||
selectedIndex = qualityOptions.length - 1;
|
||||
}
|
||||
|
||||
@@ -110,7 +103,6 @@ define(['globalize'], function (globalize) {
|
||||
}
|
||||
|
||||
function getAudioQualityOptions(options) {
|
||||
|
||||
var maxStreamingBitrate = options.currentMaxBitrate;
|
||||
|
||||
var qualityOptions = [];
|
||||
@@ -138,7 +130,6 @@ define(['globalize'], function (globalize) {
|
||||
if (maxStreamingBitrate) {
|
||||
var selectedIndex = -1;
|
||||
for (var i = 0, length = qualityOptions.length; i < length; i++) {
|
||||
|
||||
var option = qualityOptions[i];
|
||||
|
||||
if (selectedIndex === -1 && option.bitrate <= maxStreamingBitrate) {
|
||||
@@ -147,7 +138,6 @@ define(['globalize'], function (globalize) {
|
||||
}
|
||||
|
||||
if (selectedIndex === -1) {
|
||||
|
||||
selectedIndex = qualityOptions.length - 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,9 @@ define(['globalize', 'connectionManager', 'require', 'loading', 'apphost', 'dom'
|
||||
'use strict';
|
||||
|
||||
function onRecordingButtonClick(e) {
|
||||
|
||||
var item = this.item;
|
||||
|
||||
if (item) {
|
||||
|
||||
var serverId = item.ServerId;
|
||||
var programId = item.Id;
|
||||
var timerId = item.TimerId;
|
||||
@@ -50,23 +48,19 @@ define(['globalize', 'connectionManager', 'require', 'loading', 'apphost', 'dom'
|
||||
}
|
||||
|
||||
function getIndicatorIcon(item) {
|
||||
|
||||
var status;
|
||||
|
||||
if (item.Type === 'SeriesTimer') {
|
||||
return 'fiber_smart_record';
|
||||
} else if (item.TimerId || item.SeriesTimerId) {
|
||||
|
||||
status = item.Status || 'Cancelled';
|
||||
} else if (item.Type === 'Timer') {
|
||||
|
||||
status = item.Status;
|
||||
} else {
|
||||
return 'fiber_manual_record';
|
||||
}
|
||||
|
||||
if (item.SeriesTimerId) {
|
||||
|
||||
if (status !== 'Cancelled') {
|
||||
return 'fiber_smart_record';
|
||||
}
|
||||
@@ -76,7 +70,6 @@ define(['globalize', 'connectionManager', 'require', 'loading', 'apphost', 'dom'
|
||||
}
|
||||
|
||||
RecordingButton.prototype.refresh = function (serverId, itemId) {
|
||||
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
var self = this;
|
||||
apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) {
|
||||
@@ -85,7 +78,6 @@ define(['globalize', 'connectionManager', 'require', 'loading', 'apphost', 'dom'
|
||||
};
|
||||
|
||||
RecordingButton.prototype.refreshItem = function (item) {
|
||||
|
||||
var options = this.options;
|
||||
var button = options.button;
|
||||
this.item = item;
|
||||
@@ -99,7 +91,6 @@ define(['globalize', 'connectionManager', 'require', 'loading', 'apphost', 'dom'
|
||||
};
|
||||
|
||||
RecordingButton.prototype.destroy = function () {
|
||||
|
||||
var options = this.options;
|
||||
|
||||
if (options) {
|
||||
|
||||
@@ -6,27 +6,22 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
var currentRecordingFields;
|
||||
|
||||
function closeDialog() {
|
||||
|
||||
dialogHelper.close(currentDialog);
|
||||
}
|
||||
|
||||
function init(context) {
|
||||
|
||||
context.querySelector('.btnPlay').addEventListener('click', function () {
|
||||
|
||||
closeAction = 'play';
|
||||
closeDialog();
|
||||
});
|
||||
|
||||
context.querySelector('.btnCancel').addEventListener('click', function () {
|
||||
|
||||
closeAction = null;
|
||||
closeDialog();
|
||||
});
|
||||
}
|
||||
|
||||
function getImageUrl(item, apiClient, imageHeight) {
|
||||
|
||||
var imageTags = item.ImageTags || {};
|
||||
|
||||
if (item.PrimaryImageTag) {
|
||||
@@ -34,14 +29,12 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
}
|
||||
|
||||
if (imageTags.Primary) {
|
||||
|
||||
return apiClient.getScaledImageUrl(item.Id, {
|
||||
type: 'Primary',
|
||||
maxHeight: imageHeight,
|
||||
tag: item.ImageTags.Primary
|
||||
});
|
||||
} else if (imageTags.Thumb) {
|
||||
|
||||
return apiClient.getScaledImageUrl(item.Id, {
|
||||
type: 'Thumb',
|
||||
maxHeight: imageHeight,
|
||||
@@ -53,7 +46,6 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
}
|
||||
|
||||
function renderRecording(context, defaultTimer, program, apiClient, refreshRecordingStateOnly) {
|
||||
|
||||
if (!refreshRecordingStateOnly) {
|
||||
var imgUrl = getImageUrl(program, apiClient, 200);
|
||||
var imageContainer = context.querySelector('.recordingDialog-imageContainer');
|
||||
@@ -91,7 +83,6 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
}
|
||||
|
||||
function reload(context, programId, serverId, refreshRecordingStateOnly) {
|
||||
|
||||
loading.show();
|
||||
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
@@ -100,7 +91,6 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
var promise2 = apiClient.getLiveTvProgram(programId, apiClient.getCurrentUserId());
|
||||
|
||||
Promise.all([promise1, promise2]).then(function (responses) {
|
||||
|
||||
var defaults = responses[0];
|
||||
var program = responses[1];
|
||||
|
||||
@@ -109,15 +99,11 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
}
|
||||
|
||||
function executeCloseAction(action, programId, serverId) {
|
||||
|
||||
if (action === 'play') {
|
||||
|
||||
require(['playbackManager'], function (playbackManager) {
|
||||
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
|
||||
apiClient.getLiveTvProgram(programId, apiClient.getCurrentUserId()).then(function (item) {
|
||||
|
||||
playbackManager.play({
|
||||
ids: [item.ChannelId],
|
||||
serverId: serverId
|
||||
@@ -129,15 +115,12 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
}
|
||||
|
||||
function showEditor(itemId, serverId) {
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
closeAction = null;
|
||||
|
||||
loading.show();
|
||||
|
||||
require(['text!./recordingcreator.template.html'], function (template) {
|
||||
|
||||
var dialogOptions = {
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
@@ -156,7 +139,7 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
|
||||
var html = '';
|
||||
|
||||
html += globalize.translateDocument(template, 'core');
|
||||
html += globalize.translateHtml(template, 'core');
|
||||
|
||||
dlg.innerHTML = html;
|
||||
|
||||
@@ -167,7 +150,6 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
}
|
||||
|
||||
dlg.addEventListener('close', function () {
|
||||
|
||||
events.off(currentRecordingFields, 'recordingchanged', onRecordingChanged);
|
||||
executeCloseAction(closeAction, itemId, serverId);
|
||||
|
||||
|
||||
@@ -8,20 +8,14 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
var currentResolve;
|
||||
|
||||
function deleteTimer(apiClient, timerId) {
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
require(['recordingHelper'], function (recordingHelper) {
|
||||
|
||||
recordingHelper.cancelTimerWithConfirmation(timerId, apiClient.serverId()).then(resolve, reject);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function renderTimer(context, item, apiClient) {
|
||||
|
||||
var program = item.ProgramInfo || {};
|
||||
|
||||
context.querySelector('#txtPrePaddingMinutes').value = item.PrePaddingSeconds / 60;
|
||||
context.querySelector('#txtPostPaddingMinutes').value = item.PostPaddingSeconds / 60;
|
||||
|
||||
@@ -29,14 +23,12 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
}
|
||||
|
||||
function closeDialog(isDeleted) {
|
||||
|
||||
recordingDeleted = isDeleted;
|
||||
|
||||
dialogHelper.close(currentDialog);
|
||||
}
|
||||
|
||||
function onSubmit(e) {
|
||||
|
||||
var form = this;
|
||||
|
||||
var apiClient = connectionManager.getApiClient(currentServerId);
|
||||
@@ -54,14 +46,11 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
}
|
||||
|
||||
function init(context) {
|
||||
|
||||
context.querySelector('.btnCancel').addEventListener('click', function () {
|
||||
|
||||
closeDialog(false);
|
||||
});
|
||||
|
||||
context.querySelector('.btnCancelRecording').addEventListener('click', function () {
|
||||
|
||||
var apiClient = connectionManager.getApiClient(currentServerId);
|
||||
deleteTimer(apiClient, currentItemId).then(function () {
|
||||
closeDialog(true);
|
||||
@@ -72,22 +61,18 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
}
|
||||
|
||||
function reload(context, id) {
|
||||
|
||||
loading.show();
|
||||
currentItemId = id;
|
||||
|
||||
var apiClient = connectionManager.getApiClient(currentServerId);
|
||||
apiClient.getLiveTvTimer(id).then(function (result) {
|
||||
|
||||
renderTimer(context, result, apiClient);
|
||||
loading.hide();
|
||||
});
|
||||
}
|
||||
|
||||
function showEditor(itemId, serverId, options) {
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
recordingDeleted = false;
|
||||
currentServerId = serverId;
|
||||
loading.show();
|
||||
@@ -116,7 +101,7 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
|
||||
var html = '';
|
||||
|
||||
html += globalize.translateDocument(template, 'core');
|
||||
html += globalize.translateHtml(template, 'core');
|
||||
|
||||
dlg.innerHTML = html;
|
||||
|
||||
@@ -127,14 +112,12 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
currentDialog = dlg;
|
||||
|
||||
dlg.addEventListener('closing', function () {
|
||||
|
||||
if (!recordingDeleted) {
|
||||
dlg.querySelector('.btnSubmit').click();
|
||||
}
|
||||
});
|
||||
|
||||
dlg.addEventListener('close', function () {
|
||||
|
||||
if (recordingDeleted) {
|
||||
resolve({
|
||||
updated: true,
|
||||
|
||||
@@ -34,7 +34,6 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa
|
||||
}
|
||||
|
||||
function fetchData(instance) {
|
||||
|
||||
var options = instance.options;
|
||||
var apiClient = connectionManager.getApiClient(options.serverId);
|
||||
|
||||
@@ -121,7 +120,6 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa
|
||||
}
|
||||
|
||||
function onManageSeriesRecordingClick(e) {
|
||||
|
||||
var options = this.options;
|
||||
|
||||
if (!this.SeriesTimerId) {
|
||||
@@ -131,7 +129,6 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa
|
||||
var self = this;
|
||||
|
||||
require(['seriesRecordingEditor'], function (seriesRecordingEditor) {
|
||||
|
||||
seriesRecordingEditor.show(self.SeriesTimerId, options.serverId, {
|
||||
|
||||
enableCancel: false
|
||||
@@ -143,7 +140,6 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa
|
||||
}
|
||||
|
||||
function onRecordChange(e) {
|
||||
|
||||
this.changed = true;
|
||||
|
||||
var self = this;
|
||||
@@ -183,7 +179,6 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa
|
||||
}
|
||||
|
||||
function onRecordSeriesChange(e) {
|
||||
|
||||
this.changed = true;
|
||||
|
||||
var self = this;
|
||||
@@ -219,7 +214,7 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa
|
||||
require(['text!./recordingfields.template.html'], function (template) {
|
||||
var options = self.options;
|
||||
var context = options.parent;
|
||||
context.innerHTML = globalize.translateDocument(template, 'core');
|
||||
context.innerHTML = globalize.translateHtml(template, 'core');
|
||||
|
||||
context.querySelector('.singleRecordingButton').addEventListener('click', onRecordChange.bind(self));
|
||||
context.querySelector('.seriesRecordingButton').addEventListener('click', onRecordSeriesChange.bind(self));
|
||||
|
||||
@@ -2,17 +2,13 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
|
||||
'use strict';
|
||||
|
||||
function changeRecordingToSeries(apiClient, timerId, programId, confirmTimerCancellation) {
|
||||
|
||||
loading.show();
|
||||
|
||||
return apiClient.getItem(apiClient.getCurrentUserId(), programId).then(function (item) {
|
||||
|
||||
if (item.IsSeries) {
|
||||
// create series
|
||||
return apiClient.getNewLiveTvTimerDefaults({ programId: programId }).then(function (timerDefaults) {
|
||||
|
||||
return apiClient.createLiveTvSeriesTimer(timerDefaults).then(function () {
|
||||
|
||||
loading.hide();
|
||||
sendToast(globalize.translate('SeriesRecordingScheduled'));
|
||||
});
|
||||
@@ -29,12 +25,9 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
|
||||
}
|
||||
|
||||
function cancelTimerWithConfirmation(timerId, serverId) {
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
require(['confirm'], function (confirm) {
|
||||
|
||||
confirm({
|
||||
confirm.default({
|
||||
|
||||
text: globalize.translate('MessageConfirmRecordingCancellation'),
|
||||
primary: 'delete',
|
||||
@@ -42,24 +35,19 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
|
||||
cancelText: globalize.translate('HeaderKeepRecording')
|
||||
|
||||
}).then(function () {
|
||||
|
||||
loading.show();
|
||||
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
cancelTimer(apiClient, timerId, true).then(resolve, reject);
|
||||
|
||||
}, reject);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function cancelSeriesTimerWithConfirmation(timerId, serverId) {
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
require(['confirm'], function (confirm) {
|
||||
|
||||
confirm({
|
||||
confirm.default({
|
||||
|
||||
text: globalize.translate('MessageConfirmRecordingCancellation'),
|
||||
primary: 'delete',
|
||||
@@ -67,12 +55,10 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
|
||||
cancelText: globalize.translate('HeaderKeepSeries')
|
||||
|
||||
}).then(function () {
|
||||
|
||||
loading.show();
|
||||
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
apiClient.cancelLiveTvSeriesTimer(timerId).then(function () {
|
||||
|
||||
require(['toast'], function (toast) {
|
||||
toast(globalize.translate('SeriesCancelled'));
|
||||
});
|
||||
@@ -80,7 +66,6 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
|
||||
loading.hide();
|
||||
resolve();
|
||||
}, reject);
|
||||
|
||||
}, reject);
|
||||
});
|
||||
});
|
||||
@@ -89,7 +74,6 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
|
||||
function cancelTimer(apiClient, timerId, hideLoading) {
|
||||
loading.show();
|
||||
return apiClient.cancelLiveTvTimer(timerId).then(function () {
|
||||
|
||||
if (hideLoading !== false) {
|
||||
loading.hide();
|
||||
sendToast(globalize.translate('RecordingCancelled'));
|
||||
@@ -98,16 +82,13 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
|
||||
}
|
||||
|
||||
function createRecording(apiClient, programId, isSeries) {
|
||||
|
||||
loading.show();
|
||||
return apiClient.getNewLiveTvTimerDefaults({ programId: programId }).then(function (item) {
|
||||
|
||||
var promise = isSeries ?
|
||||
apiClient.createLiveTvSeriesTimer(item) :
|
||||
apiClient.createLiveTvTimer(item);
|
||||
|
||||
return promise.then(function () {
|
||||
|
||||
loading.hide();
|
||||
sendToast(globalize.translate('RecordingScheduled'));
|
||||
});
|
||||
@@ -122,9 +103,7 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
|
||||
|
||||
function showMultiCancellationPrompt(serverId, programId, timerId, timerStatus, seriesTimerId) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
require(['dialog'], function (dialog) {
|
||||
|
||||
var items = [];
|
||||
|
||||
items.push({
|
||||
@@ -159,7 +138,6 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
|
||||
buttons: items
|
||||
|
||||
}).then(function (result) {
|
||||
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
|
||||
if (result === 'canceltimer') {
|
||||
@@ -167,11 +145,9 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
|
||||
|
||||
cancelTimer(apiClient, timerId, true).then(resolve, reject);
|
||||
} else if (result === 'cancelseriestimer') {
|
||||
|
||||
loading.show();
|
||||
|
||||
apiClient.cancelLiveTvSeriesTimer(seriesTimerId).then(function () {
|
||||
|
||||
require(['toast'], function (toast) {
|
||||
toast(globalize.translate('SeriesCancelled'));
|
||||
});
|
||||
@@ -182,7 +158,6 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
|
||||
}, reject);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,20 +8,14 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
var currentServerId;
|
||||
|
||||
function deleteTimer(apiClient, timerId) {
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
require(['recordingHelper'], function (recordingHelper) {
|
||||
|
||||
recordingHelper.cancelSeriesTimerWithConfirmation(timerId, apiClient.serverId()).then(resolve, reject);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function renderTimer(context, item, apiClient) {
|
||||
|
||||
var program = item.ProgramInfo || {};
|
||||
|
||||
context.querySelector('#txtPrePaddingMinutes').value = item.PrePaddingSeconds / 60;
|
||||
context.querySelector('#txtPostPaddingMinutes').value = item.PostPaddingSeconds / 60;
|
||||
|
||||
@@ -44,7 +38,6 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
}
|
||||
|
||||
function closeDialog(isDeleted) {
|
||||
|
||||
recordingUpdated = true;
|
||||
recordingDeleted = isDeleted;
|
||||
|
||||
@@ -52,13 +45,11 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
}
|
||||
|
||||
function onSubmit(e) {
|
||||
|
||||
var form = this;
|
||||
|
||||
var apiClient = connectionManager.getApiClient(currentServerId);
|
||||
|
||||
apiClient.getLiveTvSeriesTimer(currentItemId).then(function (item) {
|
||||
|
||||
item.PrePaddingSeconds = form.querySelector('#txtPrePaddingMinutes').value * 60;
|
||||
item.PostPaddingSeconds = form.querySelector('#txtPostPaddingMinutes').value * 60;
|
||||
item.RecordAnyChannel = form.querySelector('.selectChannels').value === 'all';
|
||||
@@ -77,16 +68,13 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
}
|
||||
|
||||
function init(context) {
|
||||
|
||||
fillKeepUpTo(context);
|
||||
|
||||
context.querySelector('.btnCancel').addEventListener('click', function () {
|
||||
|
||||
closeDialog(false);
|
||||
});
|
||||
|
||||
context.querySelector('.btnCancelRecording').addEventListener('click', function () {
|
||||
|
||||
var apiClient = connectionManager.getApiClient(currentServerId);
|
||||
deleteTimer(apiClient, currentItemId).then(function () {
|
||||
closeDialog(true);
|
||||
@@ -97,7 +85,6 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
}
|
||||
|
||||
function reload(context, id) {
|
||||
|
||||
var apiClient = connectionManager.getApiClient(currentServerId);
|
||||
|
||||
loading.show();
|
||||
@@ -105,12 +92,10 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
currentItemId = id;
|
||||
|
||||
apiClient.getLiveTvSeriesTimer(id).then(function (result) {
|
||||
|
||||
renderTimer(context, result, apiClient);
|
||||
loading.hide();
|
||||
});
|
||||
} else if (id) {
|
||||
|
||||
currentItemId = id.Id;
|
||||
|
||||
renderTimer(context, id, apiClient);
|
||||
@@ -119,11 +104,9 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
}
|
||||
|
||||
function fillKeepUpTo(context) {
|
||||
|
||||
var html = '';
|
||||
|
||||
for (var i = 0; i <= 50; i++) {
|
||||
|
||||
var text;
|
||||
|
||||
if (i === 0) {
|
||||
@@ -145,7 +128,6 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
}
|
||||
|
||||
function embed(itemId, serverId, options) {
|
||||
|
||||
recordingUpdated = false;
|
||||
recordingDeleted = false;
|
||||
currentServerId = serverId;
|
||||
@@ -153,7 +135,6 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
options = options || {};
|
||||
|
||||
require(['text!./seriesrecordingeditor.template.html'], function (template) {
|
||||
|
||||
var dialogOptions = {
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
@@ -168,7 +149,7 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
var dlg = options.context;
|
||||
|
||||
dlg.classList.add('hide');
|
||||
dlg.innerHTML = globalize.translateDocument(template, 'core');
|
||||
dlg.innerHTML = globalize.translateHtml(template, 'core');
|
||||
|
||||
dlg.querySelector('.formDialogHeader').classList.add('hide');
|
||||
dlg.querySelector('.formDialogFooter').classList.add('hide');
|
||||
@@ -188,9 +169,7 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
}
|
||||
|
||||
function showEditor(itemId, serverId, options) {
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
recordingUpdated = false;
|
||||
recordingDeleted = false;
|
||||
currentServerId = serverId;
|
||||
@@ -198,7 +177,6 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
options = options || {};
|
||||
|
||||
require(['text!./seriesrecordingeditor.template.html'], function (template) {
|
||||
|
||||
var dialogOptions = {
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
@@ -221,7 +199,7 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
|
||||
var html = '';
|
||||
|
||||
html += globalize.translateDocument(template, 'core');
|
||||
html += globalize.translateHtml(template, 'core');
|
||||
|
||||
dlg.innerHTML = html;
|
||||
|
||||
@@ -232,14 +210,12 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
|
||||
currentDialog = dlg;
|
||||
|
||||
dlg.addEventListener('closing', function () {
|
||||
|
||||
if (!recordingDeleted) {
|
||||
this.querySelector('.btnSubmit').click();
|
||||
}
|
||||
});
|
||||
|
||||
dlg.addEventListener('close', function () {
|
||||
|
||||
if (recordingUpdated) {
|
||||
resolve({
|
||||
updated: true,
|
||||
|
||||
@@ -2,7 +2,6 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'connectionM
|
||||
'use strict';
|
||||
|
||||
function getEditorHtml() {
|
||||
|
||||
var html = '';
|
||||
|
||||
html += '<div class="formDialogContent smoothScrollY" style="padding-top:2em;">';
|
||||
@@ -48,7 +47,6 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'connectionM
|
||||
}
|
||||
|
||||
function onSubmit(e) {
|
||||
|
||||
loading.show();
|
||||
|
||||
var instance = this;
|
||||
@@ -90,7 +88,6 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'connectionM
|
||||
}
|
||||
|
||||
RefreshDialog.prototype.show = function () {
|
||||
|
||||
var dialogOptions = {
|
||||
removeOnClose: true,
|
||||
scrollY: false
|
||||
@@ -124,7 +121,6 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'connectionM
|
||||
dlg.querySelector('form').addEventListener('submit', onSubmit.bind(this));
|
||||
|
||||
dlg.querySelector('#selectMetadataRefreshMode').addEventListener('change', function () {
|
||||
|
||||
if (this.value === 'scan') {
|
||||
dlg.querySelector('.fldReplaceExistingImages').classList.add('hide');
|
||||
} else {
|
||||
@@ -139,7 +135,6 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'connectionM
|
||||
dlg.querySelector('#selectMetadataRefreshMode').dispatchEvent(new CustomEvent('change'));
|
||||
|
||||
dlg.querySelector('.btnCancel').addEventListener('click', function () {
|
||||
|
||||
dialogHelper.close(dlg);
|
||||
});
|
||||
|
||||
@@ -148,7 +143,6 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'connectionM
|
||||
}
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
if (layoutManager.tv) {
|
||||
centerFocus(dlg.querySelector('.formDialogContent'), false, false);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user