1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

Merge remote-tracking branch 'upstream/master' into more-es6

This commit is contained in:
MrTimscampi 2020-08-06 22:39:11 +02:00
commit 936ff4186d
310 changed files with 9162 additions and 13374 deletions

View file

@ -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'

View file

@ -8,5 +8,5 @@ trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf
[json]
[*.json]
indent_size = 2

View file

@ -1,6 +1,7 @@
module.exports = {
root: true,
plugins: [
'@babel',
'promise',
'import',
'eslint-comments'
@ -28,7 +29,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,18 +40,22 @@ 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'],
'space-infix-ops': 'error'
'space-infix-ops': 'error',
'yoda': 'error'
},
overrides: [
{
files: [
'./src/**/*.js'
],
parser: 'babel-eslint',
parser: '@babel/eslint-parser',
env: {
node: false,
amd: true,
@ -98,9 +103,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']
},

View file

@ -35,7 +35,9 @@
- [Thibault Nocchi](https://github.com/ThibaultNocchi)
- [MrTimscampi](https://github.com/MrTimscampi)
- [Sarab Singh](https://github.com/sarab97)
- [GuilhermeHideki](https://github.com/GuilhermeHideki)
- [Andrei Oanca](https://github.com/OancaAndrei)
- [Cromefire_](https://github.com/cromefire)
# Emby Contributors

View file

@ -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

View file

@ -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

View file

@ -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

6
debian/changelog vendored
View file

@ -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

View file

@ -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

View file

@ -5,21 +5,22 @@
"repository": "https://github.com/jellyfin/jellyfin-web",
"license": "GPL-2.0-or-later",
"devDependencies": {
"@babel/core": "^7.10.5",
"@babel/core": "^7.11.1",
"@babel/eslint-parser": "^7.11.0",
"@babel/eslint-plugin": "^7.11.0",
"@babel/plugin-proposal-class-properties": "^7.10.1",
"@babel/plugin-proposal-private-methods": "^7.10.1",
"@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/preset-env": "^7.11.0",
"autoprefixer": "^9.8.6",
"babel-loader": "^8.0.6",
"browser-sync": "^2.26.10",
"browser-sync": "^2.26.12",
"copy-webpack-plugin": "^5.1.1",
"css-loader": "^4.0.0",
"css-loader": "^4.2.0",
"cssnano": "^4.1.10",
"del": "^5.1.0",
"eslint": "^6.8.0",
"eslint": "^7.6.0",
"eslint-plugin-compat": "^3.5.1",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-import": "^2.21.2",
@ -37,7 +38,7 @@
"gulp-postcss": "^8.0.0",
"gulp-sass": "^4.0.2",
"gulp-sourcemaps": "^2.6.5",
"gulp-terser": "^1.2.1",
"gulp-terser": "^1.3.2",
"html-webpack-plugin": "^4.3.0",
"lazypipe": "^1.0.2",
"node-sass": "^4.13.1",
@ -48,7 +49,7 @@
"stylelint-config-rational-order": "^0.1.2",
"stylelint-no-browser-hacks": "^1.2.1",
"stylelint-order": "^4.1.0",
"webpack": "^4.44.0",
"webpack": "^4.44.1",
"webpack-merge": "^4.2.2",
"webpack-stream": "^5.2.1"
},
@ -62,7 +63,7 @@
"fast-text-encoding": "^1.0.3",
"flv.js": "^1.5.0",
"headroom.js": "^0.11.0",
"hls.js": "^0.14.5",
"hls.js": "^0.14.7",
"howler": "^2.2.0",
"intersection-observer": "^0.11.0",
"jellyfin-apiclient": "^1.4.1",
@ -76,11 +77,10 @@
"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",
"whatwg-fetch": "^3.2.0"
"whatwg-fetch": "^3.3.1"
},
"babel": {
"presets": [
@ -107,22 +107,28 @@
"src/components/dialogHelper/dialogHelper.js",
"src/components/directorybrowser/directorybrowser.js",
"src/components/displaySettings/displaySettings.js",
"src/components/favoriteitems.js",
"src/components/fetchhelper.js",
"src/components/filterdialog/filterdialog.js",
"src/components/focusManager.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/itemHelper.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/loading/loading.js",
"src/components/maintabsmanager.js",
"src/components/mediainfo/mediainfo.js",
"src/components/mediaLibraryCreator/mediaLibraryCreator.js",
@ -135,9 +141,11 @@
"src/components/playback/mediasession.js",
"src/components/playback/nowplayinghelper.js",
"src/components/playback/playbackorientation.js",
"src/components/playback/playbackmanager.js",
"src/components/playback/playerSelectionMenu.js",
"src/components/playback/playersettingsmenu.js",
"src/components/playback/playmethodhelper.js",
"src/components/playback/playqueuemanager.js",
"src/components/playback/remotecontrolautoplay.js",
"src/components/playback/volumeosd.js",
"src/components/playbackSettings/playbackSettings.js",
@ -145,8 +153,12 @@
"src/components/playlisteditor/playlisteditor.js",
"src/components/playmenu.js",
"src/components/prompt/prompt.js",
"src/components/recordingcreator/seriesrecordingeditor.js",
"src/components/recordingcreator/recordinghelper.js",
"src/components/refreshdialog/refreshdialog.js",
"src/components/sanatizefilename.js",
"src/components/scrollManager.js",
"src/plugins/htmlVideoPlayer/plugin.js",
"src/components/search/searchfields.js",
"src/components/search/searchresults.js",
"src/components/settingshelper.js",
@ -157,11 +169,17 @@
"src/components/syncPlay/playbackPermissionManager.js",
"src/components/syncPlay/syncPlayManager.js",
"src/components/syncPlay/timeSyncManager.js",
"src/components/tvproviders/schedulesdirect.js",
"src/components/tvproviders/xmltv.js",
"src/components/toast/toast.js",
"src/components/upnextdialog/upnextdialog.js",
"src/components/viewContainer.js",
"src/components/castSenderApi.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/sessopm/selectServer/index.js",
"src/controllers/session/selectServer/index.js",
"src/controllers/dashboard/apikeys.js",
"src/controllers/dashboard/dashboard.js",
"src/controllers/dashboard/devices/device.js",
@ -173,10 +191,18 @@
"src/controllers/dashboard/general.js",
"src/controllers/dashboard/librarydisplay.js",
"src/controllers/dashboard/logs.js",
"src/controllers/music/musicalbums.js",
"src/controllers/music/musicartists.js",
"src/controllers/music/musicgenres.js",
"src/controllers/music/musicplaylists.js",
"src/controllers/music/musicrecommended.js",
"src/controllers/music/songs.js",
"src/controllers/dashboard/mediaLibrary.js",
"src/controllers/dashboard/metadataImages.js",
"src/controllers/dashboard/metadatanfo.js",
"src/controllers/dashboard/networking.js",
"src/controllers/dashboard/notifications/notification.js",
"src/controllers/dashboard/notifications/notifications.js",
"src/controllers/dashboard/playback.js",
"src/controllers/dashboard/plugins/repositories/index.js",
"src/controllers/dashboard/scheduledtasks/scheduledtask.js",
@ -189,9 +215,28 @@
"src/controllers/dashboard/users/userparentalcontrol.js",
"src/controllers/dashboard/users/userpasswordpage.js",
"src/controllers/dashboard/users/userprofilespage.js",
"src/controllers/edititemmetadata.js",
"src/controllers/favorites.js",
"src/controllers/hometab.js",
"src/controllers/movies/moviecollections.js",
"src/controllers/movies/moviegenres.js",
"src/controllers/movies/movies.js",
"src/controllers/movies/moviesrecommended.js",
"src/controllers/movies/movietrailers.js",
"src/controllers/playback/nowplaying.js",
"src/controllers/playback/videoosd.js",
"src/controllers/itemDetails/index.js",
"src/controllers/playback/queue/index.js",
"src/controllers/playback/video/index.js",
"src/controllers/searchpage.js",
"src/controllers/livetvtuner.js",
"src/controllers/livetvstatus.js",
"src/controllers/livetvguideprovider.js",
"src/controllers/livetvsettings.js",
"src/controllers/livetv/livetvrecordings.js",
"src/controllers/livetv/livetvschedule.js",
"src/controllers/livetv/livetvseriestimers.js",
"src/controllers/livetv/livetvchannels.js",
"src/controllers/shows/episodes.js",
"src/controllers/shows/tvgenres.js",
"src/controllers/shows/tvlatest.js",
@ -205,7 +250,6 @@
"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",
@ -238,6 +282,7 @@
"src/plugins/youtubePlayer/plugin.js",
"src/scripts/alphanumericshortcuts.js",
"src/scripts/autoBackdrops.js",
"src/scripts/browser.js",
"src/scripts/datetime.js",
"src/scripts/deleteHelper.js",
"src/scripts/dfnshelper.js",
@ -248,10 +293,16 @@
"src/scripts/globalize.js",
"src/scripts/imagehelper.js",
"src/scripts/inputManager.js",
"src/scripts/autoThemes.js",
"src/scripts/themeManager.js",
"src/scripts/keyboardNavigation.js",
"src/scripts/libraryBrowser.js",
"src/scripts/mouseManager.js",
"src/scripts/multiDownload.js",
"src/scripts/playlists.js",
"src/scripts/scrollHelper.js",
"src/scripts/serverNotifications.js",
"src/scripts/routes.js",
"src/scripts/settings/appSettings.js",
"src/scripts/settings/userSettings.js",
"src/scripts/settings/webSettings.js",
@ -273,7 +324,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",
@ -281,9 +332,11 @@
"Chrome 53",
"Chrome 56",
"Chrome 63",
"Edge 18",
"Firefox ESR"
],
"scripts": {
"start": "yarn serve",
"serve": "gulp serve --development",
"prepare": "gulp --production",
"build:development": "gulp --development",

33
scripts/duplicates.py Normal file
View file

@ -0,0 +1,33 @@
import sys
import os
import json
# load every string in the source language
# print all duplicate values to a file
cwd = os.getcwd()
source = cwd + '/../src/strings/en-us.json'
reverse = {}
duplicates = {}
with open(source) as en:
strings = json.load(en)
for key, value in strings.items():
if value not in reverse:
reverse[value] = [key]
else:
reverse[value].append(key)
for key, value in reverse.items():
if len(value) > 1:
duplicates[key] = value
print('LENGTH: ' + str(len(duplicates)))
with open('duplicates.txt', 'w') as out:
for item in duplicates:
out.write(json.dumps(item) + ': ')
out.write(json.dumps(duplicates[item]) + '\n')
out.close()
print('DONE')

View file

@ -11,7 +11,7 @@ langlst = os.listdir(langdir)
keys = []
with open('scout.txt', 'r') as f:
with open('unused.txt', 'r') as f:
for line in f:
keys.append(line.strip('\n'))

View file

@ -640,7 +640,7 @@
.layout-desktop .detailRibbon,
.layout-tv .detailRibbon {
margin-top: -7.2em;
height: 7.18em;
height: 7.2em;
}
.layout-desktop .noBackdrop .detailRibbon,

View file

@ -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

View file

@ -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() {

View file

@ -49,7 +49,7 @@ import 'formDialogStyle';
};
if (parseFloat(updatedSchedule.StartHour) >= parseFloat(updatedSchedule.EndHour)) {
return void alert(globalize.translate('ErrorMessageStartHourGreaterThanEnd'));
return void alert(globalize.translate('ErrorStartHourGreaterThanEnd'));
}
context.submitted = true;

View file

@ -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;
@ -80,7 +78,6 @@ function centerFocus(elem, horiz, on) {
}
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);
}

View file

@ -3,7 +3,6 @@ import globalize from 'globalize';
import dom from 'dom';
import * as datefns from 'date-fns';
import dfnshelper from 'dfnshelper';
import userSettings from 'userSettings';
import serverNotifications from 'serverNotifications';
import connectionManager from 'connectionManager';
import 'emby-button';
@ -17,7 +16,7 @@ import 'listViewStyle';
let color = '#00a4dc';
let icon = 'notifications';
if ('Error' == entry.Severity || 'Fatal' == entry.Severity || 'Warn' == entry.Severity) {
if (entry.Severity == 'Error' || entry.Severity == 'Fatal' || entry.Severity == 'Warn') {
color = '#cc0000';
icon = 'notification_important';
}
@ -61,14 +60,15 @@ import 'listViewStyle';
}
function reloadData(instance, elem, apiClient, startIndex, limit) {
if (null == startIndex) {
if (startIndex == null) {
startIndex = parseInt(elem.getAttribute('data-activitystartindex') || '0');
}
limit = limit || parseInt(elem.getAttribute('data-activitylimit') || '7');
const minDate = new Date();
const hasUserId = 'false' !== elem.getAttribute('data-useractivity');
const hasUserId = elem.getAttribute('data-useractivity') !== 'false';
// TODO: Use date-fns
if (hasUserId) {
minDate.setTime(minDate.getTime() - 24 * 60 * 60 * 1000); // one day back
} else {

View file

@ -10,7 +10,6 @@ import globalize from 'globalize';
}
export default function (text, title) {
let options;
if (typeof text === 'string') {
options = {

View file

@ -26,7 +26,6 @@ import 'material-icons';
}
function getAlphaPickerButtonClassName(vertical) {
let alphaPickerButtonClassName = 'alphaPickerButton';
if (layoutManager.tv) {
@ -45,14 +44,12 @@ import 'material-icons';
}
function mapLetters(letters, vertical) {
return letters.map(l => {
return getLetterButton(l, vertical);
});
}
function render(element, options) {
element.classList.add('alphaPicker');
if (layoutManager.tv) {
@ -137,7 +134,6 @@ import 'material-icons';
}
function onAlphaPickerInKeyboardModeClick(e) {
const alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton');
if (alphaPickerButton) {
@ -153,7 +149,6 @@ import 'material-icons';
}
function onAlphaPickerClick(e) {
const alphaPickerButton = dom.parentWithClass(e.target, 'alphaPickerButton');
if (alphaPickerButton) {
@ -167,7 +162,6 @@ import 'material-icons';
}
function onAlphaPickerFocusIn(e) {
if (alphaFocusTimeout) {
clearTimeout(alphaFocusTimeout);
alphaFocusTimeout = null;
@ -182,13 +176,11 @@ import 'material-icons';
}
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);
@ -199,9 +191,7 @@ import 'material-icons';
}
this.enabled = function (enabled) {
if (enabled) {
if (itemsContainer) {
itemsContainer.addEventListener('focus', onItemsFocusIn, true);
}
@ -215,9 +205,7 @@ import 'material-icons';
} else {
element.addEventListener('click', onAlphaPickerClick.bind(this));
}
} else {
if (itemsContainer) {
itemsContainer.removeEventListener('focus', onItemsFocusIn, true);
}
@ -235,14 +223,12 @@ import 'material-icons';
}
value(value, applyValue) {
const element = this.options.element;
let btn;
let selected;
if (value !== undefined) {
if (value != null) {
value = value.toUpperCase();
this._currentValue = value;
@ -295,33 +281,27 @@ import 'material-icons';
}
visible(visible) {
const element = this.options.element;
element.style.visibility = visible ? 'visible' : 'hidden';
}
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'));
}
return values;
}
focus() {
const element = this.options.element;
focusManager.autoFocus(element, true);
}
destroy() {
const element = this.options.element;
this.enabled(false);
element.classList.remove('focuscontainer-x');

View file

@ -1,4 +1,3 @@
import browser from 'browser';
import 'css!./appFooter';
function render(options) {

View file

@ -1,6 +1,9 @@
define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdrop', 'browser', 'page', 'appSettings', 'apphost', 'connectionManager'], function (loading, globalize, events, viewManager, skinManager, backdrop, browser, page, appSettings, appHost, connectionManager) {
'use strict';
browser = browser.default || browser;
loading = loading.default || loading;
var appRouter = {
showLocalLogin: function (serverId, manualLogin) {
var pageName = manualLogin ? 'manuallogin' : 'login';
@ -34,7 +37,7 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
switch (result.State) {
case 'SignedIn':
loading.hide();
skinManager.loadUserSkin();
Emby.Page.goHome();
break;
case 'ServerSignIn':
result.ApiClient.getPublicUsers().then(function (users) {
@ -147,26 +150,19 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
if (typeof route.path === 'string') {
loadContentUrl(ctx, next, route, currentRequest);
} else {
// ? TODO
next();
}
};
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 +193,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 +204,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
showForcedLogoutMessage(globalize.translate('AccessRestrictedTryAgainLater'));
appRouter.showLocalLogin(apiClient.serverId());
}
}
}
}
@ -237,12 +230,10 @@ 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;
max = parseInt(max);
return max;
return parseInt(max, 10);
}
}
/* eslint-enable compat/compat */
@ -255,7 +246,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
}
function onApiClientCreated(e, newApiClient) {
newApiClient.normalizeImageOptions = normalizeImageOptions;
if (browser.iOS) {
@ -269,12 +259,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 +278,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
var firstConnectionResult;
function start(options) {
loading.show();
initApiClients();
@ -300,55 +287,28 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
connectionManager.connect({
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,19 +337,15 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
}
if (apiClient && apiClient.isLoggedIn()) {
console.debug('appRouter - user is authenticated');
if (route.isDefaultRoute) {
console.debug('appRouter - loading skin home page');
loadUserSkinWithOptions(ctx);
Emby.Page.goHome();
return;
} else if (route.roles) {
validateRoles(apiClient, route.roles).then(function () {
callback();
}, beginConnectionWizard);
return;
}
@ -399,15 +355,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
callback();
}
function loadUserSkinWithOptions(ctx) {
require(['queryString'], function (queryString) {
var params = queryString.parse(ctx.querystring);
skinManager.loadUserSkin({
start: params.start
});
});
}
function validateRoles(apiClient, roles) {
return Promise.all(roles.split(',').map(function (role) {
return validateRole(apiClient, role);
@ -431,7 +378,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
var isDummyBackToHome;
function loadContent(ctx, route, html, request) {
html = globalize.translateHtml(html, route.dictionary);
request.view = html;
@ -491,7 +437,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
}
function getWindowLocationSearch(win) {
var currentPath = currentRouteInfo ? (currentRouteInfo.path || '') : '';
var index = currentPath.indexOf('?');
@ -535,9 +480,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;
}
@ -644,7 +587,6 @@ define(['loading', 'globalize', 'events', 'viewManager', 'skinManager', 'backdro
function pushState(state, title, url) {
state.navigate = false;
history.pushState(state, title, url);
}
function setBaseRoute() {

View file

@ -1,6 +1,8 @@
define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'globalize'], function (appSettings, browser, events, htmlMediaHelper, webSettings, globalize) {
'use strict';
browser = browser.default || browser;
function getBaseProfileOptions(item) {
var disableHlsVideoAudioCodecs = [];
@ -47,7 +49,7 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
profile = window.NativeShell.AppHost.getDeviceProfile(profileBuilder);
} else {
var builderOpts = getBaseProfileOptions(item);
builderOpts.enableSsaRender = (item && !options.isRetry && 'allcomplexformats' !== appSettings.get('subtitleburnin'));
builderOpts.enableSsaRender = (item && !options.isRetry && appSettings.get('subtitleburnin') !== 'allcomplexformats');
profile = profileBuilder(builderOpts);
}
@ -105,6 +107,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 +261,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');
}
@ -281,7 +279,7 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
features.push('targetblank');
features.push('screensaver');
webSettings.enableMultiServer().then(enabled => {
webSettings.getMultiServer().then(enabled => {
if (enabled) features.push('multiserver');
});
@ -297,7 +295,7 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
features.push('fileinput');
}
if (browser.chrome) {
if (browser.chrome || browser.edgeChromium) {
features.push('chromecast');
}
@ -353,7 +351,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 () {
@ -374,7 +372,7 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
return window.NativeShell.AppHost.supports(command);
}
return -1 !== supportedFeatures.indexOf(command.toLowerCase());
return supportedFeatures.indexOf(command.toLowerCase()) !== -1;
},
preferVisualCards: browser.android || browser.chrome,
getSyncProfile: getSyncProfile,
@ -411,13 +409,6 @@ define(['appSettings', 'browser', 'events', 'htmlMediaHelper', 'webSettings', 'g
getPushTokenInfo: function () {
return {};
},
setThemeColor: function (color) {
var metaThemeColor = document.querySelector('meta[name=theme-color]');
if (metaThemeColor) {
metaThemeColor.setAttribute('content', color);
}
},
setUserScalable: function (scalable) {
if (!browser.tv) {
var att = scalable ? 'width=device-width, initial-scale=1, minimum-scale=1, user-scalable=yes' : 'width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no';

View file

@ -277,7 +277,7 @@ import 'programStyles';
*/
function getImageWidth(shape, screenWidth, isOrientationLandscape) {
const imagesPerRow = getPostersPerRow(shape, screenWidth, isOrientationLandscape);
return Math.round(screenWidth / imagesPerRow) * 2;
return Math.round(screenWidth / imagesPerRow);
}
/**
@ -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);
@ -1163,6 +1117,7 @@ import 'programStyles';
function importRefreshIndicator() {
if (!refreshIndicatorLoaded) {
refreshIndicatorLoaded = true;
/* 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
});
@ -1498,14 +1449,15 @@ import 'programStyles';
const userData = item.UserData || {};
if (itemHelper.canMarkPlayed(item)) {
/* 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;
/* 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);

View file

@ -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,12 +70,10 @@ import browser from 'browser';
}
function getImgUrl({Id}, {ImageTag}, index, maxWidth, apiClient) {
if (ImageTag) {
return apiClient.getScaledImageUrl(Id, {
maxWidth: maxWidth * 2,
maxWidth: maxWidth,
tag: ImageTag,
type: 'Chapter',
index
@ -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';
@ -110,13 +104,10 @@ import browser from 'browser';
const cardBoxCssClass = 'cardBox';
const cardScalableClass = 'cardScalable';
const html = `<button type="button" class="${className}"${dataAttributes}><div class="${cardBoxCssClass}"><div class="${cardScalableClass}"><div class="cardPadder-${shape}"></div>${cardImageContainer}</div><div class="innerCardFooter">${nameHtml}</div></div></div></button>`;
return html;
return `<button type="button" class="${className}"${dataAttributes}><div class="${cardBoxCssClass}"><div class="${cardScalableClass}"><div class="cardPadder-${shape}"></div>${cardImageContainer}</div><div class="innerCardFooter">${nameHtml}</div></div></div></button>`;
}
export function buildChapterCards(item, chapters, options) {
if (options.parentContainer) {
// Abort if the container has been disposed
if (!document.body.contains(options.parentContainer)) {

View file

@ -8,7 +8,6 @@
import cardBuilder from 'cardBuilder';
export function buildPeopleCards(items, options) {
options = Object.assign(options || {}, {
cardLayout: false,
centerText: true,

View file

@ -1,23 +1,16 @@
define([], function() {
'use strict';
class CastSenderApi {
load() {
if (window.appMode === 'cordova' || window.appMode === 'android') {
return {
load: function () {
window.chrome = window.chrome || {};
return Promise.resolve();
}
};
} else {
var ccLoaded = false;
return {
load: function () {
let ccLoaded = false;
if (ccLoaded) {
return Promise.resolve();
}
return new Promise(function (resolve, reject) {
var fileref = document.createElement('script');
return new Promise(function (resolve) {
const fileref = document.createElement('script');
fileref.setAttribute('type', 'text/javascript');
fileref.onload = function () {
@ -29,6 +22,7 @@ define([], function() {
document.querySelector('head').appendChild(fileref);
});
}
};
}
});
}
export default CastSenderApi;

View file

@ -1,7 +1,6 @@
import dom from 'dom';
import dialogHelper from 'dialogHelper';
import loading from 'loading';
import appHost from 'apphost';
import layoutManager from 'layoutManager';
import connectionManager from 'connectionManager';
import appRouter from 'appRouter';
@ -39,7 +38,6 @@ import 'flexStyles';
}
function createCollection(apiClient, dlg) {
const url = apiClient.getUrl('Collections', {
Name: dlg.querySelector('#txtNewCollectionName').value,
@ -53,7 +51,6 @@ import 'flexStyles';
dataType: 'json'
}).then(result => {
loading.hide();
const id = result.Id;
@ -61,17 +58,14 @@ import 'flexStyles';
dlg.submitted = true;
dialogHelper.close(dlg);
redirectToCollection(apiClient, id);
});
}
function redirectToCollection(apiClient, id) {
appRouter.showItem(id, apiClient.serverId());
}
function addToCollection(apiClient, dlg, id) {
const url = apiClient.getUrl(`Collections/${id}/Items`, {
Ids: dlg.querySelector('.fldSelectedItemIds').value || ''
@ -82,7 +76,6 @@ import 'flexStyles';
url: url
}).then(() => {
loading.hide();
dlg.submitted = true;
@ -99,7 +92,6 @@ import 'flexStyles';
}
function populateCollections(panel) {
loading.show();
const select = panel.querySelector('#selectCollectionToAddTo');
@ -116,13 +108,11 @@ import 'flexStyles';
const apiClient = connectionManager.getApiClient(currentServerId);
apiClient.getItems(apiClient.getCurrentUserId(), options).then(result => {
let html = '';
html += `<option value="">${globalize.translate('OptionNew')}</option>`;
html += result.Items.map(i => {
return `<option value="${i.Id}">${i.Name}</option>`;
});
@ -135,7 +125,6 @@ import 'flexStyles';
}
function getEditorHtml() {
let html = '';
html += '<div class="formDialogContent smoothScrollY" style="padding-top:2em;">';
@ -183,7 +172,6 @@ import 'flexStyles';
}
function initEditor(content, items) {
content.querySelector('#selectCollectionToAddTo').addEventListener('change', function () {
if (this.value) {
content.querySelector('.newCollectionInfo').classList.add('hide');
@ -220,7 +208,6 @@ import 'flexStyles';
export class showEditor {
constructor(options) {
const items = options.items || {};
currentServerId = options.serverId;
@ -248,10 +235,6 @@ import 'flexStyles';
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();
@ -261,7 +244,6 @@ import 'flexStyles';
initEditor(dlg, items);
dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg);
});
@ -270,7 +252,6 @@ import 'flexStyles';
}
return dialogHelper.open(dlg).then(() => {
if (layoutManager.tv) {
centerFocus(dlg.querySelector('.formDialogContent'), false, false);
}

View file

@ -4,7 +4,6 @@ import globalize from 'globalize';
/* eslint-disable indent */
export default (() => {
function replaceAll(str, find, replace) {
return str.split(find).join(replace);
}

View file

@ -13,7 +13,6 @@ import 'flexStyles';
/* eslint-disable indent */
function showDialog(options, template) {
const dialogOptions = {
removeOnClose: true,
scrollY: false
@ -45,10 +44,6 @@ import 'flexStyles';
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 {
@ -68,7 +63,6 @@ import 'flexStyles';
let hasDescriptions = false;
for (i = 0, length = options.buttons.length; i < length; i++) {
const item = options.buttons[i];
const autoFocus = i === 0 ? ' autofocus' : '';
@ -111,7 +105,6 @@ import 'flexStyles';
}
return dialogHelper.open(dlg).then(() => {
if (enableTvLayout) {
scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false);
}
@ -125,7 +118,6 @@ import 'flexStyles';
}
export async function show(text, title) {
let options;
if (typeof text === 'string') {
options = {

View file

@ -12,7 +12,6 @@ import 'scrollStyles';
let globalOnOpenCallback;
function enableAnimation() {
// too slow
if (browser.tv) {
return false;
@ -22,7 +21,6 @@ import 'scrollStyles';
}
function removeCenterFocus(dlg) {
if (layoutManager.tv) {
if (dlg.classList.contains('scrollX')) {
centerFocus(dlg, true, false);
@ -35,7 +33,6 @@ import 'scrollStyles';
function tryRemoveElement(elem) {
const parentNode = elem.parentNode;
if (parentNode) {
// Seeing crashes in edge webview
try {
parentNode.removeChild(elem);
@ -46,14 +43,12 @@ import 'scrollStyles';
}
function DialogHashHandler(dlg, hash, resolve) {
const self = this;
self.originalUrl = window.location.href;
const activeElement = document.activeElement;
let removeScrollLockOnClose = false;
function onHashChange(e) {
const isBack = self.originalUrl === window.location.href;
if (isBack || !isOpened(dlg)) {
@ -67,7 +62,6 @@ import 'scrollStyles';
}
function onBackCommand(e) {
if (e.detail.command === 'back') {
self.closedByBack = true;
e.preventDefault();
@ -77,7 +71,6 @@ import 'scrollStyles';
}
function onDialogClosed() {
if (!isHistoryEnabled(dlg)) {
inputManager.off(dlg, onBackCommand);
}
@ -158,7 +151,6 @@ import 'scrollStyles';
}
function addBackdropOverlay(dlg) {
const backdrop = document.createElement('div');
backdrop.classList.add('dialogBackdrop');
@ -193,7 +185,6 @@ import 'scrollStyles';
}
export function open(dlg) {
if (globalOnOpenCallback) {
globalOnOpenCallback(dlg);
}
@ -210,19 +201,16 @@ import 'scrollStyles';
document.body.appendChild(dialogContainer);
return new Promise((resolve, reject) => {
new DialogHashHandler(dlg, `dlg${new Date().getTime()}`, resolve);
});
}
function isOpened(dlg) {
//return dlg.opened;
return !dlg.classList.contains('hide');
}
export function close(dlg) {
if (isOpened(dlg)) {
if (isHistoryEnabled(dlg)) {
history.back();
@ -233,9 +221,7 @@ import 'scrollStyles';
}
function closeDialog(dlg) {
if (!dlg.classList.contains('hide')) {
dlg.dispatchEvent(new CustomEvent('closing', {
bubbles: false,
cancelable: false
@ -256,7 +242,6 @@ import 'scrollStyles';
}
function animateDialogOpen(dlg) {
const onAnimationFinish = () => {
focusManager.pushScope(dlg);
@ -271,7 +256,6 @@ import 'scrollStyles';
};
if (enableAnimation()) {
const onFinish = () => {
dom.removeEventListener(dlg, dom.whichAnimationEvent(), onFinish, {
once: true
@ -288,13 +272,10 @@ import 'scrollStyles';
}
function animateDialogClose(dlg, onAnimationFinish) {
if (enableAnimation()) {
let animated = true;
switch (dlg.animationConfig.exit.name) {
case 'fadeout':
dlg.style.animation = `fadeout ${dlg.animationConfig.exit.timing.duration}ms ease-out normal both`;
break;
@ -329,7 +310,6 @@ import 'scrollStyles';
const supportsOverscrollBehavior = 'overscroll-behavior-y' in document.body.style;
function shouldLockDocumentScroll(options) {
if (supportsOverscrollBehavior && (options.size || !browser.touch)) {
return false;
}
@ -350,7 +330,6 @@ import 'scrollStyles';
}
function removeBackdrop(dlg) {
const backdrop = dlg.backdrop;
if (!backdrop) {
@ -364,7 +343,6 @@ import 'scrollStyles';
};
if (enableAnimation()) {
backdrop.classList.remove('dialogBackdropOpened');
// this is not firing animatonend
@ -383,7 +361,6 @@ import 'scrollStyles';
}
export function createDialog(options) {
options = options || {};
// If there's no native dialog support, use a plain div
@ -473,9 +450,7 @@ import 'scrollStyles';
}
if (enableAnimation()) {
switch (dlg.animationConfig.entry.name) {
case 'fadein':
dlg.style.animation = `fadein ${entryAnimationDuration}ms ease-out normal`;
break;

View file

@ -1,6 +1,5 @@
import browser from 'browser';
import layoutManager from 'layoutManager';
import appSettings from 'appSettings';
import pluginManager from 'pluginManager';
import appHost from 'apphost';
import focusManager from 'focusManager';
@ -16,17 +15,22 @@ import 'emby-button';
/* eslint-disable indent */
function fillThemes(select, isDashboard) {
select.innerHTML = skinManager.getThemes().map(t => {
let value = t.id;
if (t.isDefault && !isDashboard) {
value = '';
} else if (t.isDefaultServerDashboard && isDashboard) {
value = '';
}
function fillThemes(context, userSettings) {
const select = context.querySelector('#selectTheme');
return `<option value="${value}">${t.name}</option>`;
skinManager.getThemes().then(themes => {
select.innerHTML = themes.map(t => {
return `<option value="${t.id}">${t.name}</option>`;
}).join('');
// get default theme
var defaultTheme = themes.find(theme => {
return theme.default;
});
// set the current theme
select.value = userSettings.theme() || defaultTheme.id;
});
}
function loadScreensavers(context, userSettings) {
@ -46,6 +50,7 @@ import 'emby-button';
selectScreensaver.innerHTML = options.map(o => {
return `<option value="${o.value}">${o.name}</option>`;
}).join('');
selectScreensaver.value = userSettings.screensaver();
if (!selectScreensaver.value) {
@ -54,61 +59,7 @@ import 'emby-button';
}
}
function loadSoundEffects(context, userSettings) {
const selectSoundEffects = context.querySelector('.selectSoundEffects');
const options = pluginManager.ofType('soundeffects').map(plugin => {
return {
name: plugin.name,
value: plugin.id
};
});
options.unshift({
name: globalize.translate('None'),
value: 'none'
});
selectSoundEffects.innerHTML = options.map(o => {
return `<option value="${o.value}">${o.name}</option>`;
}).join('');
selectSoundEffects.value = userSettings.soundEffects();
if (!selectSoundEffects.value) {
// TODO: set the default instead of none
selectSoundEffects.value = 'none';
}
}
function loadSkins(context, userSettings) {
const selectSkin = context.querySelector('.selectSkin');
const options = pluginManager.ofType('skin').map(plugin => {
return {
name: plugin.name,
value: plugin.id
};
});
selectSkin.innerHTML = options.map(o => {
return `<option value="${o.value}">${o.name}</option>`;
}).join('');
selectSkin.value = userSettings.skin();
if (!selectSkin.value && options.length) {
selectSkin.value = options[0].value;
}
if (options.length > 1 && appHost.supports('skins')) {
context.querySelector('.selectSkinContainer').classList.remove('hide');
} else {
context.querySelector('.selectSkinContainer').classList.add('hide');
}
}
function showOrHideMissingEpisodesField(context) {
if (browser.tizen || browser.web0s) {
context.querySelector('.fldDisplayMissingEpisodes').classList.add('hide');
return;
@ -118,13 +69,6 @@ import 'emby-button';
}
function loadForm(context, user, userSettings) {
if (user.Policy.IsAdministrator) {
context.querySelector('.selectDashboardThemeContainer').classList.remove('hide');
} else {
context.querySelector('.selectDashboardThemeContainer').classList.add('hide');
}
if (appHost.supports('displaylanguage')) {
context.querySelector('.languageSection').classList.remove('hide');
} else {
@ -143,18 +87,6 @@ import 'emby-button';
context.querySelector('.learnHowToContributeContainer').classList.add('hide');
}
if (appHost.supports('runatstartup')) {
context.querySelector('.fldAutorun').classList.remove('hide');
} else {
context.querySelector('.fldAutorun').classList.add('hide');
}
if (appHost.supports('soundeffects')) {
context.querySelector('.fldSoundEffects').classList.remove('hide');
} else {
context.querySelector('.fldSoundEffects').classList.add('hide');
}
if (appHost.supports('screensaver')) {
context.querySelector('.selectScreensaverContainer').classList.remove('hide');
} else {
@ -177,16 +109,8 @@ import 'emby-button';
context.querySelector('.fldThemeVideo').classList.add('hide');
}
context.querySelector('.chkRunAtStartup').checked = appSettings.runAtStartup();
const selectTheme = context.querySelector('#selectTheme');
const selectDashboardTheme = context.querySelector('#selectDashboardTheme');
fillThemes(selectTheme);
fillThemes(selectDashboardTheme, true);
fillThemes(context, userSettings);
loadScreensavers(context, userSettings);
loadSoundEffects(context, userSettings);
loadSkins(context, userSettings);
context.querySelector('.chkDisplayMissingEpisodes').checked = user.Configuration.DisplayMissingEpisodes || false;
@ -202,9 +126,6 @@ import 'emby-button';
context.querySelector('#txtLibraryPageSize').value = userSettings.libraryPageSize();
selectDashboardTheme.value = userSettings.dashboardTheme() || '';
selectTheme.value = userSettings.theme() || '';
context.querySelector('.selectLayout').value = layoutManager.getSavedLayout() || '';
showOrHideMissingEpisodesField(context);
@ -213,9 +134,6 @@ import 'emby-button';
}
function saveUser(context, user, userSettingsInstance, apiClient) {
appSettings.runAtStartup(context.querySelector('.chkRunAtStartup').checked);
user.Configuration.DisplayMissingEpisodes = context.querySelector('.chkDisplayMissingEpisodes').checked;
if (appHost.supports('displaylanguage')) {
@ -226,15 +144,11 @@ import 'emby-button';
userSettingsInstance.enableThemeSongs(context.querySelector('#chkThemeSong').checked);
userSettingsInstance.enableThemeVideos(context.querySelector('#chkThemeVideo').checked);
userSettingsInstance.dashboardTheme(context.querySelector('#selectDashboardTheme').value);
userSettingsInstance.theme(context.querySelector('#selectTheme').value);
userSettingsInstance.soundEffects(context.querySelector('.selectSoundEffects').value);
userSettingsInstance.screensaver(context.querySelector('.selectScreensaver').value);
userSettingsInstance.libraryPageSize(context.querySelector('#txtLibraryPageSize').value);
userSettingsInstance.skin(context.querySelector('.selectSkin').value);
userSettingsInstance.enableFastFadein(context.querySelector('#chkFadein').checked);
userSettingsInstance.enableBlurhash(context.querySelector('#chkBlurhash').checked);
userSettingsInstance.enableBackdrops(context.querySelector('#chkBackdrops').checked);

View file

@ -1,5 +1,4 @@
<form style="margin: 0 auto;">
<h2 class="sectionTitle">
${Display}
</h2>
@ -123,26 +122,14 @@
<div class="fieldDescription">${LabelPleaseRestart}</div>
</div>
<div class="selectContainer hide selectSkinContainer">
<select is="emby-select" class="selectSkin" label="${LabelSkin}"></select>
</div>
<div class="selectContainer">
<select id="selectTheme" is="emby-select" label="${LabelTheme}"></select>
</div>
<div class="selectContainer selectDashboardThemeContainer hide">
<select id="selectDashboardTheme" is="emby-select" label="${LabelDashboardTheme}"></select>
</div>
<div class="selectContainer hide selectScreensaverContainer">
<select is="emby-select" class="selectScreensaver" label="${LabelScreensaver}"></select>
</div>
<div class="selectContainer fldSoundEffects hide">
<select is="emby-select" class="selectSoundEffects" label="${LabelSoundEffects}"></select>
</div>
<div class="inputContainer inputContainer-withDescription">
<input is="emby-input" type="number" id="txtLibraryPageSize" pattern="[0-9]*" required="required" min="0" max="1000" step="1" label="${LabelLibraryPageSize}" />
<div class="fieldDescription">${LabelLibraryPageSizeHelp}</div>
@ -159,9 +146,9 @@
<div class="checkboxContainer checkboxContainer-withDescription">
<label>
<input type="checkbox" is="emby-checkbox" id="chkBlurhash" />
<span>${EnableBlurhash}</span>
<span>${EnableBlurHash}</span>
</label>
<div class="fieldDescription checkboxFieldDescription">${EnableBlurhashHelp}</div>
<div class="fieldDescription checkboxFieldDescription">${EnableBlurHashHelp}</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
@ -196,13 +183,6 @@
<div class="fieldDescription checkboxFieldDescription">${EnableThemeVideosHelp}</div>
</div>
<div class="checkboxContainer hide fldAutorun">
<label>
<input type="checkbox" is="emby-checkbox" class="chkRunAtStartup" />
<span>${RunAtStartup}</span>
</label>
</div>
<div class="checkboxContainer checkboxContainer-withDescription fldDisplayMissingEpisodes hide">
<label>
<input type="checkbox" is="emby-checkbox" class="chkDisplayMissingEpisodes" />

View file

@ -1,5 +1,14 @@
define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoader', 'globalize', 'layoutManager', 'scrollStyles', 'emby-itemscontainer'], function (loading, libraryBrowser, cardBuilder, dom, appHost, imageLoader, globalize, layoutManager) {
'use strict';
import loading from 'loading';
import cardBuilder from 'cardBuilder';
import dom from 'dom';
import appHost from 'apphost';
import imageLoader from 'imageLoader';
import globalize from 'globalize';
import layoutManager from 'layoutManager';
import 'scrollStyles';
import 'emby-itemscontainer';
/* eslint-disable indent */
function enableScrollX() {
return !layoutManager.desktop;
@ -94,8 +103,8 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
}
function loadSection(elem, userId, topParentId, section, isSingleSection) {
var screenWidth = dom.getWindowSize().innerWidth;
var options = {
const screenWidth = dom.getWindowSize().innerWidth;
const options = {
SortBy: 'SortName',
SortOrder: 'Ascending',
Filters: 'IsFavorite',
@ -118,9 +127,9 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
}
}
var promise;
let promise;
if ('MusicArtist' === section.types) {
if (section.types === 'MusicArtist') {
promise = ApiClient.getArtists(userId, options);
} else {
options.IncludeItemTypes = section.types;
@ -128,7 +137,7 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
}
return promise.then(function (result) {
var html = '';
let html = '';
if (result.Items.length) {
if (html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">', !layoutManager.tv && options.Limit && result.Items.length >= options.Limit) {
@ -144,7 +153,7 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
html += '</div>';
if (enableScrollX()) {
var scrollXClass = 'scrollX hiddenScrollX';
let scrollXClass = 'scrollX hiddenScrollX';
if (layoutManager.tv) {
scrollXClass += ' smoothScrollX';
}
@ -154,14 +163,13 @@ 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;
let cardLayout = appHost.preferVisualCards && section.autoCardLayout && section.showTitle;
cardLayout = false;
html += cardBuilder.getCardsHtml(result.Items, {
preferThumb: section.preferThumb,
shape: section.shape,
centerText: section.centerText && !cardLayout,
overlayText: false !== section.overlayText,
overlayText: section.overlayText !== false,
showTitle: section.showTitle,
showParentTitle: section.showParentTitle,
scalable: true,
@ -180,10 +188,10 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
});
}
function loadSections(page, userId, topParentId, types) {
export function loadSections(page, userId, topParentId, types) {
loading.show();
var sections = getSections();
var sectionid = getParameterByName('sectionid');
let sections = getSections();
const sectionid = getParameterByName('sectionid');
if (sectionid) {
sections = sections.filter(function (s) {
@ -193,30 +201,28 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
if (types) {
sections = sections.filter(function (s) {
return -1 !== types.indexOf(s.id);
return types.indexOf(s.id) !== -1;
});
}
var i;
var length;
var elem = page.querySelector('.favoriteSections');
let elem = page.querySelector('.favoriteSections');
if (!elem.innerHTML) {
var html = '';
let html = '';
for (i = 0, length = sections.length; i < length; i++) {
for (let i = 0, length = sections.length; i < length; i++) {
html += '<div class="verticalSection section' + sections[i].id + '"></div>';
}
elem.innerHTML = html;
}
var promises = [];
const promises = [];
for (i = 0, length = sections.length; i < length; i++) {
var section = sections[i];
for (let i = 0, length = sections.length; i < length; i++) {
const section = sections[i];
elem = page.querySelector('.section' + section.id);
promises.push(loadSection(elem, userId, topParentId, section, 1 === sections.length));
promises.push(loadSection(elem, userId, topParentId, section, sections.length === 1));
}
Promise.all(promises).then(function () {
@ -224,7 +230,8 @@ define(['loading', 'libraryBrowser', 'cardBuilder', 'dom', 'apphost', 'imageLoad
});
}
return {
export default {
render: loadSections
};
});
/* eslint-enable indent */

View file

@ -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}`);

View file

@ -1,20 +1,17 @@
define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost', 'inputManager', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'userSettings', 'emby-checkbox', 'emby-input', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button', 'flexStyles'], function (require, dom, focusManager, dialogHelper, loading, appHost, inputManager, layoutManager, connectionManager, appRouter, globalize, userSettings) {
'use strict';
focusManager = focusManager.default || focusManager;
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 +19,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
var html = '';
html += items.map(function (filter) {
var itemHtml = '';
var checkedHtml = isCheckedFn(filter) ? ' checked' : '';
@ -32,45 +28,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 +52,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 +64,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 +75,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 +82,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 +99,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 +115,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 +126,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 +136,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 +144,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);
@ -201,7 +158,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
}
function moveCheckboxFocus(elem, offset) {
var parent = dom.parentWithClass(elem, 'checkboxList-verticalwrap');
var elems = focusManager.getFocusableElements(parent);
@ -226,7 +182,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
function onInputCommand(e) {
switch (e.detail.command) {
case 'left':
moveCheckboxFocus(e.target, -1);
e.preventDefault();
@ -245,7 +200,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) {
@ -257,11 +211,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
@ -304,7 +255,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
bindCheckboxInput(dlg, true);
dlg.querySelector('.btnCancel').addEventListener('click', function () {
dialogHelper.close(dlg);
});
@ -315,17 +265,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) {
@ -333,7 +276,6 @@ define(['require', 'dom', 'focusManager', 'dialogHelper', 'loading', 'apphost',
}
if (submitted) {
//if (!options.onChange) {
saveValues(dlg, options.settings, options.settingsKey);
resolve();

View file

@ -1,5 +1,7 @@
define(['dom', 'scrollManager'], function (dom, scrollManager) {
'use strict';
/* eslint-disable indent */
import dom from 'dom';
import scrollManager from 'scrollManager';
var scopes = [];
function pushScope(elem) {
@ -7,14 +9,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 +37,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
}
function focus(element) {
try {
element.focus({
preventScroll: scrollManager.isEnabled()
@ -50,16 +49,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 +79,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
}
function focusableParent(elem) {
var originalElement = elem;
while (!isFocusable(elem)) {
@ -101,7 +96,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 +106,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 +136,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 +155,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
}
function isFocusContainer(elem, direction) {
if (focusableContainerTagNames.indexOf(elem.tagName) !== -1) {
return true;
}
@ -217,7 +208,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
}
function getOffset(elem) {
var box;
// Support: BlackBerry 5, iOS 3 (original iPhone)
@ -234,7 +224,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 +242,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
}
function nav(activeElement, direction, container, focusableElements) {
activeElement = activeElement || document.activeElement;
if (activeElement) {
@ -272,14 +260,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 +285,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
continue;
}
//if (!isCurrentlyFocusableInternal(curr)) {
// continue;
//}
var elementRect = getOffset(curr);
// not currently visible
@ -313,7 +293,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
}
switch (direction) {
case 0:
// left
if (elementRect.left >= rect.left) {
@ -369,7 +348,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
var distY;
switch (direction) {
case 0:
// left
distX = Math.abs(point1x - Math.min(point1x, x2));
@ -403,7 +381,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 +395,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 +409,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 +422,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 +435,6 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
}
function moveFocus(sourceElement, container, focusableSelector, offset) {
var elems = container.querySelectorAll(focusableSelector);
var list = [];
var i;
@ -472,7 +442,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 +452,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)) {
@ -506,7 +474,9 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
}
}
return {
/* eslint-enable indent */
export default {
autoFocus: autoFocus,
focus: focus,
focusableParent: focusableParent,
@ -539,4 +509,3 @@ define(['dom', 'scrollManager'], function (dom, scrollManager) {
focusLast: focusLast,
moveFocus: moveFocus
};
});

View file

@ -21,7 +21,7 @@ import connectionManager from 'connectionManager';
if (!actionableParent || actionableParent.classList.contains('cardContent')) {
apiClient.getJSON(apiClient.getUrl('Users/' + userId + '/Items/Latest', options)).then(function (items) {
if (1 === items.length) {
if (items.length === 1) {
return void appRouter.showItem(items[0]);
}

View file

@ -4,12 +4,10 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio
scrollHelper = scrollHelper.default || scrollHelper;
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) {
@ -27,12 +25,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;
@ -40,13 +36,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);
}
@ -64,13 +58,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') {
@ -92,13 +84,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
@ -121,12 +110,10 @@ define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectio
dlg.innerHTML = html;
dlg.addEventListener('change', function () {
settingsChanged = true;
});
dlg.addEventListener('close', function () {
if (layoutManager.tv) {
scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false);
}

View file

@ -1,12 +1,13 @@
define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager', 'scrollHelper', 'serverNotifications', 'loading', 'datetime', 'focusManager', 'playbackManager', 'userSettings', 'imageLoader', 'events', 'layoutManager', 'itemShortcuts', 'dom', 'css!./guide.css', 'programStyles', 'material-icons', 'scrollStyles', 'emby-programcell', 'emby-button', 'paper-icon-button-light', 'emby-tabs', 'emby-scroller', 'flexStyles', 'webcomponents'], function (require, inputManager, browser, globalize, connectionManager, scrollHelper, serverNotifications, loading, datetime, focusManager, playbackManager, userSettings, imageLoader, events, layoutManager, itemShortcuts, dom) {
'use strict';
scrollHelper = scrollHelper.default || scrollHelper;
playbackManager = playbackManager.default || playbackManager;
browser = browser.default || browser;
loading = loading.default || loading;
focusManager = focusManager.default || focusManager;scrollHelper = scrollHelper.default || scrollHelper;
serverNotifications = serverNotifications.default || serverNotifications;
function showViewSettings(instance) {
require(['guide-settings-dialog'], function (guideSettingsDialog) {
guideSettingsDialog.show(instance.categoryOptions).then(function () {
instance.refresh();
@ -15,7 +16,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
}
function updateProgramCellOnScroll(cell, scrollPct) {
var left = cell.posLeft;
if (!left) {
left = parseFloat(cell.style.left.replace('%', ''));
@ -47,11 +47,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');
}
@ -60,7 +58,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
var isUpdatingProgramCellScroll = false;
function updateProgramCellsOnScroll(programGrid, programCells) {
if (isUpdatingProgramCellScroll) {
return;
}
@ -68,13 +65,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);
}
@ -83,14 +78,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();
@ -98,7 +91,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');
@ -114,7 +106,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
}
function Guide(options) {
var self = this;
var items = {};
@ -125,7 +116,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;
@ -136,7 +126,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
var programGrid;
self.refresh = function () {
currentDate = null;
reloadPage(options.element);
restartAutoRefresh();
@ -155,7 +144,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
};
self.destroy = function () {
stopAutoRefresh();
events.off(serverNotifications, 'TimerCreated', onTimerCreated);
@ -169,7 +157,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
};
function restartAutoRefresh() {
stopAutoRefresh();
var intervalMs = 60000 * 15; // (minutes)
@ -187,15 +174,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);
}
@ -211,7 +194,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
}
function reloadGuide(context, newStartDate, scrollToTimeMs, focusToTimeMs, startTimeOfDayMs, focusProgramOnRender) {
var apiClient = connectionManager.getApiClient(options.serverId);
var channelQuery = {
@ -294,12 +276,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');
@ -316,7 +296,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
} else {
btnNextPage.disabled = true;
}
} else {
context.querySelector('.guideOptions').classList.add('hide');
}
@ -347,22 +326,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;
}
@ -372,7 +346,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
}
function getTimeslotHeadersHtml(startDate, endDateTime) {
var html = '';
// clone
@ -381,7 +354,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
html += '<div class="timeslotHeadersInner">';
while (startDate.getTime() < endDateTime) {
html += '<div class="timeslotHeader">';
html += getDisplayTime(startDate);
@ -415,23 +387,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>';
}
@ -443,7 +411,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
}
function getChannelProgramsHtml(context, date, channel, programs, options, listInfo) {
var html = '';
var startMs = date.getTime();
@ -467,11 +434,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;
}
@ -581,7 +546,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 {
@ -603,11 +567,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;
@ -619,18 +581,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,
@ -641,7 +600,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
}
if (channel.ChannelNumber) {
html += '<h3 class="guideChannelNumber">' + channel.ChannelNumber + '</h3>';
}
@ -658,7 +616,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
}
function renderPrograms(context, date, channels, programs, options) {
var listInfo = {
startIndex: 0
};
@ -666,7 +623,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));
}
@ -678,7 +634,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
}
function getProgramSortOrder(program, channels) {
var channelId = program.ChannelId;
var channelIndex = -1;
@ -695,7 +650,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);
});
@ -725,7 +679,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
}
function scrollProgramGridToTimeMs(context, scrollToTimeMs, startTimeOfDayMs) {
scrollToTimeMs -= startTimeOfDayMs;
var pct = scrollToTimeMs / msPerDay;
@ -738,7 +691,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
}
function focusProgram(context, itemId, channelRowId, focusToTimeMs, startTimeOfDayMs) {
var focusElem;
if (itemId) {
focusElem = context.querySelector('[data-id="' + itemId + '"]');
@ -747,7 +699,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
if (focusElem) {
focusManager.focus(focusElem);
} else {
var autoFocusParent;
if (channelRowId) {
@ -765,7 +716,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('%', '');
@ -786,7 +736,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
}
function nativeScrollTo(container, pos, horizontal) {
if (container.scrollTo) {
if (horizontal) {
container.scrollTo(pos, 0);
@ -806,7 +755,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();
@ -819,7 +767,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);
@ -827,7 +774,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
}
function changeDate(page, date, scrollToTimeMs, focusToTimeMs, startTimeOfDayMs, focusProgramOnRender) {
var newStartDate = normalizeDateToTimeslot(date);
currentDate = newStartDate;
@ -835,7 +781,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() + '">';
@ -850,7 +795,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);
@ -870,6 +814,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
var dateTabsHtml = '';
var tabIndex = 0;
// TODO: Use date-fns
var date = new Date();
if (currentDate) {
@ -877,13 +822,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);
@ -910,19 +853,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 = [];
@ -930,7 +870,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('%', '');
@ -947,7 +886,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
}
function onInputCommand(e) {
var target = e.target;
var programCell = dom.parentWithClass(target, 'programCell');
var container;
@ -955,10 +893,7 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
var focusableElements;
var newRow;
var scrollX = false;
switch (e.detail.command) {
case 'up':
if (programCell) {
container = programGrid;
@ -1022,7 +957,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
focusManager.moveLeft(target, {
container: container
});
scrollX = true;
break;
case 'right':
container = programCell ? dom.parentWithClass(programCell, 'channelPrograms') : null;
@ -1031,7 +965,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
focusManager.moveRight(target, {
container: container
});
scrollX = true;
break;
default:
return;
@ -1042,7 +975,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
}
function onScrollerFocus(e) {
var target = e.target;
var programCell = dom.parentWithClass(target, 'programCell');
@ -1061,22 +993,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);
}
@ -1084,7 +1010,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
}
function setScrollEvents(view, enabled) {
if (layoutManager.tv) {
var guideVerticalScroller = view.querySelector('.guideVerticalScroller');
@ -1097,7 +1022,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;
@ -1150,7 +1074,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
}
require(['text!./tvguide.template.html'], function (template) {
var context = options.element;
context.classList.add('tvguide');
@ -1207,12 +1130,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();
@ -1227,7 +1148,6 @@ define(['require', 'inputManager', 'browser', 'globalize', 'connectionManager',
}
if (previousButton) {
var previousDate = new Date();
previousDate.setTime(parseInt(previousButton.getAttribute('data-date')));

View file

@ -15,12 +15,10 @@ import 'emby-checkbox';
const numConfigurableSections = 7;
function renderViews(page, user, result) {
let folderHtml = '';
folderHtml += '<div class="checkboxList">';
folderHtml += result.map(i => {
let currentHtml = '';
const id = `chkGroupFolder${i.Id}`;
@ -35,7 +33,6 @@ import 'emby-checkbox';
currentHtml += '</label>';
return currentHtml;
}).join('');
folderHtml += '</div>';
@ -44,7 +41,6 @@ import 'emby-checkbox';
}
function getLandingScreenOptions(type) {
const list = [];
if (type === 'movies') {
@ -133,9 +129,7 @@ import 'emby-checkbox';
}
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;
@ -145,13 +139,9 @@ import 'emby-checkbox';
}
function renderViewOrder(context, user, result) {
let html = '';
let index = 0;
html += result.Items.map(view => {
html += result.Items.map((view) => {
let currentHtml = '';
currentHtml += `<div class="listItem viewItem" data-viewid="${view.Id}">`;
@ -171,18 +161,14 @@ import 'emby-checkbox';
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);
@ -203,7 +189,6 @@ import 'emby-checkbox';
}
function getPerLibrarySettingsHtml(item, user, userSettings, apiClient) {
let html = '';
let isChecked;
@ -220,7 +205,6 @@ import 'emby-checkbox';
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"' : ''}/>`;
@ -229,12 +213,10 @@ import 'emby-checkbox';
}
if (html) {
html = `<div class="checkboxListContainer">${html}</div>`;
}
if (item.CollectionType === 'movies' || item.CollectionType === 'tvshows' || item.CollectionType === 'music' || item.CollectionType === 'livetv') {
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')}">`;
@ -248,7 +230,6 @@ import 'emby-checkbox';
}
if (html) {
let prefix = '';
prefix += '<div class="verticalSection">';
@ -264,12 +245,10 @@ import 'emby-checkbox';
}
function renderPerLibrarySettings(context, user, userViews, userSettings, apiClient) {
const elem = context.querySelector('.perLibrarySettings');
let html = '';
for (let i = 0, length = userViews.length; i < length; i++) {
html += getPerLibrarySettingsHtml(userViews[i], user, userSettings, apiClient);
}
@ -277,7 +256,6 @@ import 'emby-checkbox';
}
function loadForm(context, user, userSettings, apiClient) {
context.querySelector('.chkHidePlayedFromLatest').checked = user.Configuration.HidePlayedInLatest || false;
updateHomeSectionValues(context, userSettings);
@ -286,7 +264,6 @@ import 'emby-checkbox';
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);
@ -298,17 +275,13 @@ import 'emby-checkbox';
}
function onSectionOrderListClick(e) {
const target = dom.parentWithClass(e.target, 'btnViewItemMove');
if (target) {
const viewItem = dom.parentWithClass(target, 'viewItem');
if (viewItem) {
const ul = dom.parentWithClass(viewItem, 'paperList');
if (target.classList.contains('btnViewItemDown')) {
const next = viewItem.nextSibling;
if (next) {
@ -316,9 +289,7 @@ import 'emby-checkbox';
next.parentNode.insertBefore(viewItem, next.nextSibling);
focusManager.focus(e.target);
}
} else {
const prev = viewItem.previousSibling;
if (prev) {
@ -332,37 +303,30 @@ import 'emby-checkbox';
}
function getCheckboxItems(selector, context, isChecked) {
const inputs = context.querySelectorAll(selector);
const list = [];
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(i => {
return i.getAttribute('data-folderid');
});
user.Configuration.MyMediaExcludes = getCheckboxItems('.chkIncludeInMyMedia', context, false).map(i => {
return i.getAttribute('data-folderid');
});
user.Configuration.GroupedFolders = getCheckboxItems('.chkGroupFolder', context, true).map(i => {
return i.getAttribute('data-folderid');
});
@ -396,13 +360,10 @@ import 'emby-checkbox';
}
function save(instance, context, userId, userSettings, apiClient, enableSaveConfirmation) {
loading.show();
apiClient.getUser(userId).then(user => {
saveUser(context, user, userSettings, apiClient).then(() => {
loading.hide();
if (enableSaveConfirmation) {
import('toast').then(({default: toast}) => {
@ -411,7 +372,6 @@ import 'emby-checkbox';
}
events.trigger(instance, 'saved');
}, () => {
loading.hide();
});
@ -419,14 +379,12 @@ import 'emby-checkbox';
}
function onSubmit(e) {
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(() => {
const enableSaveConfirmation = self.options.enableSaveConfirmation;
save(self, self.options.element, userId, userSettings, apiClient, enableSaveConfirmation);
});
@ -439,7 +397,6 @@ import 'emby-checkbox';
}
function onChange(e) {
const chkIncludeInMyMedia = dom.parentWithClass(e.target, 'chkIncludeInMyMedia');
if (!chkIncludeInMyMedia) {
return;
@ -457,9 +414,7 @@ import 'emby-checkbox';
}
function embed(options, self) {
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));
}
@ -491,7 +446,6 @@ import 'emby-checkbox';
}
loadData(autoFocus) {
const self = this;
const context = self.options.element;
@ -502,9 +456,7 @@ import 'emby-checkbox';
const userSettings = self.options.userSettings;
apiClient.getUser(userId).then(user => {
userSettings.setUserInfo(userId, apiClient).then(() => {
self.dataLoaded = true;
loadForm(context, user, userSettings, apiClient);
@ -521,7 +473,6 @@ import 'emby-checkbox';
}
destroy() {
this.options = null;
}
}

View file

@ -1,13 +1,9 @@
import connectionManager from 'connectionManager';
import cardBuilder from 'cardBuilder';
import appSettings from 'appSettings';
import dom from 'dom';
import appHost from 'apphost';
import layoutManager from 'layoutManager';
import imageLoader from 'imageLoader';
import globalize from 'globalize';
import itemShortcuts from 'itemShortcuts';
import itemHelper from 'itemHelper';
import appRouter from 'appRouter';
import imageHelper from 'scripts/imagehelper';
import 'paper-icon-button-light';
@ -135,7 +131,6 @@ import 'css!./homesections';
}
function loadSection(page, apiClient, user, userSettings, userViews, allSections, index) {
const section = allSections[index];
const userId = user.Id;
@ -215,14 +210,6 @@ import 'css!./homesections';
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 () {
const apiClient = connectionManager.getApiClient(serverId);
@ -347,14 +334,6 @@ import 'css!./homesections';
}
}
function getRequirePromise(deps) {
return new Promise(function (resolve, reject) {
import(deps).then(() => {
return resolve;
});
});
}
export function loadLibraryTiles(elem, apiClient, user, userSettings, shape, userViews, allSections) {
let html = '';
if (userViews.length) {
@ -549,7 +528,6 @@ import 'css!./homesections';
}
function getOnNowItemsHtml(items) {
const cardLayout = false;
return cardBuilder.getCardsHtml({
items: items,
preferThumb: 'auto',
@ -576,7 +554,6 @@ import 'css!./homesections';
return Promise.resolve();
}
const userId = user.Id;
return apiClient.getLiveTvRecommendedPrograms({
userId: apiClient.getCurrentUserId(),
IsAiring: true,
@ -649,7 +626,6 @@ import 'css!./homesections';
html += '</h2>';
html += '<span class="material-icons chevron_right"></span>';
html += '</a>';
} else {
html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate('HeaderOnNow') + '</h2>';
}
@ -766,7 +742,6 @@ import 'css!./homesections';
function getLatestRecordingItemsHtml(activeRecordingsOnly) {
return function (items) {
const cardLayout = false;
return cardBuilder.getCardsHtml({
items: items,
shape: enableScrollX() ? 'autooverflow' : 'auto',

View file

@ -33,34 +33,7 @@ import events from 'events';
return false;
}
export 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;
}
export function enableHlsJsPlayer(runTimeTicks, mediaType) {
if (window.MediaSource == null) {
return false;
}
@ -76,7 +49,6 @@ import events from 'events';
}
if (canPlayNativeHls()) {
// Having trouble with chrome's native support and transcoded music
if (browser.android && mediaType === 'Audio') {
return true;
@ -102,7 +74,6 @@ import events from 'events';
var recoverDecodingErrorDate;
var recoverSwapAudioCodecDate;
export function handleHlsJsMediaError(instance, reject) {
var hlsPlayer = instance._hlsPlayer;
if (!hlsPlayer) {
@ -138,7 +109,6 @@ import events from 'events';
}
export function onErrorInternal(instance, type) {
// Needed for video
if (instance.destroyCustomTrack) {
instance.destroyCustomTrack(instance._mediaElement);
@ -166,12 +136,9 @@ import events from 'events';
}
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
@ -204,11 +171,8 @@ import events from 'events';
}
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);
@ -217,9 +181,7 @@ import events from 'events';
elem.src = URL.createObjectURL(playlist, { oneTimeOnly: true });
return Promise.resolve();
});
} else {
elem.src = src;
}
@ -227,18 +189,15 @@ import events from 'events';
}
function onSuccessfulPlay(elem, onErrorFn) {
elem.addEventListener('error', 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' ||
@ -260,7 +219,6 @@ import events from 'events';
}
export function destroyCastPlayer(instance) {
var player = instance._castPlayer;
if (player) {
try {
@ -273,19 +231,6 @@ import events from 'events';
}
}
export function destroyShakaPlayer(instance) {
var player = instance._shakaPlayer;
if (player) {
try {
player.destroy();
} catch (err) {
console.error(err);
}
instance._shakaPlayer = null;
}
}
export function destroyHlsPlayer(instance) {
var player = instance._hlsPlayer;
if (player) {
@ -315,10 +260,8 @@ import events from 'events';
}
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;
@ -327,14 +270,12 @@ import events from 'events';
});
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
@ -348,7 +289,6 @@ import events from 'events';
}
return;
}
break;
@ -361,7 +301,6 @@ import events from 'events';
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);
@ -407,7 +346,6 @@ import events from 'events';
}
export function onEndedInternal(instance, elem, onErrorFn) {
elem.removeEventListener('error', onErrorFn);
elem.src = '';
@ -416,7 +354,6 @@ import events from 'events';
destroyHlsPlayer(instance);
destroyFlvPlayer(instance);
destroyShakaPlayer(instance);
destroyCastPlayer(instance);
var stopInfo = {
@ -431,7 +368,6 @@ import events from 'events';
}
export function getBufferedRanges(instance, elem) {
var ranges = [];
var seekable = elem.buffered || [];
@ -444,7 +380,6 @@ import events from 'events';
offset = offset || 0;
for (var i = 0, length = seekable.length; i < length; i++) {
var start = seekable.start(i);
var end = seekable.end(i);

View file

@ -1,26 +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';
scrollHelper = scrollHelper.default || scrollHelper;
/* eslint-disable indent */
var enableFocusTransform = !browser.slow && !browser.edge;
const enableFocusTransform = !browser.slow && !browser.edge;
var currentItemId;
var currentItemType;
var currentResolve;
var currentReject;
var hasChanges = false;
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;
@ -28,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 () {
@ -94,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>';
@ -129,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;
@ -138,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);
});
}
@ -150,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') {
@ -168,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') {
@ -219,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;
}
}
@ -240,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);
@ -272,7 +271,6 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
// end footer
html += '</div>';
//html += '</div>';
html += '</' + tagName + '>';
@ -289,7 +287,6 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
});
page.querySelector('#selectImageProvider').addEventListener('change', function () {
browsableImageStartIndex = 0;
selectedProvider = this.value;
@ -297,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'));
}
@ -323,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
};
@ -339,7 +333,7 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
dialogOptions.size = 'small';
}
var dlg = dialogHelper.createDialog(dialogOptions);
const dlg = dialogHelper.createDialog(dialogOptions);
dlg.innerHTML = globalize.translateHtml(template, 'core');
@ -352,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);
});
@ -365,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);
@ -379,8 +372,7 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
}
}
return {
show: function (itemId, serverId, itemType, imageType) {
export function show(itemId, serverId, itemType, imageType) {
return new Promise(function (resolve, reject) {
currentResolve = resolve;
currentReject = reject;
@ -388,9 +380,12 @@ define(['dom', 'loading', 'apphost', 'dialogHelper', 'connectionManager', 'image
browsableImageStartIndex = 0;
browsableImageType = imageType || 'Primary';
selectedProvider = null;
showEditor(itemId, serverId, itemType);
});
}
export default {
show: show
};
});
/* eslint-enable indent */

View file

@ -16,7 +16,7 @@ import 'emby-input';
return {
Type: type,
MinWidth: 0,
Limit: 'Primary' === type ? 1 : 0
Limit: type === 'Primary' ? 1 : 0
};
}

View file

@ -23,7 +23,6 @@ import 'css!./style';
let hasChanges = false;
function onFileReaderError(evt) {
loading.hide();
switch (evt.target.error.code) {
@ -43,7 +42,6 @@ import 'css!./style';
}
function setFiles(page, files) {
const file = files[0];
if (!file || !file.type.match('image.*')) {
@ -69,7 +67,6 @@ import 'css!./style';
// Closure to capture the file information.
reader.onload = (theFile => {
return e => {
// Render thumbnail.
const html = ['<img style="max-width:100%;max-height:100%;" src="', e.target.result, '" title="', escape(theFile.name), '"/>'].join('');
@ -84,7 +81,6 @@ import 'css!./style';
}
function onSubmit(e) {
const file = currentFile;
if (!file) {
@ -113,7 +109,6 @@ import 'css!./style';
}
connectionManager.getApiClient(currentServerId).uploadItemImage(currentItemId, imageType, file).then(() => {
dlg.querySelector('#uploadImage').value = '';
loading.hide();
@ -126,7 +121,6 @@ import 'css!./style';
}
function initEditor(page) {
page.querySelector('form').addEventListener('submit', onSubmit);
page.querySelector('#uploadImage').addEventListener('change', function () {
@ -139,11 +133,9 @@ import 'css!./style';
}
function showEditor(options, resolve) {
options = options || {};
return import('text!./imageUploader.template.html').then(({default: template}) => {
currentItemId = options.itemId;
currentServerId = options.serverId;
@ -169,7 +161,6 @@ import 'css!./style';
// Has to be assigned a z-index after the call to .open()
dlg.addEventListener('close', () => {
if (layoutManager.tv) {
scrollHelper.centerFocus.off(dlg, false);
}
@ -185,16 +176,13 @@ import 'css!./style';
dlg.querySelector('#selectImageType').value = options.imageType || 'Primary';
dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg);
});
});
}
export function show(options) {
return new Promise(resolve => {
hasChanges = false;
showEditor(options, resolve);

View file

@ -1,16 +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';
scrollHelper = scrollHelper.default || scrollHelper;
/* eslint-disable indent */
var enableFocusTransform = !browser.slow && !browser.edge;
const enableFocusTransform = !browser.slow && !browser.edge;
var currentItem;
var hasChanges = false;
let currentItem;
let hasChanges = false;
function getBaseRemoteOptions() {
var options = {};
const options = {};
options.itemId = currentItem.Id;
@ -18,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);
@ -36,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);
}
@ -46,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++) {
if (providers.length) {
btnBrowseAllImages[i].classList.remove('hide');
} else {
@ -62,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);
@ -76,7 +82,6 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
}
function getImageUrl(item, apiClient, type, index, options) {
options = options || {};
options.type = type;
options.index = index;
@ -96,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';
@ -132,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>';
@ -155,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 {
@ -185,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);
});
};
@ -200,9 +200,8 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
return;
}
require(['confirm'], function (confirm) {
confirm.default({
import('confirm').then(({default: confirm}) => {
confirm({
text: globalize.translate('ConfirmDeleteImage'),
confirmText: globalize.translate('Delete'),
@ -213,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) {
alert(globalize.translate('DefaultErrorMessage'));
import('alert').then(({default: alert}) => {
alert(globalize.translate('ErrorDefault'));
});
});
}
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);
}
@ -251,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';
});
@ -260,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;
});
@ -277,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;
});
@ -294,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'),
@ -355,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;
@ -373,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 {
@ -391,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,
@ -403,7 +380,6 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
serverId: currentItem.ServerId
}).then(function (hasChanged) {
if (hasChanged) {
hasChanges = true;
reload(context);
@ -425,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
};
@ -462,7 +436,7 @@ define(['dialogHelper', 'connectionManager', 'loading', 'dom', 'layoutManager',
dialogOptions.size = 'small';
}
var dlg = dialogHelper.createDialog(dialogOptions);
const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog');
@ -476,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);
}
@ -495,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);
});
}
export default {
show
};
});
/* eslint-enable indent */

View file

@ -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);
@ -208,7 +205,7 @@ import 'css!./style';
/* eslint-enable indent */
export default {
serLazyImage: setLazyImage,
setLazyImage: setLazyImage,
fillImages: fillImages,
fillImage: fillImage,
lazyImage: lazyImage,

View file

@ -4,8 +4,6 @@ import connectionManager from 'connectionManager';
import itemHelper from 'itemHelper';
import appRouter from 'appRouter';
import playbackManager from 'playbackManager';
import loading from 'loading';
import appSettings from 'appSettings';
import browser from 'browser';
import actionsheet from 'actionsheet';
@ -144,7 +142,6 @@ import actionsheet from 'actionsheet';
}
if (item.CanDelete && options.deleteItem !== false) {
if (item.Type === 'Playlist' || item.Type === 'BoxSet') {
commands.push({
name: globalize.translate('Delete'),
@ -355,7 +352,7 @@ import actionsheet from 'actionsheet';
});
break;
case 'download':
import('fileDownloader').then(({default: fileDownloader}) => {
import('fileDownloader').then((fileDownloader) => {
const downloadHref = apiClient.getItemDownloadUrl(itemId);
fileDownloader.download([{
url: downloadHref,

View file

@ -1,8 +1,7 @@
define(['apphost', 'globalize'], function (appHost, globalize) {
'use strict';
function getDisplayName(item, options = {}) {
import appHost from 'apphost';
import globalize from 'globalize';
export function getDisplayName(item, options = {}) {
if (!item) {
throw new Error('null item passed into getDisplayName');
}
@ -11,7 +10,7 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
item = item.ProgramInfo || item;
}
var name = ((item.Type === 'Program' || item.Type === 'Recording') && (item.IsSeries || item.EpisodeTitle) ? item.EpisodeTitle : item.Name) || '';
let name = ((item.Type === 'Program' || item.Type === 'Recording') && (item.IsSeries || item.EpisodeTitle) ? item.EpisodeTitle : item.Name) || '';
if (item.Type === 'TvChannel') {
if (item.ChannelNumber) {
@ -22,11 +21,10 @@ 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) {
let displayIndexNumber = item.IndexNumber;
var displayIndexNumber = item.IndexNumber;
var number = displayIndexNumber;
var nameSeparator = ' - ';
let number = displayIndexNumber;
let nameSeparator = ' - ';
if (options.includeParentInfo !== false) {
number = 'S' + item.ParentIndexNumber + ':E' + number;
@ -35,7 +33,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
}
if (item.IndexNumberEnd) {
displayIndexNumber = item.IndexNumberEnd;
number += '-' + displayIndexNumber;
}
@ -48,9 +45,8 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
return name;
}
function supportsAddingToCollection(item) {
var invalidTypes = ['Genre', 'MusicGenre', 'Studio', 'UserView', 'CollectionFolder', 'Audio', 'Program', 'Timer', 'SeriesTimer'];
export function supportsAddingToCollection(item) {
const invalidTypes = ['Genre', 'MusicGenre', 'Studio', 'UserView', 'CollectionFolder', 'Audio', 'Program', 'Timer', 'SeriesTimer'];
if (item.Type === 'Recording') {
if (item.Status !== 'Completed') {
@ -61,8 +57,7 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
return !item.CollectionType && invalidTypes.indexOf(item.Type) === -1 && item.MediaType !== 'Photo' && !isLocalItem(item);
}
function supportsAddingToPlaylist(item) {
export function supportsAddingToPlaylist(item) {
if (item.Type === 'Program') {
return false;
}
@ -95,9 +90,8 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
return item.MediaType || item.IsFolder || item.Type === 'Genre' || item.Type === 'MusicGenre' || item.Type === 'MusicArtist';
}
function canEdit(user, item) {
var itemType = item.Type;
export function canEdit(user, item) {
const itemType = item.Type;
if (itemType === 'UserRootFolder' || itemType === 'UserView') {
return false;
@ -128,8 +122,7 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
return user.Policy.IsAdministrator;
}
function isLocalItem(item) {
export function isLocalItem(item) {
if (item && item.Id && item.Id.indexOf('local') === 0) {
return true;
}
@ -137,15 +130,8 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
return false;
}
return {
getDisplayName: getDisplayName,
supportsAddingToCollection: supportsAddingToCollection,
supportsAddingToPlaylist: supportsAddingToPlaylist,
isLocalItem: isLocalItem,
canIdentify: function (user, item) {
var itemType = item.Type;
export function canIdentify (user, item) {
const itemType = item.Type;
if (itemType === 'Movie' ||
itemType === 'Trailer' ||
@ -156,9 +142,7 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
itemType === 'MusicAlbum' ||
itemType === 'MusicArtist' ||
itemType === 'MusicVideo') {
if (user.Policy.IsAdministrator) {
if (!isLocalItem(item)) {
return true;
}
@ -166,13 +150,10 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
}
return false;
},
}
canEdit: canEdit,
canEditImages: function (user, item) {
var itemType = item.Type;
export function canEditImages (user, item) {
const itemType = item.Type;
if (item.MediaType === 'Photo') {
return false;
@ -180,7 +161,6 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
if (itemType === 'UserView') {
if (user.Policy.IsAdministrator) {
return true;
}
@ -194,10 +174,9 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
}
return itemType !== 'Timer' && itemType !== 'SeriesTimer' && canEdit(user, item) && !isLocalItem(item);
},
canSync: function (user, item) {
}
export function canSync (user, item) {
if (user && !user.Policy.EnableContentDownloading) {
return false;
}
@ -207,10 +186,9 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
}
return item.SupportsSync;
},
canShare: function (item, user) {
}
export function canShare (item, user) {
if (item.Type === 'Program') {
return false;
}
@ -232,14 +210,13 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
return false;
}
return user.Policy.EnablePublicSharing && appHost.supports('sharing');
},
}
enableDateAddedDisplay: function (item) {
export function enableDateAddedDisplay (item) {
return !item.IsFolder && item.MediaType && item.Type !== 'Program' && item.Type !== 'TvChannel' && item.Type !== 'Trailer';
},
canMarkPlayed: function (item) {
}
export function canMarkPlayed (item) {
if (item.Type === 'Program') {
return false;
}
@ -266,10 +243,9 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
}
return false;
},
canRate: function (item) {
}
export function canRate (item) {
if (item.Type === 'Program'
|| item.Type === 'Timer'
|| item.Type === 'SeriesTimer'
@ -281,10 +257,9 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
}
return true;
},
canConvert: function (item, user) {
}
export function canConvert (item, user) {
if (!user.Policy.EnableMediaConversion) {
return false;
}
@ -293,17 +268,17 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
return false;
}
var mediaType = item.MediaType;
const mediaType = item.MediaType;
if (mediaType === 'Book' || mediaType === 'Photo' || mediaType === 'Audio') {
return false;
}
var collectionType = item.CollectionType;
const collectionType = item.CollectionType;
if (collectionType === 'livetv') {
return false;
}
var type = item.Type;
const type = item.Type;
if (type === 'Channel' || type === 'Person' || type === 'Year' || type === 'Program' || type === 'Timer' || type === 'SeriesTimer') {
return false;
}
@ -317,19 +292,16 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
}
return true;
},
canRefreshMetadata: function (item, user) {
}
export function canRefreshMetadata (item, user) {
if (user.Policy.IsAdministrator) {
var collectionType = item.CollectionType;
const 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;
}
@ -337,10 +309,9 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
}
return false;
},
supportsMediaSourceSelection: function (item) {
}
export function supportsMediaSourceSelection (item) {
if (item.MediaType !== 'Video') {
return false;
}
@ -359,5 +330,21 @@ define(['apphost', 'globalize'], function (appHost, globalize) {
return true;
}
export default {
getDisplayName: getDisplayName,
supportsAddingToCollection: supportsAddingToCollection,
supportsAddingToPlaylist: supportsAddingToPlaylist,
isLocalItem: isLocalItem,
canIdentify: canIdentify,
canEdit: canEdit,
canEditImages: canEditImages,
canSync: canSync,
canShare: canShare,
enableDateAddedDisplay: enableDateAddedDisplay,
canMarkPlayed: canMarkPlayed,
canRate: canRate,
canConvert: canConvert,
canRefreshMetadata: canRefreshMetadata,
supportsMediaSourceSelection: supportsMediaSourceSelection
};
});

View file

@ -35,7 +35,6 @@ import 'cardStyle';
}
function searchForIdentificationResults(page) {
let lookupInfo = {
ProviderIds: {}
};
@ -45,11 +44,9 @@ import 'cardStyle';
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);
}
@ -62,7 +59,6 @@ import 'cardStyle';
const txtLookupId = page.querySelectorAll('.txtLookupId');
for (i = 0, length = txtLookupId.length; i < length; i++) {
value = txtLookupId[i].value;
if (value) {
@ -100,14 +96,12 @@ import 'cardStyle';
dataType: 'json'
}).then(results => {
loading.hide();
showIdentificationSearchResults(page, results);
});
}
function showIdentificationSearchResults(page, results) {
const identificationSearchResults = page.querySelector('.identificationSearchResults');
page.querySelector('.popupIdentifyForm').classList.add('hide');
@ -119,7 +113,6 @@ import 'cardStyle';
let i;
let length;
for (i = 0, length = results.length; i < length; i++) {
const result = results[i];
html += getSearchResultHtml(result, i);
}
@ -133,17 +126,14 @@ import 'cardStyle';
const currentResult = results[index];
if (currentItem != null) {
showIdentifyOptions(page, currentResult);
} else {
finishFindNewDialog(page, currentResult);
}
}
const searchImages = elem.querySelectorAll('.card');
for (i = 0, length = searchImages.length; i < length; i++) {
searchImages[i].addEventListener('click', onSearchImageClick);
}
@ -161,7 +151,6 @@ import 'cardStyle';
}
function showIdentifyOptions(page, identifyResult) {
const identifyOptionsForm = page.querySelector('.identifyOptionsForm');
page.querySelector('.popupIdentifyForm').classList.add('hide');
@ -193,7 +182,6 @@ import 'cardStyle';
}
function getSearchResultHtml(result, index) {
// TODO move card creation code to Card component
let html = '';
@ -234,7 +222,6 @@ import 'cardStyle';
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>';
@ -257,7 +244,6 @@ import 'cardStyle';
}
for (let i = 0; i < numLines; i++) {
if (i === 0) {
html += '<div class="cardText cardText-first cardTextCentered">';
} else {
@ -279,7 +265,6 @@ import 'cardStyle';
}
function submitIdentficationResult(page) {
loading.show();
const options = {
@ -295,14 +280,11 @@ import 'cardStyle';
contentType: 'application/json'
}).then(() => {
hasChanges = true;
loading.hide();
dialogHelper.close(page);
}, () => {
loading.hide();
dialogHelper.close(page);
@ -310,15 +292,12 @@ import 'cardStyle';
}
function showIdentificationForm(page, item) {
const apiClient = getApiClient();
apiClient.getJSON(apiClient.getUrl(`Items/${item.Id}/ExternalIdInfos`)).then(idList => {
let html = '';
for (let i = 0, length = idList.length; i < length; i++) {
const idInfo = idList[i];
const id = `txtLookup${idInfo.Key}`;
@ -340,11 +319,9 @@ import 'cardStyle';
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 = '';
}
@ -356,15 +333,12 @@ import 'cardStyle';
}
function showEditor(itemId) {
loading.show();
return import('text!./itemidentifier.template.html').then(({default: template}) => {
const apiClient = getApiClient();
apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(item => {
currentItem = item;
currentItemType = currentItem.Type;
@ -406,21 +380,18 @@ import 'cardStyle';
dialogHelper.open(dlg);
dlg.querySelector('.popupIdentifyForm').addEventListener('submit', e => {
e.preventDefault();
searchForIdentificationResults(dlg);
return false;
});
dlg.querySelector('.identifyOptionsForm').addEventListener('submit', e => {
e.preventDefault();
submitIdentficationResult(dlg);
return false;
});
dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg);
});
@ -433,7 +404,6 @@ import 'cardStyle';
}
function onDialogClosed() {
loading.hide();
if (hasChanges) {
currentResolve();
@ -444,12 +414,10 @@ import 'cardStyle';
// TODO investigate where this was used
function showEditorFindNew(itemName, itemYear, itemType, resolveFunc) {
currentItem = null;
currentItemType = itemType;
return import('text!./itemidentifier.template.html').then(({default: template}) => {
const dialogOptions = {
size: 'small',
removeOnClose: true,
@ -477,19 +445,16 @@ import 'cardStyle';
dialogHelper.open(dlg);
dlg.querySelector('.btnCancel').addEventListener('click', () => {
dialogHelper.close(dlg);
});
dlg.querySelector('.popupIdentifyForm').addEventListener('submit', e => {
e.preventDefault();
searchForIdentificationResults(dlg);
return false;
});
dlg.addEventListener('close', () => {
loading.hide();
const foundItem = hasChanges ? currentSearchResult : null;
@ -503,16 +468,12 @@ import 'cardStyle';
}
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;
}
@ -521,9 +482,7 @@ import 'cardStyle';
}
export function show(itemId, serverId) {
return new Promise((resolve, reject) => {
currentResolve = resolve;
currentReject = reject;
currentServerId = serverId;
@ -534,9 +493,7 @@ import 'cardStyle';
}
export function showFindNew(itemName, itemYear, itemType, serverId) {
return new Promise((resolve) => {
currentServerId = serverId;
hasChanges = false;

View file

@ -2,25 +2,22 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
'use strict';
serverNotifications = serverNotifications.default || serverNotifications;
playbackManager = playbackManager.default || playbackManager;
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) {
@ -31,21 +28,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;
}
@ -55,28 +48,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;
}
@ -103,23 +91,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;
}
@ -127,7 +110,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);
@ -135,7 +117,6 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
}
function removeNotificationEvent(instance, name, owner) {
var handler = instance['event_' + name];
if (handler) {
owner = owner || serverNotifications;
@ -145,7 +126,6 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
}
function ItemsRefresher(options) {
this.options = options || {};
addNotificationEvent(this, 'UserDataChanged', onUserDataChanged);
@ -158,24 +138,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;
@ -190,7 +165,6 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
};
ItemsRefresher.prototype.refreshItems = function () {
if (!this.fetchData) {
return Promise.resolve();
}
@ -206,7 +180,6 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
};
ItemsRefresher.prototype.notifyRefreshNeeded = function (isInForeground) {
if (this.paused) {
this.needsRefresh = true;
return;
@ -225,9 +198,7 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
};
function clearRefreshInterval(instance, isPausing) {
if (instance.refreshInterval) {
clearInterval(instance.refreshInterval);
instance.refreshInterval = null;
@ -238,7 +209,6 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
}
function resetRefreshInterval(instance, intervalMs) {
clearRefreshInterval(instance);
if (!intervalMs) {
@ -255,7 +225,6 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
}
function onDataFetched(result) {
resetRefreshInterval(this);
if (this.afterRefresh) {
@ -264,7 +233,6 @@ define(['playbackManager', 'serverNotifications', 'events'], function (playbackM
}
ItemsRefresher.prototype.destroy = function () {
clearRefreshInterval(this);
removeNotificationEvent(this, 'UserDataChanged');

View file

@ -1,6 +1,8 @@
define(['browser', 'appSettings', 'events'], function (browser, appSettings, events) {
'use strict';
browser = browser.default || browser;
function setLayout(instance, layout, selectedLayout) {
if (layout === selectedLayout) {
instance[layout] = true;
@ -16,7 +18,6 @@ define(['browser', 'appSettings', 'events'], function (browser, appSettings, eve
}
LayoutManager.prototype.setLayout = function (layout, save) {
if (!layout || layout === 'auto') {
this.autoLayout();
@ -41,7 +42,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);

View file

@ -219,7 +219,7 @@ import 'emby-input';
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>';
const supportedImageTypes = availableTypeOptions.SupportedImageTypes || [];
if (supportedImageTypes.length > 1 || 1 === supportedImageTypes.length && 'Primary' !== supportedImageTypes[0]) {
if (supportedImageTypes.length > 1 || supportedImageTypes.length === 1 && supportedImageTypes[0] !== 'Primary') {
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>';
@ -362,7 +362,7 @@ import 'emby-input';
TypeOptions: []
};
currentAvailableOptions = null;
const isNewLibrary = null === libraryOptions;
const isNewLibrary = libraryOptions === null;
isNewLibrary && parent.classList.add('newlibrary');
const response = await fetch('components/libraryoptionseditor/libraryoptionseditor.template.html');
const template = await response.text();
@ -578,7 +578,7 @@ import 'emby-input';
parent.querySelector('#chkSkipIfAudioTrackPresent').checked = options.SkipSubtitlesIfAudioTrackMatches;
parent.querySelector('#chkRequirePerfectMatch').checked = options.RequirePerfectSubtitleMatch;
Array.prototype.forEach.call(parent.querySelectorAll('.chkMetadataSaver'), elem => {
elem.checked = options.MetadataSavers ? options.MetadataSavers.includes(elem.getAttribute('data-pluginname')) : 'true' === elem.getAttribute('data-defaultenabled');
elem.checked = options.MetadataSavers ? options.MetadataSavers.includes(elem.getAttribute('data-pluginname')) : elem.getAttribute('data-defaultenabled') === 'true';
});
Array.prototype.forEach.call(parent.querySelectorAll('.chkSubtitleLanguage'), elem => {
elem.checked = !!options.SubtitleDownloadLanguages && options.SubtitleDownloadLanguages.includes(elem.getAttribute('data-lang'));

View file

@ -18,9 +18,7 @@ import 'emby-ratingbutton';
import 'emby-playstatebutton';
function getIndex(item, options) {
if (options.index === 'disc') {
return item.ParentIndexNumber == null ? '' : globalize.translate('ValueDiscNumber', item.ParentIndexNumber);
}
@ -29,7 +27,6 @@ import 'emby-playstatebutton';
let name;
if (sortBy.indexOf('sortname') === 0) {
if (item.Type === 'Episode') {
return '';
}
@ -45,11 +42,9 @@ import 'emby-playstatebutton';
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');
}
@ -57,7 +52,6 @@ import 'emby-playstatebutton';
return Math.floor(item.CommunityRating);
}
if (sortBy.indexOf('criticrating') === 0) {
if (item.CriticRating == null) {
return globalize.translate('Unrated');
}
@ -65,7 +59,6 @@ import 'emby-playstatebutton';
return Math.floor(item.CriticRating);
}
if (sortBy.indexOf('albumartist') === 0) {
// SortName
if (!item.AlbumArtist) {
return '';
@ -84,12 +77,11 @@ import 'emby-playstatebutton';
}
function getImageUrl(item, width) {
const apiClient = connectionManager.getApiClient(item.ServerId);
let itemId;
const options = {
maxWidth: width * 2,
maxWidth: width,
type: 'Primary'
};
@ -114,10 +106,9 @@ import 'emby-playstatebutton';
}
function getChannelImageUrl(item, width) {
const apiClient = connectionManager.getApiClient(item.ServerId);
const options = {
maxWidth: width * 2,
maxWidth: width,
type: 'Primary'
};
@ -161,11 +152,9 @@ import 'emby-playstatebutton';
}
function getRightButtonsHtml(options) {
let html = '';
for (let i = 0, length = options.rightButtons.length; i < length; i++) {
const 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>`;
@ -179,7 +168,6 @@ import 'emby-playstatebutton';
}
export function getListViewHtml(options) {
const items = options.items;
let groupTitle = '';
@ -198,17 +186,14 @@ import 'emby-playstatebutton';
const containerAlbumArtistIds = (options.containerAlbumArtists || []).map(getId);
for (let i = 0, length = items.length; i < length; i++) {
const item = items[i];
let html = '';
if (options.showIndex) {
const itemGroupTitle = getIndex(item, options);
if (itemGroupTitle !== groupTitle) {
if (html) {
html += '</div>';
}
@ -258,20 +243,16 @@ import 'emby-playstatebutton';
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}>`;
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>';
}
@ -319,7 +300,6 @@ import 'emby-playstatebutton';
}
if (options.showIndexNumberLeft) {
html += '<div class="listItem-indexnumberleft">';
html += (item.IndexNumber || '&nbsp;');
html += '</div>';
@ -367,9 +347,7 @@ import 'emby-playstatebutton';
}
if (options.showParentTitle && options.parentTitleWithTitle) {
if (displayName) {
if (parentTitle) {
parentTitle += ' - ';
}
@ -387,18 +365,15 @@ import 'emby-playstatebutton';
if (item.IsFolder) {
if (options.artist !== false) {
if (item.AlbumArtist && item.Type === 'MusicAlbum') {
textlines.push(item.AlbumArtist);
}
}
} else {
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.includes(artistItems[0].Id)) {
@ -407,7 +382,6 @@ import 'emby-playstatebutton';
}
if (showArtist) {
if (artistItems && item.Type !== 'MusicAlbum') {
textlines.push(artistItems.map(a => {
return a.Name;
@ -417,7 +391,6 @@ import 'emby-playstatebutton';
}
if (item.Type === 'TvChannel') {
if (item.CurrentProgram) {
textlines.push(itemHelper.getDisplayName(item.CurrentProgram));
}
@ -438,7 +411,6 @@ import 'emby-playstatebutton';
if (options.mediaInfo !== false) {
if (!enableSideMediaInfo) {
const mediaInfoClass = 'secondary listItemMediaInfo listItemBodyText';
html += `<div class="${mediaInfoClass}">`;
@ -483,7 +455,6 @@ import 'emby-playstatebutton';
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>';
}
@ -497,7 +468,6 @@ import 'emby-playstatebutton';
}
if (options.enableUserDataButtons !== false) {
const userData = item.UserData || {};
const likes = userData.Likes == null ? '' : userData.Likes;

View file

@ -1,20 +1,17 @@
define(['css!./loading'], function () {
'use strict';
import 'css!./loading';
var loadingElem;
var layer1;
var layer2;
var layer3;
var layer4;
var circleLefts;
var circleRights;
let loadingElem;
let layer1;
let layer2;
let layer3;
let layer4;
let circleLefts;
let circleRights;
return {
show: function () {
var elem = loadingElem;
export function show() {
let elem = loadingElem;
if (!elem) {
elem = document.createElement('div');
loadingElem = elem;
@ -41,22 +38,19 @@ define(['css!./loading'], function () {
layer3.classList.add('mdl-spinner__layer-3-active');
layer4.classList.add('mdl-spinner__layer-4-active');
var i;
var length;
for (i = 0, length = circleLefts.length; i < length; i++) {
for (let i = 0, length = circleLefts.length; i < length; i++) {
circleLefts[i].classList.add('mdl-spinner__circleLeft-active');
}
for (i = 0, length = circleRights.length; i < length; i++) {
for (let i = 0, length = circleRights.length; i < length; i++) {
circleRights[i].classList.add('mdl-spinner__circleRight-active');
}
},
hide: function () {
var elem = loadingElem;
}
export function hide() {
const elem = loadingElem;
if (elem) {
elem.classList.remove('mdlSpinnerActive');
elem.classList.remove('mdl-spinner__layer-1-active');
@ -64,17 +58,17 @@ define(['css!./loading'], function () {
elem.classList.remove('mdl-spinner__layer-3-active');
elem.classList.remove('mdl-spinner__layer-4-active');
var i;
var length;
for (i = 0, length = circleLefts.length; i < length; i++) {
for (let i = 0, length = circleLefts.length; i < length; i++) {
circleLefts[i].classList.remove('mdl-spinner__circleLeft-active');
}
for (i = 0, length = circleRights.length; i < length; i++) {
for (let i = 0, length = circleRights.length; i < length; i++) {
circleRights[i].classList.remove('mdl-spinner__circleRight-active');
}
}
}
export default {
show: show,
hide: hide
};
});

View file

@ -8,29 +8,10 @@ import 'emby-button';
let tabOwnerView;
const queryScope = document.querySelector('.skinHeader');
let footerTabsContainer;
let headerTabsContainer;
let tabsElem;
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);
}
}
function ensureElements() {
if (!headerTabsContainer) {
headerTabsContainer = queryScope.querySelector('.headerTabs');
}
@ -42,9 +23,7 @@ import 'emby-button';
}
function allowSwipe(target) {
function allowSwipeOn(elem) {
if (dom.parentWithTag(elem, 'input')) {
return false;
}
@ -69,13 +48,11 @@ import 'emby-button';
}
function configureSwipeTabs(view, tabsElem, getTabContainersFn) {
if (!browser.touch) {
return;
}
// implement without hammer
const pageCount = getTabContainersFn().length;
const onSwipeLeft = function (e, target) {
if (allowSwipe(target) && view.contains(target)) {
tabsElem.selectNext();
@ -89,7 +66,6 @@ import 'emby-button';
};
import('touchHelper').then(({default: TouchHelper}) => {
const touchHelper = new TouchHelper(view.parentNode.parentNode);
events.on(touchHelper, 'swipeleft', onSwipeLeft);
@ -102,28 +78,19 @@ import 'emby-button';
}
export function setTabs(view, selectedIndex, getTabsFn, getTabContainersFn, onBeforeTabChange, onTabChange, setSelectedIndex) {
const enableInFooter = enableTabsInFooter();
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 {
@ -132,21 +99,19 @@ import 'emby-button';
};
}
ensureElements(enableInFooter);
ensureElements();
const tabsContainerElem = enableInFooter ? footerTabsContainer : headerTabsContainer;
const tabsContainerElem = headerTabsContainer;
if (!tabOwnerView) {
tabsContainerElem.classList.remove('hide');
}
if (tabOwnerView !== view) {
let index = 0;
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) {
@ -167,7 +132,6 @@ import 'emby-button';
index++;
return tabHtml;
}).join('') + '</div></div>';
tabsContainerElem.innerHTML = tabsHtml;
@ -181,10 +145,8 @@ import 'emby-button';
configureSwipeTabs(view, tabsElem, getTabContainersFn);
tabsElem.addEventListener('beforetabchange', function (e) {
const tabContainers = getTabContainersFn();
if (e.detail.previousIndex != null) {
const previousPanel = tabContainers[e.detail.previousIndex];
if (previousPanel) {
previousPanel.classList.remove('is-active');
@ -193,12 +155,6 @@ import 'emby-button';
const 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);
// }
//}
if (newPanel) {
newPanel.classList.add('is-active');
}
@ -215,16 +171,11 @@ import 'emby-button';
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"]'),
@ -247,7 +198,6 @@ import 'emby-button';
}
export function selectedTabIndex(index) {
const tabsContainerElem = headerTabsContainer;
if (!tabsElem) {

View file

@ -85,7 +85,7 @@ import 'flexStyles';
refreshLibraryFromServer(dom.parentWithClass(button, 'dlg-libraryeditor'));
}, () => {
import('toast').then(({default: toast}) => {
toast(globalize.translate('DefaultErrorMessage'));
toast(globalize.translate('ErrorDefault'));
});
});
});
@ -98,8 +98,8 @@ import 'flexStyles';
if (listItem) {
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 pathInfo = index == null ? {} : pathInfos[index] || {};
const originalPath = pathInfo.Path || (index == null ? null : currentOptions.library.Locations[index]);
const btnRemovePath = dom.parentWithClass(e.target, 'btnRemovePath');
if (btnRemovePath) {
@ -171,7 +171,7 @@ import 'flexStyles';
const picker = new directoryBrowser();
picker.show({
enableNetworkSharePath: true,
pathReadOnly: null != originalPath,
pathReadOnly: originalPath != null,
path: originalPath,
networkSharePath: networkPath,
callback: function (path, networkSharePath) {

View file

@ -11,23 +11,19 @@ import 'emby-button';
/* eslint-disable indent */
function getTimerIndicator(item) {
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>';
}
@ -46,9 +42,7 @@ import 'emby-button';
let date;
if (item.StartDate && options.programTime !== false) {
try {
text = '';
date = datetime.parseISO8601Date(item.StartDate);
@ -75,7 +69,6 @@ import 'emby-button';
}
if (item.ChannelName) {
if (options.interactive && item.ChannelId) {
miscInfo.push({
html: `<a is="emby-linkbutton" class="button-flat mediaInfoItem" href="${appRouter.getRouteUrl({
@ -121,11 +114,9 @@ import 'emby-button';
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));
}
@ -133,19 +124,15 @@ import 'emby-button';
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);
@ -159,7 +146,6 @@ import 'emby-button';
if (item.Type === 'SeriesTimer') {
if (item.RecordAnyTime) {
miscInfo.push(globalize.translate('Anytime'));
} else {
miscInfo.push(datetime.getDisplayTime(item.StartDate));
@ -173,7 +159,6 @@ import 'emby-button';
}
if (item.StartDate && item.Type !== 'Program' && item.Type !== 'SeriesTimer') {
try {
date = datetime.parseISO8601Date(item.StartDate);
@ -190,24 +175,18 @@ import 'emby-button';
}
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 {
const endYear = datetime.parseISO8601Date(item.EndDate).getFullYear();
if (endYear !== item.ProductionYear) {
text += `-${datetime.parseISO8601Date(item.EndDate).getFullYear()}`;
}
} catch (e) {
console.error('error parsing date:', item.EndDate);
}
@ -218,7 +197,6 @@ import 'emby-button';
}
if (item.Type === 'Program') {
if (options.programIndicator !== false) {
if (item.IsLive) {
miscInfo.push({
@ -240,7 +218,6 @@ import 'emby-button';
}
if ((item.IsSeries || item.EpisodeTitle) && options.episodeTitle !== false) {
text = itemHelper.getDisplayName(item, {
includeIndexNumber: options.episodeTitleIndexNumber
});
@ -251,7 +228,6 @@ import 'emby-button';
} 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));
@ -266,12 +242,9 @@ import 'emby-button';
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);
@ -283,11 +256,8 @@ import 'emby-button';
}
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;
@ -327,7 +297,6 @@ import 'emby-button';
}
if (item.CriticRating && options.criticRating !== false) {
if (item.CriticRating >= 60) {
html += `<div class="mediaInfoItem mediaInfoCriticRating mediaInfoCriticRatingFresh">${item.CriticRating}</div>`;
} else {
@ -336,7 +305,6 @@ import 'emby-button';
}
if (options.endsAt !== false) {
const endsAt = getEndsAt(item);
if (endsAt) {
html += getMediaInfoItem(endsAt, 'endsAt');
@ -349,9 +317,7 @@ import 'emby-button';
}
export function getEndsAt(item) {
if (item.MediaType === 'Video' && item.RunTimeTicks) {
if (!item.StartDate) {
let endDate = new Date().getTime() + (item.RunTimeTicks / 10000);
endDate = new Date(endDate);
@ -365,7 +331,6 @@ import 'emby-button';
}
export function getEndsAtFromPosition(runtimeTicks, positionTicks, includeText) {
let endDate = new Date().getTime() + ((runtimeTicks - (positionTicks || 0)) / 10000);
endDate = new Date(endDate);
@ -378,12 +343,10 @@ import 'emby-button';
}
function getMediaInfoItem(m, cssClass) {
cssClass = cssClass ? (`${cssClass} mediaInfoItem`) : 'mediaInfoItem';
let mediaInfoText = m;
if (typeof (m) !== 'string' && typeof (m) !== 'number') {
if (m.html) {
return m.html;
}
@ -408,17 +371,13 @@ import 'emby-button';
}
function dynamicEndTime(elem, item) {
const interval = setInterval(() => {
if (!document.body.contains(elem)) {
clearInterval(interval);
return;
}
elem.innerHTML = getEndsAt(item);
}, 60000);
}
@ -437,7 +396,6 @@ import 'emby-button';
}
function afterFill(elem, item, options) {
if (options.endsAt !== false) {
const endsAtElem = elem.querySelector('.endsAt');
if (endsAtElem) {
@ -452,7 +410,6 @@ import 'emby-button';
}
function onChannelLinkClick(e) {
const channelId = this.getAttribute('data-id');
const serverId = this.getAttribute('data-serverid');
@ -463,7 +420,6 @@ import 'emby-button';
}
export function getPrimaryMediaInfoHtml(item, options) {
options = options || {};
if (options.interactive == null) {
options.interactive = false;
@ -473,7 +429,6 @@ import 'emby-button';
}
export function getSecondaryMediaInfoHtml(item, options) {
options = options || {};
if (options.interactive == null) {
options.interactive = false;
@ -486,12 +441,10 @@ import 'emby-button';
}
export function getResolutionText(i) {
const width = i.Width;
const height = i.Height;
if (width && height) {
if (width >= 3800 || height >= 2000) {
return '4K';
}
@ -514,19 +467,16 @@ import 'emby-button';
return '720p';
}
if (width >= 700 || height >= 400) {
if (i.IsInterlaced) {
return '480i';
}
return '480p';
}
}
return null;
}
function getAudioStreamForDisplay(item) {
if (!item.MediaSources) {
return null;
}
@ -542,7 +492,6 @@ import 'emby-button';
}
export function getMediaInfoStats(item, options) {
options = options || {};
const list = [];
@ -568,10 +517,6 @@ import 'emby-button';
});
}
//if (mediaSource.Container) {
// html += '<div class="mediaInfoIcon mediaInfoText">' + mediaSource.Container + '</div>';
//}
const resolutionText = getResolutionText(videoStream);
if (resolutionText) {
list.push({
@ -591,19 +536,12 @@ import 'emby-button';
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';
}
@ -629,7 +567,6 @@ import 'emby-button';
}
if (item.DateCreated && itemHelper.enableDateAddedDisplay(item)) {
const dateCreated = datetime.parseISO8601Date(item.DateCreated);
list.push({

View file

@ -1,4 +1,3 @@
import itemHelper from 'itemHelper';
import dom from 'dom';
import layoutManager from 'layoutManager';
import dialogHelper from 'dialogHelper';
@ -31,16 +30,13 @@ import 'flexStyles';
}
function closeDialog(isSubmitted) {
if (isDialog()) {
dialogHelper.close(currentContext);
}
}
function submitUpdatedItem(form, item) {
function afterContentTypeUpdated() {
require(['toast'], function (toast) {
toast(globalize.translate('MessageItemSaved'));
});
@ -52,11 +48,9 @@ import 'flexStyles';
const apiClient = getApiClient();
apiClient.updateItem(item).then(function () {
const newContentType = form.querySelector('#selectContentType').value || '';
if ((metadataEditorInfo.ContentType || '') !== newContentType) {
apiClient.ajax({
url: apiClient.getUrl('Items/' + item.Id + '/ContentType', {
@ -68,11 +62,9 @@ import 'flexStyles';
}).then(function () {
afterContentTypeUpdated();
});
} else {
afterContentTypeUpdated();
}
});
}
@ -84,13 +76,9 @@ import 'flexStyles';
}
function getAlbumArtists(form) {
return form.querySelector('#txtAlbumArtist').value.trim().split(';').filter(function (s) {
return s.length > 0;
}).map(function (a) {
return {
Name: a
};
@ -98,13 +86,9 @@ import 'flexStyles';
}
function getArtists(form) {
return form.querySelector('#txtArtist').value.trim().split(';').filter(function (s) {
return s.length > 0;
}).map(function (a) {
return {
Name: a
};
@ -112,7 +96,6 @@ import 'flexStyles';
}
function getDateValue(form, element, property) {
let val = form.querySelector(element).value;
if (!val) {
@ -120,14 +103,12 @@ import 'flexStyles';
}
if (currentItem[property]) {
const date = datetime.parseISO8601Date(currentItem[property], true);
const parts = date.toISOString().split('T');
// If the date is the same, preserve the time
if (parts[0].indexOf(val) === 0) {
const iso = parts[1];
val += 'T' + iso;
@ -138,7 +119,6 @@ import 'flexStyles';
}
function onSubmit(e) {
loading.show();
const form = this;
@ -199,14 +179,12 @@ import 'flexStyles';
item.PreferredMetadataCountryCode = form.querySelector('#selectCountry').value;
if (currentItem.Type === 'Person') {
const placeOfBirth = form.querySelector('#txtPlaceOfBirth').value;
item.ProductionLocations = placeOfBirth ? [placeOfBirth] : [];
}
if (currentItem.Type === 'Series') {
// 600000000
const seriesRuntime = form.querySelector('#txtSeriesRuntime').value;
item.RunTimeTicks = seriesRuntime ? (seriesRuntime * 600000000) : null;
@ -249,11 +227,8 @@ import 'flexStyles';
}
function editPerson(context, person, index) {
require(['personEditor'], function (personEditor) {
personEditor.show(person).then(function (updatedPerson) {
const isNew = index === -1;
if (isNew) {
@ -303,7 +278,6 @@ import 'flexStyles';
}
function onEditorClick(e) {
const btnRemoveFromEditorList = dom.parentWithClass(e.target, 'btnRemoveFromEditorList');
if (btnRemoveFromEditorList) {
removeElementFromList(btnRemoveFromEditorList);
@ -376,12 +350,10 @@ import 'flexStyles';
form.addEventListener('submit', onSubmit);
context.querySelector('#btnAddPerson').addEventListener('click', function (event, data) {
editPerson(context, {}, -1);
});
context.querySelector('#peopleList').addEventListener('click', function (e) {
let index;
const btnDeletePerson = dom.parentWithClass(e.target, 'btnDeletePerson');
if (btnDeletePerson) {
@ -399,7 +371,6 @@ import 'flexStyles';
}
function getItem(itemId, serverId) {
const apiClient = connectionManager.getApiClient(serverId);
if (itemId) {
@ -410,7 +381,6 @@ import 'flexStyles';
}
function getEditorConfig(itemId, serverId) {
const apiClient = connectionManager.getApiClient(serverId);
if (itemId) {
@ -421,13 +391,11 @@ import 'flexStyles';
}
function populateCountries(select, allCountries) {
let html = '';
html += "<option value=''></option>";
for (let i = 0, length = allCountries.length; i < length; i++) {
const culture = allCountries[i];
html += "<option value='" + culture.TwoLetterISORegionName + "'>" + culture.DisplayName + '</option>';
@ -437,13 +405,11 @@ import 'flexStyles';
}
function populateLanguages(select, languages) {
let html = '';
html += "<option value=''></option>";
for (let i = 0, length = languages.length; i < length; i++) {
const culture = languages[i];
html += "<option value='" + culture.TwoLetterISOLanguageName + "'>" + culture.DisplayName + '</option>';
@ -453,7 +419,6 @@ import 'flexStyles';
}
function renderContentTypeOptions(context, metadataInfo) {
if (!metadataInfo.ContentTypeOptions.length) {
hideElement('#fldContentType', context);
} else {
@ -461,9 +426,7 @@ import 'flexStyles';
}
const html = metadataInfo.ContentTypeOptions.map(function (i) {
return '<option value="' + i.Value + '">' + i.Name + '</option>';
}).join('');
const selectEl = context.querySelector('#selectContentType');
@ -472,13 +435,11 @@ import 'flexStyles';
}
function loadExternalIds(context, item, externalIds) {
let html = '';
const providerIds = item.ProviderIds || {};
for (let i = 0, length = externalIds.length; i < length; i++) {
const idInfo = externalIds[i];
const id = 'txt1' + idInfo.Key;
@ -524,7 +485,6 @@ import 'flexStyles';
function hideElement(selector, context, multiple) {
context = context || document;
if (typeof selector === 'string') {
const elements = multiple ? context.querySelectorAll(selector) : [context.querySelector(selector)];
Array.prototype.forEach.call(elements, function (el) {
@ -543,7 +503,6 @@ import 'flexStyles';
function showElement(selector, context, multiple) {
context = context || document;
if (typeof selector === 'string') {
const elements = multiple ? context.querySelectorAll(selector) : [context.querySelector(selector)];
Array.prototype.forEach.call(elements, function (el) {
@ -745,7 +704,6 @@ import 'flexStyles';
}
function fillItemInfo(context, item, parentalRatingOptions) {
let select = context.querySelector('#selectOfficialRating');
populateRatings(parentalRatingOptions, select, item.OfficialRating);
@ -867,7 +825,6 @@ import 'flexStyles';
context.querySelector('#selectCountry').value = item.PreferredMetadataCountryCode || '';
if (item.RunTimeTicks) {
const minutes = item.RunTimeTicks / 600000000;
context.querySelector('#txtSeriesRuntime').value = Math.round(minutes);
@ -877,7 +834,6 @@ import 'flexStyles';
}
function populateRatings(allParentalRatings, select, currentValue) {
let html = '';
html += "<option value=''></option>";
@ -888,7 +844,6 @@ import 'flexStyles';
let currentValueFound = false;
for (let i = 0, length = allParentalRatings.length; i < length; i++) {
rating = allParentalRatings[i];
ratings.push({ Name: rating.Name, Value: rating.Name });
@ -903,7 +858,6 @@ import 'flexStyles';
}
for (let i = 0, length = ratings.length; i < length; i++) {
rating = ratings[i];
html += "<option value='" + rating.Value + "'>" + rating.Name + '</option>';
@ -922,7 +876,6 @@ import 'flexStyles';
}
function populateListView(list, items, sortCallback) {
items = items || [];
if (typeof (sortCallback) === 'undefined') {
items.sort(function (a, b) {
@ -954,14 +907,12 @@ import 'flexStyles';
}
function populatePeople(context, people) {
let lastType = '';
let html = '';
const elem = context.querySelector('#peopleList');
for (let i = 0, length = people.length; i < length; i++) {
const person = people[i];
html += '<div class="listItem">';
@ -991,10 +942,8 @@ import 'flexStyles';
}
function getLockedFieldsHtml(fields, currentFields) {
let html = '';
for (let i = 0; i < fields.length; i++) {
const field = fields[i];
const name = field.name;
const value = field.value || field.name;
@ -1041,11 +990,9 @@ import 'flexStyles';
}
function reload(context, itemId, serverId) {
loading.show();
Promise.all([getItem(itemId, serverId), getEditorConfig(itemId, serverId)]).then(function (responses) {
const item = responses[0];
metadataEditorInfo = responses[1];
@ -1137,7 +1084,6 @@ import 'flexStyles';
embed: function (elem, itemId, serverId) {
return new Promise(function (resolve, reject) {
loading.show();
import('text!./metadataEditor.template.html').then(({default: template}) => {

View file

@ -1,7 +1,6 @@
import dialogHelper from 'dialogHelper';
import layoutManager from 'layoutManager';
import globalize from 'globalize';
import require from 'require';
import 'paper-icon-button-light';
import 'emby-input';
import 'emby-select';
@ -18,9 +17,7 @@ import 'css!./../formdialog';
function show(person) {
return new Promise(function (resolve, reject) {
import('text!./personEditor.template.html').then(({default: template}) => {
const dialogOptions = {
removeOnClose: true,
scrollY: false
@ -54,7 +51,6 @@ import 'css!./../formdialog';
dialogHelper.open(dlg);
dlg.addEventListener('close', function () {
if (layoutManager.tv) {
centerFocus(dlg.querySelector('.formDialogContent'), false, false);
}
@ -67,7 +63,6 @@ import 'css!./../formdialog';
});
dlg.querySelector('.selectPersonType').addEventListener('change', function (e) {
if (this.value === 'Actor') {
dlg.querySelector('.fldRole').classList.remove('hide');
} else {
@ -76,12 +71,10 @@ import 'css!./../formdialog';
});
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;

View file

@ -13,10 +13,8 @@ import 'css!./multiSelect';
let currentSelectionCommandsPanel;
function hideSelections() {
const selectionCommandsPanel = currentSelectionCommandsPanel;
if (selectionCommandsPanel) {
selectionCommandsPanel.parentNode.removeChild(selectionCommandsPanel);
currentSelectionCommandsPanel = null;
@ -24,7 +22,6 @@ import 'css!./multiSelect';
selectedElements = [];
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');
@ -33,13 +30,11 @@ import 'css!./multiSelect';
}
function onItemSelectionPanelClick(e, itemSelectionPanel) {
// toggle the checkbox, if it wasn't clicked on
if (!dom.parentWithClass(e.target, 'chkItemSelect')) {
const chkItemSelect = itemSelectionPanel.querySelector('.chkItemSelect');
if (chkItemSelect) {
if (chkItemSelect.classList.contains('checkedInitial')) {
chkItemSelect.classList.remove('checkedInitial');
} else {
@ -56,11 +51,9 @@ import 'css!./multiSelect';
}
function updateItemSelection(chkItemSelect, selected) {
const id = dom.parentWithAttribute(chkItemSelect, 'data-id').getAttribute('data-id');
if (selected) {
const current = selectedItems.filter(i => {
return i === id;
});
@ -69,7 +62,6 @@ import 'css!./multiSelect';
selectedItems.push(id);
selectedElements.push(chkItemSelect);
}
} else {
selectedItems = selectedItems.filter(i => {
return i !== id;
@ -94,11 +86,9 @@ import 'css!./multiSelect';
}
function showSelection(item, isChecked) {
let itemSelectionPanel = item.querySelector('.itemSelectionPanel');
if (!itemSelectionPanel) {
itemSelectionPanel = document.createElement('div');
itemSelectionPanel.classList.add('itemSelectionPanel');
@ -120,11 +110,9 @@ import 'css!./multiSelect';
}
function showSelectionCommands() {
let selectionCommandsPanel = currentSelectionCommandsPanel;
if (!selectionCommandsPanel) {
selectionCommandsPanel = document.createElement('div');
selectionCommandsPanel.classList.add('selectionCommandsPanel');
@ -150,9 +138,7 @@ import 'css!./multiSelect';
}
function alertText(options) {
return new Promise((resolve, reject) => {
import('alert').then(({default: alert}) => {
alert(options).then(resolve, resolve);
});
@ -160,9 +146,7 @@ import 'css!./multiSelect';
}
function deleteItems(apiClient, itemIds) {
return new Promise((resolve, reject) => {
let msg = globalize.translate('ConfirmDeleteItem');
let title = globalize.translate('HeaderDeleteItem');
@ -172,28 +156,23 @@ import 'css!./multiSelect';
}
import('confirm').then(({default: confirm}) => {
confirm(msg, title).then(() => {
const promises = itemIds.map(itemId => {
apiClient.deleteItem(itemId);
});
Promise.all(promises).then(resolve, () => {
alertText(globalize.translate('ErrorDeletingItem')).then(reject, reject);
});
}, reject);
});
});
}
function showMenuForSelectedItems(e) {
const apiClient = connectionManager.currentApiClient();
apiClient.getCurrentUser().then(user => {
const menuItems = [];
menuItems.push({
@ -317,17 +296,14 @@ import 'css!./multiSelect';
}
}
});
});
});
}
function dispatchNeedsRefresh() {
const elems = [];
[].forEach.call(selectedElements, i => {
const container = dom.parentWithAttribute(i, 'is', 'emby-itemscontainer');
if (container && !elems.includes(container)) {
@ -341,9 +317,7 @@ import 'css!./multiSelect';
}
function combineVersions(apiClient, selection) {
if (selection.length < 2) {
import('alert').then(({default: alert}) => {
alert({
@ -361,7 +335,6 @@ import 'css!./multiSelect';
url: apiClient.getUrl('Videos/MergeVersions', { Ids: selection.join(',') })
}).then(() => {
loading.hide();
hideSelections();
dispatchNeedsRefresh();
@ -369,7 +342,6 @@ import 'css!./multiSelect';
}
function showSelections(initialCard) {
import('emby-checkbox').then(() => {
const cards = document.querySelectorAll('.card');
for (let i = 0, length = cards.length; i < length; i++) {
@ -382,11 +354,9 @@ import 'css!./multiSelect';
}
function onContainerClick(e) {
const target = e.target;
if (selectedItems.length) {
const card = dom.parentWithClass(target, 'card');
if (card) {
const itemSelectionPanel = card.querySelector('.itemSelectionPanel');
@ -404,17 +374,14 @@ import 'css!./multiSelect';
document.addEventListener('viewbeforehide', hideSelections);
export default function (options) {
const self = this;
const container = options.container;
function onTapHold(e) {
const card = dom.parentWithClass(e.target, 'card');
if (card) {
showSelections(card);
}
@ -427,7 +394,6 @@ import 'css!./multiSelect';
}
function getTouches(e) {
return e.changedTouches || e.targetTouches || e.touches;
}
@ -436,7 +402,6 @@ import 'css!./multiSelect';
let touchStartX;
let touchStartY;
function onTouchStart(e) {
const touch = getTouches(e)[0];
touchTarget = null;
touchStartX = 0;
@ -451,7 +416,6 @@ import 'css!./multiSelect';
const card = dom.parentWithClass(element, 'card');
if (card) {
if (touchStartTimeout) {
clearTimeout(touchStartTimeout);
touchStartTimeout = null;
@ -465,7 +429,6 @@ import 'css!./multiSelect';
}
function onTouchMove(e) {
if (touchTarget) {
const touch = getTouches(e)[0];
let deltaX;
@ -487,12 +450,10 @@ import 'css!./multiSelect';
}
function onTouchEnd(e) {
onMouseOut(e);
}
function onMouseDown(e) {
if (touchStartTimeout) {
clearTimeout(touchStartTimeout);
touchStartTimeout = null;
@ -503,7 +464,6 @@ import 'css!./multiSelect';
}
function onMouseOut(e) {
if (touchStartTimeout) {
clearTimeout(touchStartTimeout);
touchStartTimeout = null;
@ -512,7 +472,6 @@ import 'css!./multiSelect';
}
function onTouchStartTimerFired() {
if (!touchTarget) {
return;
}
@ -521,13 +480,11 @@ import 'css!./multiSelect';
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);
@ -565,7 +522,6 @@ import 'css!./multiSelect';
self.onContainerClick = onContainerClick;
self.destroy = () => {
container.removeEventListener('click', onContainerClick);
container.removeEventListener('contextmenu', onTapHold);
@ -580,10 +536,6 @@ import 'css!./multiSelect';
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
});

View file

@ -1,6 +1,7 @@
define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'require'], function (serverNotifications, playbackManager, events, globalize, require) {
'use strict';
playbackManager = playbackManager.default || playbackManager;
serverNotifications = serverNotifications.default || serverNotifications;
function onOneDocumentClick() {
@ -46,7 +47,6 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir
}
function showNonPersistentNotification(title, options, timeoutMs) {
try {
var notif = new Notification(title, options); /* eslint-disable-line compat/compat */
@ -68,7 +68,6 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir
}
function showNotification(options, timeoutMs, apiClient) {
var title = options.title;
options.data = options.data || {};
@ -87,7 +86,6 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir
}
function showNewItemNotification(item, apiClient) {
if (playbackManager.isPlayingLocally(['Video'])) {
return;
}
@ -103,17 +101,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,
@ -125,7 +118,6 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir
}
function onLibraryChanged(data, apiClient) {
var newItems = data.ItemsAdded;
if (!newItems.length) {
@ -149,11 +141,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);
}
});
@ -165,9 +155,7 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir
}
function showPackageInstallNotification(apiClient, installation, status) {
apiClient.getCurrentUser().then(function (user) {
if (!user.Policy.IsAdministrator) {
return;
}
@ -201,7 +189,6 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir
}
if (status === 'progress') {
var percentComplete = Math.round(installation.PercentComplete || 0);
notification.body = percentComplete + '% complete.';
@ -252,7 +239,6 @@ define(['serverNotifications', 'playbackManager', 'events', 'globalize', 'requir
});
events.on(serverNotifications, 'RestartRequired', function (e, apiClient) {
var serverId = apiClient.serverInfo().Id;
var notification = {
tag: 'restart' + serverId,

View file

@ -1,6 +1,4 @@
import require from 'require';
import datetime from 'datetime';
import itemHelper from 'itemHelper';
import events from 'events';
import browser from 'browser';
import imageLoader from 'imageLoader';
@ -39,7 +37,6 @@ import 'emby-ratingbutton';
let isVisibilityAllowed = true;
function getNowPlayingBarHtml() {
let html = '';
html += '<div class="nowPlayingBar hide nowPlayingBar-hidden">';
@ -99,12 +96,10 @@ import 'emby-ratingbutton';
}
function onSlideDownComplete() {
this.classList.add('hide');
}
function slideDown(elem) {
// trigger reflow
void elem.offsetWidth;
@ -116,7 +111,6 @@ import 'emby-ratingbutton';
}
function slideUp(elem) {
dom.removeEventListener(elem, dom.whichTransitionEvent(), onSlideDownComplete, {
once: true
});
@ -134,7 +128,6 @@ import 'emby-ratingbutton';
}
function bindEvents(elem) {
currentTimeElement = elem.querySelector('.nowPlayingBarCurrentTime');
nowPlayingImageElement = elem.querySelector('.nowPlayingImage');
nowPlayingTextElement = elem.querySelector('.nowPlayingBarText');
@ -147,15 +140,12 @@ import 'emby-ratingbutton';
volumeSliderContainer = elem.querySelector('.nowPlayingBarVolumeSliderContainer');
muteButton.addEventListener('click', function () {
if (currentPlayer) {
playbackManager.toggleMute(currentPlayer);
}
});
elem.querySelector('.stopButton').addEventListener('click', function () {
if (currentPlayer) {
playbackManager.stop(currentPlayer);
}
@ -166,7 +156,6 @@ import 'emby-ratingbutton';
});
elem.querySelector('.nextTrackButton').addEventListener('click', function () {
if (currentPlayer) {
playbackManager.nextTrack(currentPlayer);
}
@ -226,18 +215,14 @@ import 'emby-ratingbutton';
});
positionSlider.addEventListener('change', function () {
if (currentPlayer) {
const newPercent = parseFloat(this.value);
playbackManager.seekPercent(newPercent, currentPlayer);
}
});
positionSlider.getBubbleText = function (value) {
const state = lastPlayerState;
if (!state || !state.NowPlayingItem || !currentRuntimeTicks) {
@ -252,7 +237,6 @@ import 'emby-ratingbutton';
};
elem.addEventListener('click', function (e) {
if (!dom.parentWithTag(e.target, ['BUTTON', 'INPUT'])) {
showRemoteControl();
}
@ -260,7 +244,6 @@ import 'emby-ratingbutton';
}
function showRemoteControl() {
import('appRouter').then(({default: appRouter}) => {
appRouter.showNowPlaying();
});
@ -268,7 +251,6 @@ import 'emby-ratingbutton';
let nowPlayingBarElement;
function getNowPlayingBar() {
if (nowPlayingBarElement) {
return Promise.resolve(nowPlayingBarElement);
}
@ -329,7 +311,6 @@ import 'emby-ratingbutton';
}
function updatePlayerStateInternal(event, state, player) {
showNowPlayingBar();
lastPlayerState = state;
@ -417,7 +398,6 @@ import 'emby-ratingbutton';
}
function updatePlayerVolumeState(isMuted, volumeLevel) {
const supportedCommands = currentPlayerSupportedCommands;
let showMuteButton = true;
@ -448,7 +428,6 @@ import 'emby-ratingbutton';
// See bindEvents for why this is necessary
if (volumeSlider) {
volumeSliderContainer.classList.toggle('hide', !showVolumeSlider);
if (!volumeSlider.dragging) {
@ -458,7 +437,6 @@ import 'emby-ratingbutton';
}
function seriesImageUrl(item, options) {
if (!item) {
throw new Error('item cannot be null!');
}
@ -471,9 +449,7 @@ import 'emby-ratingbutton';
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);
@ -481,15 +457,12 @@ import 'emby-ratingbutton';
}
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);
@ -500,7 +473,6 @@ import 'emby-ratingbutton';
}
function imageUrl(item, options) {
if (!item) {
throw new Error('item cannot be null!');
}
@ -509,13 +481,11 @@ import 'emby-ratingbutton';
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);
}
@ -525,7 +495,6 @@ import 'emby-ratingbutton';
let currentImgUrl;
function updateNowPlayingInfo(state) {
const nowPlayingItem = state.NowPlayingItem;
const textLines = nowPlayingItem ? nowPlayingHelper.getNowPlayingNames(nowPlayingItem) : [];
@ -579,7 +548,6 @@ import 'emby-ratingbutton';
if (nowPlayingItem.Id) {
if (isRefreshing) {
const apiClient = connectionManager.getApiClient(nowPlayingItem.ServerId);
apiClient.getItem(apiClient.getCurrentUserId(), nowPlayingItem.Id).then(function (item) {
const userData = item.UserData || {};
@ -657,7 +625,6 @@ import 'emby-ratingbutton';
}
function hideNowPlayingBar() {
isEnabled = false;
// Use a timeout to prevent the bar from hiding and showing quickly
@ -666,13 +633,11 @@ import 'emby-ratingbutton';
// Don't call getNowPlayingBar here because we don't want to end up creating it just to hide it
const elem = document.getElementsByClassName('nowPlayingBar')[0];
if (elem) {
slideDown(elem);
}
}
function onPlaybackStopped(e, state) {
console.debug('nowplaying event: ' + e.type);
const player = this;
@ -688,7 +653,6 @@ import 'emby-ratingbutton';
}
function onPlayPauseStateChanged(e) {
if (!isEnabled) {
return;
}
@ -698,7 +662,6 @@ import 'emby-ratingbutton';
}
function onStateChanged(event, state) {
console.debug('nowplaying event: ' + event.type);
const player = this;
@ -725,7 +688,6 @@ import 'emby-ratingbutton';
}
function onTimeUpdate(e) {
if (!isEnabled) {
return;
}
@ -733,7 +695,6 @@ import 'emby-ratingbutton';
// Try to avoid hammering the document with changes
const now = new Date().getTime();
if ((now - lastUpdateTime) < 700) {
return;
}
lastUpdateTime = now;
@ -744,7 +705,6 @@ import 'emby-ratingbutton';
}
function releaseCurrentPlayer() {
const player = currentPlayer;
if (player) {
@ -764,7 +724,6 @@ import 'emby-ratingbutton';
}
function onVolumeChanged(e) {
if (!isEnabled) {
return;
}
@ -775,14 +734,12 @@ import 'emby-ratingbutton';
}
function refreshFromPlayer(player) {
const state = playbackManager.getPlayerState(player);
onStateChanged.call(player, { type: 'init' }, state);
}
function bindToPlayer(player) {
if (player === currentPlayer) {
return;
}
@ -815,16 +772,12 @@ import 'emby-ratingbutton';
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);

View file

@ -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;

View file

@ -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;
}

View file

@ -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

View file

@ -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);

View file

@ -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)
};
});
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,7 +133,6 @@ export function show(button) {
playbackManager.trySetActivePlayer(target.playerName, target);
mirrorIfEnabled();
}, emptyCallback);
});
});
@ -164,11 +150,8 @@ function showActivePlayerMenu(playerInfo) {
}
function disconnectFromPlayer(currentDeviceName) {
if (playbackManager.getSupportedCommands().indexOf('EndSession') !== -1) {
import('dialog').then(({default: dialog}) => {
var menuItems = [];
menuItems.push({
@ -182,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();
@ -199,17 +180,13 @@ function disconnectFromPlayer(currentDeviceName) {
break;
}
});
});
} else {
playbackManager.setDefaultPlayerActive();
}
}
function showActivePlayerMenuInternal(dialogHelper, playerInfo) {
var html = '';
var dialogOptions = {
@ -235,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 + '/>';
@ -294,7 +270,6 @@ function onMirrorChange() {
}
document.addEventListener('viewshow', function (e) {
var state = e.detail.state || {};
var item = state.item;

View file

@ -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) {

View file

@ -1,5 +1,4 @@
export function getDisplayPlayMethod(session) {
if (!session.NowPlayingItem) {
return null;
}

View file

@ -1,19 +1,15 @@
define([], function () {
'use strict';
/*eslint prefer-const: "error"*/
var currentId = 0;
let 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++) {
for (let i = 0, length = list.length; i < length; i++) {
if (list[i].PlaylistItemId === playlistItemId) {
return i;
}
@ -22,43 +18,39 @@ define([], function () {
return -1;
}
function PlayQueueManager() {
class PlayQueueManager {
constructor() {
this._sortedPlaylist = [];
this._playlist = [];
this._repeatMode = 'RepeatNone';
this._shuffleMode = 'Sorted';
}
PlayQueueManager.prototype.getPlaylist = function () {
getPlaylist() {
return this._playlist.slice(0);
};
PlayQueueManager.prototype.setPlaylist = function (items) {
}
setPlaylist(items) {
items = items.slice(0);
for (var i = 0, length = items.length; i < length; i++) {
for (let i = 0, length = items.length; i < length; i++) {
addUniquePlaylistItemId(items[i]);
}
this._currentPlaylistItemId = null;
this._playlist = items;
this._repeatMode = 'RepeatNone';
};
PlayQueueManager.prototype.queue = function (items) {
for (var i = 0, length = items.length; i < length; i++) {
}
queue(items) {
for (let i = 0, length = items.length; i < length; i++) {
addUniquePlaylistItemId(items[i]);
this._playlist.push(items[i]);
}
};
}
PlayQueueManager.prototype.shufflePlaylist = function () {
shufflePlaylist() {
this._sortedPlaylist = [];
for (const item of this._playlist) {
this._sortedPlaylist.push(item);
@ -73,43 +65,31 @@ define([], function () {
}
this._playlist.unshift(currentPlaylistItem);
this._shuffleMode = 'Shuffle';
};
}
PlayQueueManager.prototype.sortShuffledPlaylist = function () {
sortShuffledPlaylist() {
this._playlist = [];
for (let item of this._sortedPlaylist) {
for (const item of this._sortedPlaylist) {
this._playlist.push(item);
}
this._sortedPlaylist = [];
this._shuffleMode = 'Sorted';
};
}
PlayQueueManager.prototype.clearPlaylist = function (clearCurrentItem = false) {
clearPlaylist(clearCurrentItem = false) {
const currentPlaylistItem = this._playlist.splice(this.getCurrentPlaylistIndex(), 1)[0];
this._playlist = [];
if (!clearCurrentItem) {
this._playlist.push(currentPlaylistItem);
}
};
function arrayInsertAt(destArray, pos, arrayToInsert) {
var args = [];
args.push(pos); // where to insert
args.push(0); // nothing to remove
args = args.concat(arrayToInsert); // add on array to insert
destArray.splice.apply(destArray, args); // splice it in
}
PlayQueueManager.prototype.queueNext = function (items) {
var i;
var length;
for (i = 0, length = items.length; i < length; i++) {
queueNext(items) {
for (let i = 0, length = items.length; i < length; i++) {
addUniquePlaylistItemId(items[i]);
}
var currentIndex = this.getCurrentPlaylistIndex();
let currentIndex = this.getCurrentPlaylistIndex();
if (currentIndex === -1) {
currentIndex = this._playlist.length;
@ -118,48 +98,43 @@ define([], function () {
}
arrayInsertAt(this._playlist, currentIndex, items);
};
PlayQueueManager.prototype.getCurrentPlaylistIndex = function () {
}
getCurrentPlaylistIndex() {
return findPlaylistIndex(this.getCurrentPlaylistItemId(), this._playlist);
};
}
PlayQueueManager.prototype.getCurrentItem = function () {
var index = findPlaylistIndex(this.getCurrentPlaylistItemId(), this._playlist);
getCurrentItem() {
const index = findPlaylistIndex(this.getCurrentPlaylistItemId(), this._playlist);
return index === -1 ? null : this._playlist[index];
};
}
PlayQueueManager.prototype.getCurrentPlaylistItemId = function () {
getCurrentPlaylistItemId() {
return this._currentPlaylistItemId;
};
PlayQueueManager.prototype.setPlaylistState = function (playlistItemId, playlistIndex) {
}
setPlaylistState(playlistItemId, playlistIndex) {
this._currentPlaylistItemId = playlistItemId;
};
PlayQueueManager.prototype.setPlaylistIndex = function (playlistIndex) {
}
setPlaylistIndex(playlistIndex) {
if (playlistIndex < 0) {
this.setPlaylistState(null);
} else {
this.setPlaylistState(this._playlist[playlistIndex].PlaylistItemId);
}
};
PlayQueueManager.prototype.removeFromPlaylist = function (playlistItemIds) {
}
removeFromPlaylist(playlistItemIds) {
if (this._playlist.length <= playlistItemIds.length) {
return {
result: 'empty'
};
}
var currentPlaylistItemId = this.getCurrentPlaylistItemId();
var isCurrentIndex = playlistItemIds.indexOf(currentPlaylistItemId) !== -1;
const currentPlaylistItemId = this.getCurrentPlaylistItemId();
const isCurrentIndex = playlistItemIds.indexOf(currentPlaylistItemId) !== -1;
this._sortedPlaylist = this._sortedPlaylist.filter(function (item) {
return !playlistItemIds.includes(item.PlaylistItemId);
@ -173,18 +148,13 @@ define([], function () {
result: 'removed',
isCurrentIndex: isCurrentIndex
};
};
function moveInArray(array, from, to) {
array.splice(to, 0, array.splice(from, 1)[0]);
}
PlayQueueManager.prototype.movePlaylistItem = function (playlistItemId, newIndex) {
movePlaylistItem(playlistItemId, newIndex) {
const playlist = this.getPlaylist();
var playlist = this.getPlaylist();
var oldIndex;
for (var i = 0, length = playlist.length; i < length; i++) {
let oldIndex;
for (let i = 0, length = playlist.length; i < length; i++) {
if (playlist[i].PlaylistItemId === playlistItemId) {
oldIndex = i;
break;
@ -210,31 +180,30 @@ define([], function () {
playlistItemId: playlistItemId,
newIndex: newIndex
};
};
PlayQueueManager.prototype.reset = function () {
}
reset() {
this._sortedPlaylist = [];
this._playlist = [];
this._currentPlaylistItemId = null;
this._repeatMode = 'RepeatNone';
this._shuffleMode = 'Sorted';
};
}
PlayQueueManager.prototype.setRepeatMode = function (value) {
setRepeatMode(value) {
const repeatModes = ['RepeatOne', 'RepeatAll', 'RepeatNone'];
if (repeatModes.includes(value)) {
this._repeatMode = value;
} else {
throw new TypeError('invalid value provided for setRepeatMode');
}
};
}
PlayQueueManager.prototype.getRepeatMode = function () {
getRepeatMode() {
return this._repeatMode;
};
}
PlayQueueManager.prototype.setShuffleMode = function (value) {
setShuffleMode(value) {
switch (value) {
case 'Shuffle':
this.shufflePlaylist();
@ -245,9 +214,9 @@ define([], function () {
default:
throw new TypeError('invalid value provided to setShuffleMode');
}
};
}
PlayQueueManager.prototype.toggleShuffleMode = function () {
toggleShuffleMode() {
switch (this._shuffleMode) {
case 'Shuffle':
this.setShuffleMode('Sorted');
@ -258,20 +227,18 @@ define([], function () {
default:
throw new TypeError('current value for shufflequeue is invalid');
}
};
}
PlayQueueManager.prototype.getShuffleMode = function () {
getShuffleMode() {
return this._shuffleMode;
};
}
PlayQueueManager.prototype.getNextItemInfo = function () {
var newIndex;
var playlist = this.getPlaylist();
var playlistLength = playlist.length;
getNextItemInfo() {
let newIndex;
const playlist = this.getPlaylist();
const playlistLength = playlist.length;
switch (this.getRepeatMode()) {
case 'RepeatOne':
newIndex = this.getCurrentPlaylistIndex();
break;
@ -290,7 +257,7 @@ define([], function () {
return null;
}
var item = playlist[newIndex];
const item = playlist[newIndex];
if (!item) {
return null;
@ -300,7 +267,19 @@ define([], function () {
item: item,
index: newIndex
};
};
}
}
return PlayQueueManager;
});
function arrayInsertAt(destArray, pos, arrayToInsert) {
let args = [];
args.push(pos); // where to insert
args.push(0); // nothing to remove
args = args.concat(arrayToInsert); // add on array to insert
destArray.splice.apply(destArray, args); // splice it in
}
function moveInArray(array, from, to) {
array.splice(to, 0, array.splice(from, 1)[0]);
}
export default PlayQueueManager;

View file

@ -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;
}

View file

@ -13,7 +13,6 @@ import 'emby-checkbox';
/* eslint-disable indent */
function fillSkipLengths(select) {
const options = [5, 10, 15, 20, 25, 30];
select.innerHTML = options.map(option => {
@ -27,13 +26,11 @@ import 'emby-checkbox';
}
function populateLanguages(select, languages) {
let html = '';
html += `<option value=''>${globalize.translate('AnyLanguage')}</option>`;
for (let i = 0, length = languages.length; i < length; i++) {
const culture = languages[i];
html += `<option value='${culture.ThreeLetterISOLanguageName}'>${culture.DisplayName}</option>`;
@ -43,7 +40,6 @@ import 'emby-checkbox';
}
function setMaxBitrateIntoField(select, isInNetwork, mediatype) {
const options = mediatype === 'Audio' ? qualityoptions.getAudioQualityOptions({
currentMaxBitrate: appSettings.maxStreamingBitrate(isInNetwork, mediatype),
@ -59,7 +55,6 @@ import 'emby-checkbox';
});
select.innerHTML = options.map(i => {
// render empty string instead of 0 for the auto option
return `<option value="${i.bitrate || ''}">${i.name}</option>`;
}).join('');
@ -72,7 +67,6 @@ import 'emby-checkbox';
}
function fillChromecastQuality(select) {
const options = qualityoptions.getVideoQualityOptions({
currentMaxBitrate: appSettings.maxChromecastBitrate(),
@ -81,7 +75,6 @@ import 'emby-checkbox';
});
select.innerHTML = options.map(i => {
// render empty string instead of 0 for the auto option
return `<option value="${i.bitrate || ''}">${i.name}</option>`;
}).join('');
@ -90,7 +83,6 @@ import 'emby-checkbox';
}
function setMaxBitrateFromField(select, isInNetwork, mediatype) {
if (select.value) {
appSettings.maxStreamingBitrate(isInNetwork, mediatype, select.value);
appSettings.enableAutomaticBitrateDetection(isInNetwork, mediatype, false);
@ -100,7 +92,6 @@ import 'emby-checkbox';
}
function showHideQualityFields(context, user, apiClient) {
if (user.Policy.EnableVideoPlaybackTranscoding) {
context.querySelector('.videoQualitySection').classList.remove('hide');
} else {
@ -108,7 +99,6 @@ import 'emby-checkbox';
}
if (appHost.supports('multiserver')) {
context.querySelector('.fldVideoInNetworkQuality').classList.remove('hide');
context.querySelector('.fldVideoInternetQuality').classList.remove('hide');
@ -122,15 +112,12 @@ import 'emby-checkbox';
}
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');
@ -145,7 +132,6 @@ import 'emby-checkbox';
}
function showOrHideEpisodesField(context) {
if (browser.tizen || browser.web0s) {
context.querySelector('.fldEpisodeAutoPlay').classList.add('hide');
return;
@ -155,14 +141,12 @@ import 'emby-checkbox';
}
function loadForm(context, user, userSettings, apiClient) {
const loggedInUserId = apiClient.getCurrentUserId();
const userId = user.Id;
showHideQualityFields(context, user, apiClient);
apiClient.getCultures().then(allCultures => {
populateLanguages(context.querySelector('#selectAudioLanguage'), allCultures);
context.querySelector('#selectAudioLanguage', context).value = user.Configuration.AudioLanguagePreference || '';
@ -171,7 +155,6 @@ import 'emby-checkbox';
// hide cinema mode options if disabled at server level
apiClient.getNamedConfiguration('cinemamode').then(cinemaConfig => {
if (cinemaConfig.EnableIntrosForMovies || cinemaConfig.EnableIntrosForEpisodes) {
context.querySelector('.cinemaModeOptions').classList.remove('hide');
} else {
@ -232,7 +215,6 @@ import 'emby-checkbox';
}
function saveUser(context, user, userSettingsInstance, apiClient) {
appSettings.enableSystemExternalPlayers(context.querySelector('.chkExternalVideoPlayer').checked);
appSettings.maxChromecastBitrate(context.querySelector('.selectChromecastVideoQuality').value);
@ -256,13 +238,10 @@ import 'emby-checkbox';
}
function save(instance, context, userId, userSettings, apiClient, enableSaveConfirmation) {
loading.show();
apiClient.getUser(userId).then(user => {
saveUser(context, user, userSettings, apiClient).then(() => {
loading.hide();
if (enableSaveConfirmation) {
import('toast').then(({default: toast}) => {
@ -271,7 +250,6 @@ import 'emby-checkbox';
}
events.trigger(instance, 'saved');
}, () => {
loading.hide();
});
@ -279,14 +257,12 @@ import 'emby-checkbox';
}
function onSubmit(e) {
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(() => {
const enableSaveConfirmation = self.options.enableSaveConfirmation;
save(self, self.options.element, userId, userSettings, apiClient, enableSaveConfirmation);
});
@ -299,9 +275,7 @@ import 'emby-checkbox';
}
function embed(options, self) {
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));
@ -325,7 +299,6 @@ import 'emby-checkbox';
}
loadData() {
const self = this;
const context = self.options.element;
@ -336,9 +309,7 @@ import 'emby-checkbox';
const userSettings = self.options.userSettings;
apiClient.getUser(userId).then(user => {
userSettings.setUserInfo(userId, apiClient).then(() => {
self.dataLoaded = true;
loadForm(context, user, userSettings, apiClient);
@ -351,7 +322,6 @@ import 'emby-checkbox';
}
destroy() {
this.options = null;
}
}

View file

@ -85,7 +85,7 @@
<div class="selectContainer">
<select is="emby-select" class="selectChromecastVersion" label="${LabelChromecastVersion}">
<option value="stable">${LabelStable}</option>
<option value="nightly">${LabelNightly}</option>
<option value="unstable">${LabelUnstable}</option>
</select>
</div>

View file

@ -5,14 +5,12 @@ import connectionManager from 'connectionManager';
import syncPlayManager from 'syncPlayManager';
import playMethodHelper from 'playMethodHelper';
import layoutManager from 'layoutManager';
import serverNotifications from 'serverNotifications';
import 'paper-icon-button-light';
import 'css!./playerstats';
/* eslint-disable indent */
function init(instance) {
const parent = document.createElement('div');
parent.classList.add('playerStats');
@ -51,9 +49,7 @@ import 'css!./playerstats';
}
function renderStats(elem, categories) {
elem.querySelector('.playerStats-stats').innerHTML = categories.map(function (category) {
let categoryHtml = '';
const stats = category.stats;
@ -73,7 +69,6 @@ import 'css!./playerstats';
}
for (let i = 0, length = stats.length; i < length; i++) {
categoryHtml += '<div class="playerStats-stat">';
const stat = stats[i];
@ -90,12 +85,10 @@ import 'css!./playerstats';
}
return categoryHtml;
}).join('');
}
function getSession(instance, player) {
const now = new Date().getTime();
if ((now - (instance.lastSessionTime || 0)) < 10000) {
@ -107,19 +100,16 @@ import 'css!./playerstats';
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);
}
@ -132,7 +122,6 @@ import 'css!./playerstats';
let audioChannels;
if (session.TranscodingInfo) {
videoCodec = session.TranscodingInfo.VideoCodec;
audioCodec = session.TranscodingInfo.AudioCodec;
totalBitrate = session.TranscodingInfo.Bitrate;
@ -140,7 +129,6 @@ import 'css!./playerstats';
}
if (videoCodec) {
sessionStats.push({
label: globalize.translate('LabelVideoCodec'),
value: session.TranscodingInfo.IsVideoDirect ? (videoCodec.toUpperCase() + ' (direct)') : videoCodec.toUpperCase()
@ -148,45 +136,39 @@ import 'css!./playerstats';
}
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/>')
@ -198,7 +180,6 @@ import 'css!./playerstats';
}
function getDisplayBitrate(bitrate) {
if (bitrate > 1000000) {
return (bitrate / 1000000).toFixed(1) + ' Mbps';
} else {
@ -217,7 +198,6 @@ import 'css!./playerstats';
}
function getMediaSourceStats(session, player, displayPlayMethod) {
const sessionStats = [];
const mediaSource = playbackManager.currentMediaSource(player) || {};
@ -239,7 +219,6 @@ import 'css!./playerstats';
}
if (totalBitrate) {
sessionStats.push({
label: globalize.translate('LabelBitrate'),
value: getDisplayBitrate(totalBitrate)
@ -248,18 +227,14 @@ import 'css!./playerstats';
const mediaStreams = mediaSource.MediaStreams || [];
const videoStream = mediaStreams.filter(function (s) {
return s.Type === 'Video';
})[0] || {};
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] || {};
const audioCodec = audioStream.Codec;
@ -360,12 +335,10 @@ import 'css!./playerstats';
}
function getStats(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];
@ -392,7 +365,6 @@ import 'css!./playerstats';
categories.push(baseCategory);
for (let i = 0, length = playerStats.length; i < length; i++) {
const category = playerStats[i];
if (category.type === 'audio') {
category.name = 'Audio Info';
@ -403,7 +375,6 @@ import 'css!./playerstats';
}
if (session.TranscodingInfo) {
categories.push({
stats: getTranscodingStats(session, player, displayPlayMethod),
name: displayPlayMethod === 'Transcode' ? 'Transcoding Info' : 'Direct Stream Info'
@ -428,7 +399,6 @@ import 'css!./playerstats';
}
function renderPlayerStats(instance, player) {
const now = new Date().getTime();
if ((now - (instance.lastRender || 0)) < 700) {
@ -438,7 +408,6 @@ import 'css!./playerstats';
instance.lastRender = now;
getStats(instance, player).then(function (stats) {
const elem = instance.element;
if (!elem) {
return;
@ -449,7 +418,6 @@ import 'css!./playerstats';
}
function bindEvents(instance, player) {
const localOnTimeUpdate = function () {
renderPlayerStats(instance, player);
};
@ -459,7 +427,6 @@ import 'css!./playerstats';
}
function unbindEvents(instance, player) {
const localOnTimeUpdate = instance.onTimeUpdate;
if (localOnTimeUpdate) {
@ -469,7 +436,6 @@ import 'css!./playerstats';
class PlayerStats {
constructor(options) {
this.options = options;
init(this);
@ -478,7 +444,6 @@ class PlayerStats {
}
enabled(enabled) {
if (enabled == null) {
return this._enabled;
}
@ -504,11 +469,9 @@ class PlayerStats {
}
destroy() {
const options = this.options;
if (options) {
this.options = null;
unbindEvents(this, options.player);
}

View file

@ -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],

View file

@ -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;

View file

@ -12,7 +12,6 @@ import 'formDialogStyle';
/* eslint-disable indent */
export default (() => {
function replaceAll(str, find, replace) {
return str.split(find).join(replace);
}
@ -68,7 +67,6 @@ export default (() => {
let submitValue;
dlg.querySelector('form').addEventListener('submit', e => {
submitValue = dlg.querySelector('#txtInput').value;
e.preventDefault();
e.stopPropagation();

View file

@ -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;
}

View file

@ -1,12 +1,12 @@
define(['globalize', 'connectionManager', 'require', 'loading', 'apphost', 'dom', 'recordingHelper', 'events', 'paper-icon-button-light', 'emby-button', 'css!./recordingfields'], function (globalize, connectionManager, require, loading, appHost, dom, recordingHelper, events) {
'use strict';
function onRecordingButtonClick(e) {
recordingHelper = recordingHelper.default || recordingHelper;
function onRecordingButtonClick(e) {
var item = this.item;
if (item) {
var serverId = item.ServerId;
var programId = item.Id;
var timerId = item.TimerId;
@ -50,23 +50,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 +72,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 +80,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 +93,6 @@ define(['globalize', 'connectionManager', 'require', 'loading', 'apphost', 'dom'
};
RecordingButton.prototype.destroy = function () {
var options = this.options;
if (options) {

View file

@ -8,27 +8,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) {
@ -36,14 +31,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,
@ -55,7 +48,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');
@ -93,7 +85,6 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
}
function reload(context, programId, serverId, refreshRecordingStateOnly) {
loading.show();
var apiClient = connectionManager.getApiClient(serverId);
@ -102,7 +93,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];
@ -111,16 +101,12 @@ 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({
playbackManager.default.play({
ids: [item.ChannelId],
serverId: serverId
});
@ -131,15 +117,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
@ -169,7 +152,6 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
}
dlg.addEventListener('close', function () {
events.off(currentRecordingFields, 'recordingchanged', onRecordingChanged);
executeCloseAction(closeAction, itemId, serverId);

View file

@ -2,6 +2,7 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
'use strict';
scrollHelper = scrollHelper.default || scrollHelper;
loading = loading.default || loading;
var currentDialog;
var recordingDeleted = false;
@ -10,10 +11,9 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
var currentResolve;
function deleteTimer(apiClient, timerId) {
return new Promise(function (resolve, reject) {
require(['recordingHelper'], function (recordingHelper) {
recordingHelper = recordingHelper.default || recordingHelper;
recordingHelper.cancelTimerWithConfirmation(timerId, apiClient.serverId()).then(resolve, reject);
});
@ -21,9 +21,6 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
}
function renderTimer(context, item, apiClient) {
var program = item.ProgramInfo || {};
context.querySelector('#txtPrePaddingMinutes').value = item.PrePaddingSeconds / 60;
context.querySelector('#txtPostPaddingMinutes').value = item.PostPaddingSeconds / 60;
@ -31,14 +28,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);
@ -56,14 +51,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);
@ -74,22 +66,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();
@ -129,14 +117,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,

View file

@ -2,6 +2,8 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa
'use strict';
serverNotifications = serverNotifications.default || serverNotifications;
recordingHelper = recordingHelper.default || recordingHelper;
loading = loading.default || loading;
function loadData(parent, program, apiClient) {
if (program.IsSeries) {
@ -36,7 +38,6 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa
}
function fetchData(instance) {
var options = instance.options;
var apiClient = connectionManager.getApiClient(options.serverId);
@ -123,7 +124,6 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa
}
function onManageSeriesRecordingClick(e) {
var options = this.options;
if (!this.SeriesTimerId) {
@ -133,7 +133,6 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa
var self = this;
require(['seriesRecordingEditor'], function (seriesRecordingEditor) {
seriesRecordingEditor.show(self.SeriesTimerId, options.serverId, {
enableCancel: false
@ -145,7 +144,6 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa
}
function onRecordChange(e) {
this.changed = true;
var self = this;
@ -185,7 +183,6 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loa
}
function onRecordSeriesChange(e) {
this.changed = true;
var self = this;

View file

@ -1,18 +1,17 @@
define(['globalize', 'loading', 'connectionManager'], function (globalize, loading, connectionManager) {
'use strict';
import globalize from 'globalize';
import loading from 'loading';
import connectionManager from 'connectionManager';
/*eslint prefer-const: "error"*/
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,11 +28,8 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
}
function cancelTimerWithConfirmation(timerId, serverId) {
return new Promise(function (resolve, reject) {
require(['confirm'], function (confirm) {
import('confirm').then(({ default: confirm }) => {
confirm.default({
text: globalize.translate('MessageConfirmRecordingCancellation'),
@ -42,23 +38,18 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
cancelText: globalize.translate('HeaderKeepRecording')
}).then(function () {
loading.show();
var apiClient = connectionManager.getApiClient(serverId);
const 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) {
import('confirm').then(({ default: confirm }) => {
confirm.default({
text: globalize.translate('MessageConfirmRecordingCancellation'),
@ -67,20 +58,17 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
cancelText: globalize.translate('HeaderKeepSeries')
}).then(function () {
loading.show();
var apiClient = connectionManager.getApiClient(serverId);
const apiClient = connectionManager.getApiClient(serverId);
apiClient.cancelLiveTvSeriesTimer(timerId).then(function () {
require(['toast'], function (toast) {
import('toast').then(({default: toast}) => {
toast(globalize.translate('SeriesCancelled'));
});
loading.hide();
resolve();
}, reject);
}, reject);
});
});
@ -89,7 +77,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 +85,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 ?
const promise = isSeries ?
apiClient.createLiveTvSeriesTimer(item) :
apiClient.createLiveTvTimer(item);
return promise.then(function () {
loading.hide();
sendToast(globalize.translate('RecordingScheduled'));
});
@ -115,17 +99,15 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
}
function sendToast(msg) {
require(['toast'], function (toast) {
import('toast').then(({ default: toast }) => {
toast(msg);
});
}
function showMultiCancellationPrompt(serverId, programId, timerId, timerStatus, seriesTimerId) {
return new Promise(function (resolve, reject) {
require(['dialog'], function (dialog) {
var items = [];
import('dialog').then(({ default: dialog }) => {
const items = [];
items.push({
name: globalize.translate('HeaderKeepRecording'),
@ -159,20 +141,17 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
buttons: items
}).then(function (result) {
var apiClient = connectionManager.getApiClient(serverId);
const apiClient = connectionManager.getApiClient(serverId);
if (result === 'canceltimer') {
loading.show();
cancelTimer(apiClient, timerId, true).then(resolve, reject);
} else if (result === 'cancelseriestimer') {
loading.show();
apiClient.cancelLiveTvSeriesTimer(seriesTimerId).then(function () {
require(['toast'], function (toast) {
import('toast').then(({ default: toast }) => {
toast(globalize.translate('SeriesCancelled'));
});
@ -182,15 +161,14 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
} else {
resolve();
}
}, reject);
});
});
}
function toggleRecording(serverId, programId, timerId, timerStatus, seriesTimerId) {
var apiClient = connectionManager.getApiClient(serverId);
var hasTimer = timerId && timerStatus !== 'Cancelled';
const apiClient = connectionManager.getApiClient(serverId);
const hasTimer = timerId && timerStatus !== 'Cancelled';
if (seriesTimerId && hasTimer) {
// cancel
return showMultiCancellationPrompt(serverId, programId, timerId, timerStatus, seriesTimerId);
@ -206,7 +184,7 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
}
}
return {
export default {
cancelTimer: cancelTimer,
createRecording: createRecording,
changeRecordingToSeries: changeRecordingToSeries,
@ -214,4 +192,4 @@ define(['globalize', 'loading', 'connectionManager'], function (globalize, loadi
cancelTimerWithConfirmation: cancelTimerWithConfirmation,
cancelSeriesTimerWithConfirmation: cancelSeriesTimerWithConfirmation
};
});

View file

@ -1,29 +1,38 @@
define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'connectionManager', 'require', 'loading', 'scrollHelper', 'imageLoader', 'datetime', 'scrollStyles', 'emby-button', 'emby-checkbox', 'emby-input', 'emby-select', 'paper-icon-button-light', 'css!./../formdialog', 'css!./recordingcreator', 'material-icons', 'flexStyles'], function (dialogHelper, globalize, layoutManager, mediaInfo, appHost, connectionManager, require, loading, scrollHelper, imageLoader, datetime) {
'use strict';
import dialogHelper from 'dialogHelper';
import globalize from 'globalize';
import layoutManager from 'layoutManager';
import connectionManager from 'connectionManager';
import loading from 'loading';
import scrollHelper from 'scrollHelper';
import datetime from 'datetime';
import 'scrollStyles';
import 'emby-button';
import 'emby-checkbox';
import 'emby-input';
import 'emby-select';
import 'paper-icon-button-light';
import 'css!./../formdialog';
import 'css!./recordingcreator';
import 'material-icons';
import 'flexStyles';
scrollHelper = scrollHelper.default || scrollHelper;
/*eslint prefer-const: "error"*/
var currentDialog;
var recordingUpdated = false;
var recordingDeleted = false;
var currentItemId;
var currentServerId;
let currentDialog;
let recordingUpdated = false;
let recordingDeleted = false;
let currentItemId;
let currentServerId;
function deleteTimer(apiClient, timerId) {
return new Promise(function (resolve, reject) {
require(['recordingHelper'], function (recordingHelper) {
import('recordingHelper').then(({ default: recordingHelper }) => {
recordingHelper.cancelSeriesTimerWithConfirmation(timerId, apiClient.serverId()).then(resolve, reject);
});
});
}
function renderTimer(context, item, apiClient) {
var program = item.ProgramInfo || {};
function renderTimer(context, item) {
context.querySelector('#txtPrePaddingMinutes').value = item.PrePaddingSeconds / 60;
context.querySelector('#txtPostPaddingMinutes').value = item.PostPaddingSeconds / 60;
@ -46,7 +55,6 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
}
function closeDialog(isDeleted) {
recordingUpdated = true;
recordingDeleted = isDeleted;
@ -54,13 +62,11 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
}
function onSubmit(e) {
const form = this;
var form = this;
var apiClient = connectionManager.getApiClient(currentServerId);
const 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';
@ -79,17 +85,14 @@ 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);
const apiClient = connectionManager.getApiClient(currentServerId);
deleteTimer(apiClient, currentItemId).then(function () {
closeDialog(true);
});
@ -99,34 +102,29 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
}
function reload(context, id) {
var apiClient = connectionManager.getApiClient(currentServerId);
const apiClient = connectionManager.getApiClient(currentServerId);
loading.show();
if (typeof id === 'string') {
currentItemId = id;
apiClient.getLiveTvSeriesTimer(id).then(function (result) {
renderTimer(context, result, apiClient);
renderTimer(context, result);
loading.hide();
});
} else if (id) {
currentItemId = id.Id;
renderTimer(context, id, apiClient);
renderTimer(context, id);
loading.hide();
}
}
function fillKeepUpTo(context) {
let html = '';
var html = '';
for (var i = 0; i <= 50; i++) {
var text;
for (let i = 0; i <= 50; i++) {
let text;
if (i === 0) {
text = globalize.translate('AsManyAsPossible');
@ -142,21 +140,19 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
context.querySelector('.selectKeepUpTo').innerHTML = html;
}
function onFieldChange(e) {
function onFieldChange() {
this.querySelector('.btnSubmit').click();
}
function embed(itemId, serverId, options) {
recordingUpdated = false;
recordingDeleted = false;
currentServerId = serverId;
loading.show();
options = options || {};
require(['text!./seriesrecordingeditor.template.html'], function (template) {
var dialogOptions = {
import('text!./seriesrecordingeditor.template.html').then(({ default: template }) => {
const dialogOptions = {
removeOnClose: true,
scrollY: false
};
@ -167,7 +163,7 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
dialogOptions.size = 'small';
}
var dlg = options.context;
const dlg = options.context;
dlg.classList.add('hide');
dlg.innerHTML = globalize.translateHtml(template, 'core');
@ -190,18 +186,15 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
}
function showEditor(itemId, serverId, options) {
return new Promise(function (resolve, reject) {
recordingUpdated = false;
recordingDeleted = false;
currentServerId = serverId;
loading.show();
options = options || {};
require(['text!./seriesrecordingeditor.template.html'], function (template) {
var dialogOptions = {
import('text!./seriesrecordingeditor.template.html').then(({ default: template }) => {
const dialogOptions = {
removeOnClose: true,
scrollY: false
};
@ -212,7 +205,7 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
dialogOptions.size = 'small';
}
var dlg = dialogHelper.createDialog(dialogOptions);
const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog');
dlg.classList.add('recordingDialog');
@ -221,7 +214,7 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
dlg.style['min-width'] = '20%';
}
var html = '';
let html = '';
html += globalize.translateHtml(template, 'core');
@ -234,14 +227,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,
@ -265,8 +256,7 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c
});
}
return {
export default {
show: showEditor,
embed: embed
};
});

View file

@ -1,9 +1,21 @@
define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'connectionManager', 'appRouter', 'globalize', 'emby-input', 'emby-checkbox', 'paper-icon-button-light', 'emby-select', 'material-icons', 'css!./../formdialog', 'emby-button'], function (dom, shell, dialogHelper, loading, 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 globalize from 'globalize';
import 'emby-input';
import 'emby-checkbox';
import 'paper-icon-button-light';
import 'emby-select';
import 'material-icons';
import 'css!./../formdialog';
import 'emby-button';
/*eslint prefer-const: "error"*/
function getEditorHtml() {
var html = '';
let html = '';
html += '<div class="formDialogContent smoothScrollY" style="padding-top:2em;">';
html += '<div class="dialogContentInner dialog-content-centered">';
@ -41,27 +53,25 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'connectionM
}
function centerFocus(elem, horiz, on) {
require(['scrollHelper'], function (scrollHelper) {
scrollHelper = scrollHelper.default || scrollHelper;
var fn = on ? 'on' : 'off';
import('scrollHelper').then(({default: scrollHelper}) => {
const fn = on ? 'on' : 'off';
scrollHelper.centerFocus[fn](elem, horiz);
});
}
function onSubmit(e) {
loading.show();
var instance = this;
var dlg = dom.parentWithClass(e.target, 'dialog');
var options = instance.options;
const instance = this;
const dlg = dom.parentWithClass(e.target, 'dialog');
const options = instance.options;
var apiClient = connectionManager.getApiClient(options.serverId);
const apiClient = connectionManager.getApiClient(options.serverId);
var replaceAllMetadata = dlg.querySelector('#selectMetadataRefreshMode').value === 'all';
const replaceAllMetadata = dlg.querySelector('#selectMetadataRefreshMode').value === 'all';
var mode = dlg.querySelector('#selectMetadataRefreshMode').value === 'scan' ? 'Default' : 'FullRefresh';
var replaceAllImages = mode === 'FullRefresh' && dlg.querySelector('.chkReplaceImages').checked;
const mode = dlg.querySelector('#selectMetadataRefreshMode').value === 'scan' ? 'Default' : 'FullRefresh';
const replaceAllImages = mode === 'FullRefresh' && dlg.querySelector('.chkReplaceImages').checked;
options.itemIds.forEach(function (itemId) {
apiClient.refreshItem(itemId, {
@ -76,7 +86,7 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'connectionM
dialogHelper.close(dlg);
require(['toast'], function (toast) {
import('toast').then(({default: toast}) => {
toast(globalize.translate('RefreshQueued'));
});
@ -86,13 +96,13 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'connectionM
return false;
}
function RefreshDialog(options) {
class RefreshDialog {
constructor(options) {
this.options = options;
}
RefreshDialog.prototype.show = function () {
var dialogOptions = {
show() {
const dialogOptions = {
removeOnClose: true,
scrollY: false
};
@ -103,12 +113,12 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'connectionM
dialogOptions.size = 'small';
}
var dlg = dialogHelper.createDialog(dialogOptions);
const dlg = dialogHelper.createDialog(dialogOptions);
dlg.classList.add('formDialog');
var html = '';
var title = globalize.translate('RefreshMetadata');
let html = '';
const title = globalize.translate('RefreshMetadata');
html += '<div class="formDialogHeader">';
html += '<button is="paper-icon-button-light" class="btnCancel autoSize" tabindex="-1"><span class="material-icons arrow_back"></span></button>';
@ -125,7 +135,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 {
@ -140,7 +149,6 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'connectionM
dlg.querySelector('#selectMetadataRefreshMode').dispatchEvent(new CustomEvent('change'));
dlg.querySelector('.btnCancel').addEventListener('click', function () {
dialogHelper.close(dlg);
});
@ -149,7 +157,6 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'connectionM
}
return new Promise(function (resolve, reject) {
if (layoutManager.tv) {
centerFocus(dlg.querySelector('.formDialogContent'), false, false);
}
@ -157,7 +164,7 @@ define(['dom', 'shell', 'dialogHelper', 'loading', 'layoutManager', 'connectionM
dlg.addEventListener('close', resolve);
dialogHelper.open(dlg);
});
};
}
}
return RefreshDialog;
});
export default RefreshDialog;

View file

@ -1,5 +1,8 @@
define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageLoader', 'playbackManager', 'nowPlayingHelper', 'events', 'connectionManager', 'apphost', 'globalize', 'layoutManager', 'userSettings', 'cardBuilder', 'itemContextMenu', 'cardStyle', 'emby-itemscontainer', 'css!./remotecontrol.css', 'emby-ratingbutton'], function (browser, datetime, backdrop, libraryBrowser, listView, imageLoader, playbackManager, nowPlayingHelper, events, connectionManager, appHost, globalize, layoutManager, userSettings, cardBuilder, itemContextMenu) {
'use strict';
playbackManager = playbackManager.default || playbackManager;
var showMuteButton = true;
var showVolumeSlider = true;
@ -48,7 +51,7 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
menuItems.unshift({
id: -1,
name: globalize.translate('ButtonOff'),
selected: null == currentIndex
selected: currentIndex == null
});
require(['actionsheet'], function (actionsheet) {
@ -69,18 +72,18 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
}
function seriesImageUrl(item, options) {
if ('Episode' !== item.Type) {
if (item.Type !== 'Episode') {
return null;
}
options = options || {};
options.type = options.type || 'Primary';
if ('Primary' === options.type && item.SeriesPrimaryImageTag) {
if (options.type === 'Primary' && item.SeriesPrimaryImageTag) {
options.tag = item.SeriesPrimaryImageTag;
return connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options);
}
if ('Thumb' === options.type) {
if (options.type === 'Thumb') {
if (item.SeriesThumbImageTag) {
options.tag = item.SeriesThumbImageTag;
return connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options);
@ -119,9 +122,9 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
var nowPlayingServerId = (item.ServerId || serverId);
if (item.Type == 'Audio' || item.MediaStreams[0].Type == 'Audio') {
var songName = item.Name;
if (item.Album != null && item.Artists != null) {
var artistsSeries = '';
var albumName = item.Album;
var albumName = '';
if (item.Artists != null) {
if (item.ArtistItems != null) {
for (const artist of item.ArtistItems) {
let artistName = artist.Name;
@ -142,9 +145,12 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
}
}
}
context.querySelector('.nowPlayingArtist').innerHTML = artistsSeries;
context.querySelector('.nowPlayingAlbum').innerHTML = '<a class="button-link emby-button" is="emby-linkbutton" href="details?id=' + item.AlbumId + `&serverId=${nowPlayingServerId}">${albumName}</a>`;
}
if (item.Album != null) {
albumName = '<a class="button-link emby-button" is="emby-linkbutton" href="details?id=' + item.AlbumId + `&serverId=${nowPlayingServerId}">` + item.Album + '</a>';
}
context.querySelector('.nowPlayingAlbum').innerHTML = albumName;
context.querySelector('.nowPlayingArtist').innerHTML = artistsSeries;
context.querySelector('.nowPlayingSongName').innerHTML = songName;
} else if (item.Type == 'Episode') {
if (item.SeasonName != null) {
@ -171,9 +177,9 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
}
var url = item ? seriesImageUrl(item, {
maxHeight: 300 * 2
maxHeight: 300
}) || imageUrl(item, {
maxHeight: 300 * 2
maxHeight: 300
}) : null;
let contextButton = context.querySelector('.btnToggleContextMenu');
@ -210,7 +216,7 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
backdrop.setBackdrops([item]);
apiClient.getItem(apiClient.getCurrentUserId(), item.Id).then(function (fullItem) {
var userData = fullItem.UserData || {};
var likes = null == userData.Likes ? '' : userData.Likes;
var likes = userData.Likes == null ? '' : userData.Likes;
context.querySelector('.nowPlayingPageUserDataButtonsTitle').innerHTML = '<button is="emby-ratingbutton" type="button" class="listItemButton paper-icon-button-light" data-id="' + fullItem.Id + '" data-serverid="' + fullItem.ServerId + '" data-itemtype="' + fullItem.Type + '" data-likes="' + likes + '" data-isfavorite="' + userData.IsFavorite + '"><span class="material-icons favorite"></span></button>';
context.querySelector('.nowPlayingPageUserDataButtons').innerHTML = '<button is="emby-ratingbutton" type="button" class="listItemButton paper-icon-button-light" data-id="' + fullItem.Id + '" data-serverid="' + fullItem.ServerId + '" data-itemtype="' + fullItem.Type + '" data-likes="' + likes + '" data-isfavorite="' + userData.IsFavorite + '"><span class="material-icons favorite"></span></button>';
});
@ -222,7 +228,6 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
}
function setImageUrl(context, state, url) {
currentImgUrl = url;
var item = state.NowPlayingItem;
var imgContainer = context.querySelector('.nowPlayingPageImageContainer');
@ -252,12 +257,11 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
var all = context.querySelectorAll('.btnCommand');
for (var i = 0, length = all.length; i < length; i++) {
var enableButton = -1 !== commands.indexOf(all[i].getAttribute('data-command'));
var enableButton = commands.indexOf(all[i].getAttribute('data-command')) !== -1;
all[i].disabled = !enableButton;
}
}
var currentImgUrl;
return function () {
function toggleRepeat() {
switch (playbackManager.getRepeatMode()) {
@ -280,7 +284,7 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
currentPlayerSupportedCommands = supportedCommands;
var playState = state.PlayState || {};
var isSupportedCommands = supportedCommands.includes('DisplayMessage') || supportedCommands.includes('SendString') || supportedCommands.includes('Select');
buttonVisible(context.querySelector('.btnToggleFullscreen'), item && 'Video' == item.MediaType && supportedCommands.includes('ToggleFullscreen'));
buttonVisible(context.querySelector('.btnToggleFullscreen'), item && item.MediaType == 'Video' && supportedCommands.includes('ToggleFullscreen'));
updateAudioTracksDisplay(player, context);
updateSubtitleTracksDisplay(player, context);
@ -308,15 +312,15 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
context.querySelector('.remoteControlSection').classList.add('hide');
}
buttonVisible(context.querySelector('.btnStop'), null != item);
buttonVisible(context.querySelector('.btnNextTrack'), null != item);
buttonVisible(context.querySelector('.btnPreviousTrack'), null != item);
buttonVisible(context.querySelector('.btnStop'), item != null);
buttonVisible(context.querySelector('.btnNextTrack'), item != null);
buttonVisible(context.querySelector('.btnPreviousTrack'), item != null);
if (layoutManager.mobile) {
buttonVisible(context.querySelector('.btnRewind'), false);
buttonVisible(context.querySelector('.btnFastForward'), false);
} else {
buttonVisible(context.querySelector('.btnRewind'), null != item);
buttonVisible(context.querySelector('.btnFastForward'), null != item);
buttonVisible(context.querySelector('.btnRewind'), item != null);
buttonVisible(context.querySelector('.btnFastForward'), item != null);
}
var positionSlider = context.querySelector('.nowPlayingPositionSlider');
@ -327,15 +331,15 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
if (positionSlider && !positionSlider.dragging) {
positionSlider.disabled = !playState.CanSeek;
var isProgressClear = state.MediaSource && null == state.MediaSource.RunTimeTicks;
var isProgressClear = state.MediaSource && state.MediaSource.RunTimeTicks == null;
positionSlider.setIsClear(isProgressClear);
}
updatePlayPauseState(playState.IsPaused, null != item);
updatePlayPauseState(playState.IsPaused, item != null);
updateTimeDisplay(playState.PositionTicks, item ? item.RunTimeTicks : null);
updatePlayerVolumeState(context, playState.IsMuted, playState.VolumeLevel);
if (item && 'Video' == item.MediaType) {
if (item && item.MediaType == 'Video') {
context.classList.remove('hideVideoButtons');
} else {
context.classList.add('hideVideoButtons');
@ -348,12 +352,12 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
function updateAudioTracksDisplay(player, context) {
var supportedCommands = currentPlayerSupportedCommands;
buttonVisible(context.querySelector('.btnAudioTracks'), playbackManager.audioTracks(player).length > 1 && -1 != supportedCommands.indexOf('SetAudioStreamIndex'));
buttonVisible(context.querySelector('.btnAudioTracks'), playbackManager.audioTracks(player).length > 1 && supportedCommands.indexOf('SetAudioStreamIndex') != -1);
}
function updateSubtitleTracksDisplay(player, context) {
var supportedCommands = currentPlayerSupportedCommands;
buttonVisible(context.querySelector('.btnSubtitles'), playbackManager.subtitleTracks(player).length && -1 != supportedCommands.indexOf('SetSubtitleStreamIndex'));
buttonVisible(context.querySelector('.btnSubtitles'), playbackManager.subtitleTracks(player).length && supportedCommands.indexOf('SetSubtitleStreamIndex') != -1);
}
function updateRepeatModeDisplay(repeatMode) {
@ -385,11 +389,11 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
var view = context;
var supportedCommands = currentPlayerSupportedCommands;
if (-1 === supportedCommands.indexOf('Mute')) {
if (supportedCommands.indexOf('Mute') === -1) {
showMuteButton = false;
}
if (-1 === supportedCommands.indexOf('SetVolume')) {
if (supportedCommands.indexOf('SetVolume') === -1) {
showVolumeSlider = false;
}
@ -420,7 +424,6 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
var nowPlayingVolumeSliderContainer = context.querySelector('.nowPlayingVolumeSliderContainer');
if (nowPlayingVolumeSlider) {
nowPlayingVolumeSliderContainer.classList.toggle('hide', !showVolumeSlider);
if (!nowPlayingVolumeSlider.dragging) {
@ -455,8 +458,8 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
}
}
context.querySelector('.positionTime').innerHTML = null == positionTicks ? '--:--' : datetime.getDisplayRunningTime(positionTicks);
context.querySelector('.runtime').innerHTML = null != runtimeTicks ? datetime.getDisplayRunningTime(runtimeTicks) : '--:--';
context.querySelector('.positionTime').innerHTML = positionTicks == null ? '--:--' : datetime.getDisplayRunningTime(positionTicks);
context.querySelector('.runtime').innerHTML = runtimeTicks != null ? datetime.getDisplayRunningTime(runtimeTicks) : '--:--';
}
function getPlaylistItems(player) {
@ -909,7 +912,6 @@ define(['browser', 'datetime', 'backdrop', 'libraryBrowser', 'listView', 'imageL
}
function onShow(context, tab) {
currentImgUrl = null;
bindToPlayer(context, playbackManager.getCurrentPlayer());
}

View file

@ -18,7 +18,6 @@ define(function () {
}
function removeFromLoadHistory(url) {
url = url.toLowerCase();
importedCss = importedCss.filter(function (c) {
@ -27,7 +26,6 @@ define(function () {
}
requireCss.load = function (cssId, req, load, config) {
// Somehow if the url starts with /css, require will get all screwed up since this extension is also called css
var srch = 'components/require/requirecss';
var index = cssId.indexOf(srch);
@ -65,7 +63,6 @@ define(function () {
window.requireCss = {
removeStylesheet: function (stylesheet) {
stylesheet.parentNode.removeChild(stylesheet);
removeFromLoadHistory(stylesheet.href);
}

View file

@ -7,7 +7,6 @@ define(function () {
return {
load: function (url, req, load, config) {
if (url.indexOf('://') === -1) {
url = config.baseUrl + url;
}

View file

@ -1,3 +1,4 @@
// TODO: Check if needed and move to external dependency
// From https://github.com/parshap/node-sanitize-filename
const illegalRe = /[\/\?<>\\:\*\|":]/g;

View file

@ -376,7 +376,6 @@ import layoutManager from 'layoutManager';
* @param {number} scrollY - Vertical coordinate.
*/
function animateScroll(xScroller, scrollX, yScroller, scrollY) {
const ox = xScroller.scrollLeft;
const oy = yScroller.scrollTop;
const dx = scrollX - ox;
@ -389,7 +388,6 @@ import layoutManager from 'layoutManager';
let start;
function scrollAnim(currentTimestamp) {
start = start || currentTimestamp;
let k = Math.min(1, (currentTimestamp - start) / ScrollTime);
@ -423,7 +421,6 @@ import layoutManager from 'layoutManager';
* @param {boolean} smooth - Smooth scrolling.
*/
function doScroll(xScroller, scrollX, yScroller, scrollY, smooth) {
resetScrollTimer();
if (smooth && useAnimatedScroll()) {
@ -437,7 +434,6 @@ import layoutManager from 'layoutManager';
* Returns true if smooth scroll must be used.
*/
function useSmoothScroll() {
if (browser.tizen) {
return true;
}
@ -469,7 +465,6 @@ import layoutManager from 'layoutManager';
* @param {boolean} [smooth=false] - Smooth scrolling.
*/
export function scrollTo(scrollX, scrollY, smooth) {
smooth = !!smooth;
// Scroller is document itself by default
@ -491,7 +486,6 @@ import layoutManager from 'layoutManager';
* @param {boolean} [smooth=false] - Smooth scrolling.
*/
export function scrollToElement(element, smooth) {
smooth = !!smooth;
let scrollCenterX = true;

View file

@ -11,7 +11,6 @@ import 'css!./searchfields';
/* eslint-disable indent */
function onSearchTimeout() {
const instance = this;
let value = instance.nextSearchValue;
@ -20,7 +19,6 @@ import 'css!./searchfields';
}
function triggerSearch(instance, value) {
if (instance.searchTimeout) {
clearTimeout(instance.searchTimeout);
}
@ -30,17 +28,14 @@ import 'css!./searchfields';
}
function onAlphaValueClicked(e) {
const value = e.detail.value;
const searchFieldsInstance = this;
const txtSearch = searchFieldsInstance.options.element.querySelector('.searchfields-txtSearch');
if (value === 'backspace') {
const val = txtSearch.value;
txtSearch.value = val.length ? val.substring(0, val.length - 1) : '';
} else {
txtSearch.value += value;
}
@ -51,7 +46,6 @@ import 'css!./searchfields';
}
function initAlphaPicker(alphaPickerElement, instance) {
instance.alphaPicker = new AlphaPicker({
element: alphaPickerElement,
mode: 'keyboard'
@ -61,16 +55,13 @@ import 'css!./searchfields';
}
function onSearchInput(e) {
const value = e.target.value;
const searchFieldsInstance = this;
triggerSearch(searchFieldsInstance, value);
}
function embed(elem, instance, options) {
import('text!./searchfields.template.html').then(({default: template}) => {
let html = globalize.translateHtml(template, 'core');
if (browser.tizen || browser.orsay) {
@ -98,16 +89,13 @@ import 'css!./searchfields';
class SearchFields {
constructor(options) {
this.options = options;
embed(options.element, this, options);
}
focus() {
this.options.element.querySelector('.searchfields-txtSearch').focus();
}
destroy() {
const options = this.options;
if (options) {
options.element.classList.remove('searchFields');

View file

@ -1,7 +1,5 @@
import layoutManager from 'layoutManager';
import globalize from 'globalize';
import require from 'require';
import events from 'events';
import connectionManager from 'connectionManager';
import cardBuilder from 'cardBuilder';
import appRouter from 'appRouter';
@ -12,7 +10,6 @@ import 'emby-button';
/* eslint-disable indent */
function loadSuggestions(instance, context, apiClient) {
const options = {
SortBy: 'IsFavoriteOrLiked,Random',
@ -26,20 +23,17 @@ import 'emby-button';
};
apiClient.getItems(apiClient.getCurrentUserId(), options).then(function (result) {
if (instance.mode !== 'suggestions') {
result.Items = [];
}
const html = result.Items.map(function (i) {
const href = appRouter.getRouteUrl(i);
let itemHtml = '<div><a is="emby-linkbutton" class="button-link" style="display:inline-block;padding:.5em 1em;" href="' + href + '">';
itemHtml += i.Name;
itemHtml += '</a></div>';
return itemHtml;
}).join('');
const searchSuggestions = context.querySelector('.searchSuggestions');
@ -52,7 +46,6 @@ import 'emby-button';
}
function getSearchHints(instance, apiClient, query) {
if (!query.searchTerm) {
return Promise.resolve({
SearchHints: []
@ -131,7 +124,6 @@ import 'emby-button';
// Convert the search hint query to a regular item query
if (apiClient.isMinServerVersion('3.4.1.31')) {
query.Fields = 'PrimaryImageAspectRatio,CanDelete,BasicSyncInfo,MediaSourceCount';
query.Recursive = true;
query.EnableTotalRecordCount = false;
@ -142,7 +134,6 @@ import 'emby-button';
if (!query.IncludeMedia) {
if (query.IncludePeople) {
methodName = 'getPeople';
} else if (query.IncludeArtists) {
methodName = 'getArtists';
}
@ -157,7 +148,6 @@ import 'emby-button';
}
function search(instance, apiClient, context, value) {
if (value || layoutManager.tv) {
instance.mode = 'search';
context.querySelector('.searchSuggestions').classList.add('hide');
@ -167,7 +157,6 @@ import 'emby-button';
}
if (instance.options.collectionType === 'livetv') {
searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: false,
@ -196,7 +185,6 @@ import 'emby-button';
showChannelName: true
});
} else {
searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: false,
@ -233,7 +221,6 @@ import 'emby-button';
});
if (instance.options.collectionType === 'livetv') {
searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: false,
@ -262,9 +249,7 @@ import 'emby-button';
showAirDateTime: true,
showChannelName: true
});
} else {
searchType(instance, apiClient, {
searchTerm: value,
IncludePeople: false,
@ -562,18 +547,15 @@ import 'emby-button';
}
function searchType(instance, apiClient, query, context, section, cardOptions) {
query.Limit = enableScrollX() ? 24 : 16;
query.ParentId = instance.options.parentId;
getSearchHints(instance, apiClient, query).then(function (result) {
populateResults(result, context, section, cardOptions);
});
}
function populateResults(result, context, section, cardOptions) {
section = context.querySelector(section);
const items = result.Items || result.SearchHints;
@ -603,9 +585,7 @@ import 'emby-button';
}
function embed(elem, instance, options) {
import('text!./searchresults.template.html').then(({default: template}) => {
if (!enableScrollX()) {
template = replaceAll(template, 'data-horizontal="true"', 'data-horizontal="false"');
template = replaceAll(template, 'itemsContainer scrollSlider', 'itemsContainer scrollSlider vertical-wrap');
@ -622,24 +602,20 @@ import 'emby-button';
class SearchResults {
constructor(options) {
this.options = options;
embed(options.element, this, options);
}
search(value) {
const apiClient = connectionManager.getApiClient(this.options.serverId);
search(this, apiClient, this.options.element, value);
}
destroy() {
const options = this.options;
if (options) {
options.element.classList.remove('searchFields');
}
this.options = null;
}
}

View file

@ -14,7 +14,6 @@ import dom from 'dom';
import recordingHelper from 'recordingHelper';
function playAllFromHere(card, serverId, queue) {
const parent = card.parentNode;
const className = card.classList.length ? (`.${card.classList[0]}`) : '';
const cards = parent.querySelectorAll(`${className}[data-id]`);
@ -36,17 +35,14 @@ import recordingHelper from 'recordingHelper';
const itemsContainer = dom.parentWithClass(card, 'itemsContainer');
if (itemsContainer && itemsContainer.fetchData) {
const queryOptions = queue ? { StartIndex: startIndex } : {};
return itemsContainer.fetchData(queryOptions).then(result => {
if (queue) {
return playbackManager.queue({
items: result.Items
});
} else {
return playbackManager.play({
items: result.Items,
startIndex: startIndex
@ -65,7 +61,6 @@ import recordingHelper from 'recordingHelper';
serverId: serverId
});
} else {
return playbackManager.play({
ids: ids,
serverId: serverId,
@ -75,15 +70,12 @@ import recordingHelper from 'recordingHelper';
}
function showProgramDialog(item) {
import('recordingCreator').then(({default:recordingCreator}) => {
recordingCreator.show(item.Id, item.ServerId);
});
}
function getItem(button) {
button = dom.parentWithAttribute(button, 'data-id');
const serverId = button.getAttribute('data-serverid');
const id = button.getAttribute('data-id');
@ -101,7 +93,6 @@ import recordingHelper from 'recordingHelper';
}
function notifyRefreshNeeded(childElement, itemsContainer) {
itemsContainer = itemsContainer || dom.parentWithAttribute(childElement, 'is', 'emby-itemscontainer');
if (itemsContainer) {
@ -110,9 +101,7 @@ import recordingHelper from 'recordingHelper';
}
function showContextMenu(card, options) {
getItem(card).then(item => {
const playlistId = card.getAttribute('data-playlistid');
const collectionId = card.getAttribute('data-collectionid');
@ -122,7 +111,6 @@ import recordingHelper from 'recordingHelper';
}
import('itemContextMenu').then(({default: itemContextMenu}) => {
connectionManager.getApiClient(item.ServerId).getCurrentUser().then(user => {
itemContextMenu.show(Object.assign({
item: item,
@ -135,7 +123,6 @@ import recordingHelper from 'recordingHelper';
user: user
}, options || {})).then(result => {
if (result.command === 'playallfromhere' || result.command === 'queueallfromhere') {
executeAction(card, options.positionTo, result.command);
} else if (result.updated || result.deleted) {
@ -148,7 +135,6 @@ import recordingHelper from 'recordingHelper';
}
function getItemInfoFromCard(card) {
return {
Type: card.getAttribute('data-type'),
Id: card.getAttribute('data-id'),
@ -166,11 +152,9 @@ import recordingHelper from 'recordingHelper';
}
function showPlayMenu(card, target) {
const item = getItemInfoFromCard(card);
import('playMenu').then(({default: playMenu}) => {
playMenu.show({
item: item,
@ -186,7 +170,6 @@ import recordingHelper from 'recordingHelper';
}
function executeAction(card, target, action) {
target = target || card;
let id = card.getAttribute('data-id');
@ -208,13 +191,11 @@ import recordingHelper from 'recordingHelper';
}
if (action === 'link') {
appRouter.showItem(item, {
context: card.getAttribute('data-context'),
parentId: card.getAttribute('data-parentid')
});
} else if (action === 'programdialog') {
showProgramDialog(item);
} else if (action === 'instantmix') {
playbackManager.instantMix({
@ -222,7 +203,6 @@ import recordingHelper from 'recordingHelper';
ServerId: serverId
});
} else if (action === 'play' || action === 'resume') {
const startPositionTicks = parseInt(card.getAttribute('data-positionticks') || '0');
playbackManager.play({
@ -231,7 +211,6 @@ import recordingHelper from 'recordingHelper';
serverId: serverId
});
} else if (action === 'queue') {
if (playbackManager.isPlaying()) {
playbackManager.queue({
ids: [playableItemId],
@ -253,7 +232,6 @@ import recordingHelper from 'recordingHelper';
} else if (action === 'record') {
onRecordCommand(serverId, id, type, card.getAttribute('data-timerid'), card.getAttribute('data-seriestimerid'));
} else if (action === 'menu') {
const options = target.getAttribute('data-playoptions') === 'false' ?
{
shuffle: false,
@ -279,7 +257,6 @@ import recordingHelper from 'recordingHelper';
} else if (action === 'addtoplaylist') {
getItem(target).then(addToPlaylist);
} else if (action === 'custom') {
const customAction = target.getAttribute('data-customaction');
card.dispatchEvent(new CustomEvent(`action-${customAction}`, {
@ -294,7 +271,6 @@ import recordingHelper from 'recordingHelper';
function addToPlaylist(item) {
import('playlistEditor').then(({default: playlistEditor}) => {
new playlistEditor().show({
items: [item.Id],
serverId: item.ServerId
@ -304,7 +280,6 @@ import recordingHelper from 'recordingHelper';
}
function playTrailer(item) {
const apiClient = connectionManager.getApiClient(item.ServerId);
apiClient.getLocalTrailers(apiClient.getCurrentUserId(), item.Id).then(trailers => {
@ -313,28 +288,23 @@ import recordingHelper from 'recordingHelper';
}
function editItem(item, serverId) {
const apiClient = connectionManager.getApiClient(serverId);
return new Promise((resolve, reject) => {
const serverId = apiClient.serverInfo().Id;
if (item.Type === 'Timer') {
if (item.ProgramId) {
import('recordingCreator').then(({default: recordingCreator}) => {
recordingCreator.show(item.ProgramId, serverId).then(resolve, reject);
});
} else {
import('recordingEditor').then(({default: recordingEditor}) => {
recordingEditor.show(item.Id, serverId).then(resolve, reject);
});
}
} else {
import('metadataEditor').then(({default: metadataEditor}) => {
metadataEditor.show(item.Id, serverId).then(resolve, reject);
});
}
@ -342,20 +312,16 @@ import recordingHelper from 'recordingHelper';
}
function onRecordCommand(serverId, id, type, timerId, seriesTimerId) {
if (type === 'Program' || timerId || seriesTimerId) {
const programId = type === 'Program' ? id : null;
recordingHelper.toggleRecording(serverId, programId, timerId, seriesTimerId);
}
}
export function onClick(e) {
const card = dom.parentWithClass(e.target, 'itemAction');
if (card) {
let actionElement = card;
let action = actionElement.getAttribute('data-action');
@ -377,11 +343,9 @@ import recordingHelper from 'recordingHelper';
}
function onCommand(e) {
const cmd = e.detail.command;
if (cmd === 'play' || cmd === 'resume' || cmd === 'record' || cmd === 'menu' || cmd === 'info') {
const target = e.target;
const card = dom.parentWithClass(target, 'itemAction') || dom.parentWithAttribute(target, 'data-id');
@ -394,7 +358,6 @@ import recordingHelper from 'recordingHelper';
}
export function on(context, options) {
options = options || {};
if (options.click !== false) {
@ -417,7 +380,6 @@ import recordingHelper from 'recordingHelper';
}
export function getShortcutAttributesHtml(item, serverId) {
let html = `data-id="${item.Id}" data-serverid="${serverId || item.ServerId}" data-type="${item.Type}" data-mediatype="${item.MediaType}" data-channelid="${item.ChannelId}" data-isfolder="${item.IsFolder}"`;
const collectionType = item.CollectionType;

View file

@ -1,184 +0,0 @@
define(['apphost', 'userSettings', 'browser', 'events', 'backdrop', 'globalize', 'require', 'appSettings'], function (appHost, userSettings, browser, events, backdrop, globalize, require, appSettings) {
'use strict';
var themeStyleElement;
var currentThemeId;
function unloadTheme() {
var elem = themeStyleElement;
if (elem) {
elem.parentNode.removeChild(elem);
themeStyleElement = null;
currentThemeId = null;
}
}
function loadUserSkin(options) {
options = options || {};
if (options.start) {
Emby.Page.invokeShortcut(options.start);
} else {
Emby.Page.goHome();
}
}
function getThemes() {
return [{
name: 'Apple TV',
id: 'appletv'
}, {
name: 'Blue Radiance',
id: 'blueradiance'
}, {
name: 'Dark',
id: 'dark',
isDefault: true,
isDefaultServerDashboard: true
}, {
name: 'Light',
id: 'light'
}, {
name: 'Purple Haze',
id: 'purplehaze'
}, {
name: 'Windows Media Center',
id: 'wmc'
}];
}
var skinManager = {
getThemes: getThemes,
loadUserSkin: loadUserSkin
};
function getThemeStylesheetInfo(id, isDefaultProperty) {
var themes = skinManager.getThemes();
var defaultTheme;
var selectedTheme;
for (var i = 0, length = themes.length; i < length; i++) {
var theme = themes[i];
if (theme[isDefaultProperty]) {
defaultTheme = theme;
}
if (id === theme.id) {
selectedTheme = theme;
}
}
selectedTheme = selectedTheme || defaultTheme;
return {
stylesheetPath: require.toUrl('themes/' + selectedTheme.id + '/theme.css'),
themeId: selectedTheme.id
};
}
var themeResources = {};
var lastSound = 0;
var currentSound;
function loadThemeResources(id) {
lastSound = 0;
if (currentSound) {
currentSound.stop();
currentSound = null;
}
backdrop.clearBackdrop();
}
function onThemeLoaded() {
document.documentElement.classList.remove('preload');
try {
var color = getComputedStyle(document.querySelector('.skinHeader')).getPropertyValue('background-color');
if (color) {
appHost.setThemeColor(color);
}
} catch (err) {
console.error('error setting theme color: ' + err);
}
}
skinManager.setTheme = function (id, context) {
return new Promise(function (resolve, reject) {
if (currentThemeId && currentThemeId === id) {
resolve();
return;
}
var isDefaultProperty = context === 'serverdashboard' ? 'isDefaultServerDashboard' : 'isDefault';
var info = getThemeStylesheetInfo(id, isDefaultProperty);
if (currentThemeId && currentThemeId === info.themeId) {
resolve();
return;
}
var linkUrl = info.stylesheetPath;
unloadTheme();
var link = document.createElement('link');
link.setAttribute('rel', 'stylesheet');
link.setAttribute('type', 'text/css');
link.onload = function () {
onThemeLoaded();
resolve();
};
link.setAttribute('href', linkUrl);
document.head.appendChild(link);
themeStyleElement = link;
currentThemeId = info.themeId;
loadThemeResources(info.themeId);
onViewBeforeShow({});
});
};
function onViewBeforeShow(e) {
if (e.detail && e.detail.type === 'video-osd') {
// This removes the space that the scrollbar takes while playing a video
document.body.classList.remove('force-scroll');
return;
}
if (themeResources.backdrop) {
backdrop.setBackdrop(themeResources.backdrop);
}
if (!browser.mobile && userSettings.enableThemeSongs()) {
if (lastSound === 0) {
if (themeResources.themeSong) {
playSound(themeResources.themeSong);
}
} else if ((new Date().getTime() - lastSound) > 30000) {
if (themeResources.effect) {
playSound(themeResources.effect);
}
}
}
// This keeps the scrollbar always present in all pages, so we avoid clipping while switching between pages
// that need the scrollbar and pages that don't.
document.body.classList.add('force-scroll');
}
document.addEventListener('viewshow', onViewBeforeShow);
function playSound(path, volume) {
lastSound = new Date().getTime();
require(['howler'], function (howler) {
/* globals Howl */
try {
var sound = new Howl({
src: [path],
volume: volume || 0.1
});
sound.play();
currentSound = sound;
} catch (err) {
console.error('error playing sound: ' + err);
}
});
}
return skinManager;
});

View file

@ -5,6 +5,9 @@
define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'focusManager', 'browser', 'apphost', 'dom', 'css!./style', 'material-icons', 'paper-icon-button-light'], function (dialogHelper, inputManager, connectionManager, layoutManager, focusManager, browser, appHost, dom) {
'use strict';
browser = browser.default || browser;
focusManager = focusManager.default || focusManager;
/**
* Name of transition event.
*/
@ -38,7 +41,6 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f
if (options.type === 'Primary') {
if (item.AlbumId && item.AlbumPrimaryImageTag) {
options.tag = item.AlbumPrimaryImageTag;
return apiClient.getScaledImageUrl(item.AlbumId, options);
}
@ -64,7 +66,6 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f
}
if (item.BackdropImageTags && item.BackdropImageTags.length) {
options.tag = item.BackdropImageTags[0];
return apiClient.getScaledImageUrl(item.Id, options);
}
@ -130,11 +131,6 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f
var hideTimeout;
/** Last coordinates of the mouse pointer. */
var lastMouseMoveData;
/** Visibility status of the OSD. */
var _osdOpen = false;
// Use autoplay on Chromecast since it is non-interactive.
if (browser.chromecast) options.interactive = false;
/**
* Creates the HTML markup for the dialog and the OSD.
@ -189,7 +185,6 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f
html += '</div>';
}
} else {
html += '<div class="slideshowImage"></div><h1 class="slideshowImageText"></h1>';
}
@ -363,8 +358,6 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f
function getSwiperSlideHtmlFromItem(item) {
return getSwiperSlideHtmlFromSlide({
originalImage: getImgUrl(item, currentOptions.user),
//title: item.Name,
//description: item.Overview
Id: item.Id,
ServerId: item.ServerId
});
@ -545,7 +538,6 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f
return;
}
_osdOpen = true;
element.classList.remove('hide');
var onFinish = function () {
@ -578,7 +570,6 @@ define(['dialogHelper', 'inputManager', 'connectionManager', 'layoutManager', 'f
var onFinish = function () {
element.classList.add('hide');
_osdOpen = false;
};
if (!element.animate) {

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