diff --git a/package.json b/package.json index 9571ab4019..a759484ecf 100644 --- a/package.json +++ b/package.json @@ -92,6 +92,9 @@ "src/components/autoFocuser.js", "src/components/cardbuilder/cardBuilder.js", "src/components/filedownloader.js", + "src/components/images/imageLoader.js", + "src/components/lazyloader/lazyloader-intersectionobserver.js", + "src/components/playback/mediasession.js", "src/components/sanatizefilename.js", "src/components/scrollManager.js", "src/scripts/dfnshelper.js", diff --git a/src/components/images/imageLoader.js b/src/components/images/imageLoader.js index 74e07c7669..f23b407def 100644 --- a/src/components/images/imageLoader.js +++ b/src/components/images/imageLoader.js @@ -1,50 +1,82 @@ -define(['lazyLoader', 'imageFetcher', 'layoutManager', 'browser', 'appSettings', 'userSettings', 'require', 'css!./style'], function (lazyLoader, imageFetcher, layoutManager, browser, appSettings, userSettings, require) { - 'use strict'; - - var self = {}; - - function fillImage(elem, source, enableEffects) { - - if (!elem) { - throw new Error('elem cannot be null'); - } - - if (!source) { - source = elem.getAttribute('data-src'); - } +import * as lazyLoader from 'lazyLoader'; +import * as userSettings from 'userSettings'; +import 'css!./style'; +/* eslint-disable indent */ + export function lazyImage(elem, source = elem.getAttribute('data-src')) { if (!source) { return; } - fillImageElement(elem, source, enableEffects); + fillImageElement(elem, source); } - function fillImageElement(elem, source, enableEffects) { - imageFetcher.loadImage(elem, source).then(function () { + export function fillImage(entry) { + if (!entry) { + throw new Error('entry cannot be null'); + } - if (enableEffects !== false) { - fadeIn(elem); + var source = undefined; + if (entry.target) { + source = entry.target.getAttribute('data-src'); + } else { + source = entry; + } + + if (entry.intersectionRatio > 0) { + if (source) fillImageElement(entry.target, source); + } else if (!source) { + emptyImageElement(entry.target); + } + } + + function fillImageElement(elem, url) { + if (url === undefined) { + throw new Error('url cannot be undefined'); + } + + let preloaderImg = new Image(); + preloaderImg.src = url; + + preloaderImg.addEventListener('load', () => { + if (elem.tagName !== 'IMG') { + elem.style.backgroundImage = "url('" + url + "')"; + } else { + elem.setAttribute('src', url); + } + + if (userSettings.enableFastFadein()) { + elem.classList.add('lazy-image-fadein-fast'); + } else { + elem.classList.add('lazy-image-fadein'); } elem.removeAttribute('data-src'); }); } - function fadeIn(elem) { - if (userSettings.enableFastFadein()) { - elem.classList.add('lazy-image-fadein-fast'); + function emptyImageElement(elem) { + var url; + + if (elem.tagName !== 'IMG') { + url = elem.style.backgroundImage.slice(4, -1).replace(/"/g, ''); + elem.style.backgroundImage = 'none'; } else { - elem.classList.add('lazy-image-fadein'); + url = elem.getAttribute('src'); + elem.setAttribute('src', ''); } + + elem.setAttribute('data-src', url); + + elem.classList.remove('lazy-image-fadein-fast'); + elem.classList.remove('lazy-image-fadein'); } - function lazyChildren(elem) { - + export function lazyChildren(elem) { lazyLoader.lazyChildren(elem, fillImage); } - function getPrimaryImageAspectRatio(items) { + export function getPrimaryImageAspectRatio(items) { var values = []; @@ -104,7 +136,7 @@ define(['lazyLoader', 'imageFetcher', 'layoutManager', 'browser', 'appSettings', return result; } - function fillImages(elems) { + export function fillImages(elems) { for (var i = 0, length = elems.length; i < length; i++) { var elem = elems[0]; @@ -112,10 +144,11 @@ define(['lazyLoader', 'imageFetcher', 'layoutManager', 'browser', 'appSettings', } } - self.fillImages = fillImages; - self.lazyImage = fillImage; - self.lazyChildren = lazyChildren; - self.getPrimaryImageAspectRatio = getPrimaryImageAspectRatio; - - return self; -}); +/* eslint-enable indent */ +export default { + fillImages: fillImages, + fillImage: fillImage, + lazyImage: lazyImage, + lazyChildren: lazyChildren, + getPrimaryImageAspectRatio: getPrimaryImageAspectRatio +}; diff --git a/src/components/images/style.css b/src/components/images/style.css index 2836dd0159..2b9422d55b 100644 --- a/src/components/images/style.css +++ b/src/components/images/style.css @@ -1,44 +1,13 @@ -.lazy-image-fadein { +.cardImageContainer.lazy { opacity: 0; - animation: lazy-image-fadein 330ms ease-in normal both; - -webkit-animation-duration: 0.8s; - -moz-animation-duration: 0.8s; - -o-animation-duration: 0.8s; - animation-duration: 0.8s; - -webkit-animation-name: popInAnimation; - -moz-animation-name: popInAnimation; - -o-animation-name: popInAnimation; - animation-name: popInAnimation; - -webkit-animation-fill-mode: forwards; - -moz-animation-fill-mode: forwards; - -o-animation-fill-mode: forwards; - animation-fill-mode: forwards; - -webkit-animation-timing-function: cubic-bezier(0, 0, 0.5, 1); - -moz-animation-timing-function: cubic-bezier(0, 0, 0.5, 1); - -o-animation-timing-function: cubic-bezier(0, 0, 0.5, 1); - animation-timing-function: cubic-bezier(0, 0, 0.5, 1); } -.lazy-image-fadein-fast { - animation: lazy-image-fadein 160ms ease-in normal both; +.cardImageContainer.lazy.lazy-image-fadein { + opacity: 1; + transition: opacity 0.7s; } -@keyframes lazy-image-fadein { - from { - opacity: 0; - } - - to { - opacity: 1; - } -} - -@keyframes popInAnimation { - 0% { - opacity: 0; - } - - 100% { - opacity: 1; - } +.cardImageContainer.lazy.lazy-image-fadein-fast { + opacity: 1; + transition: opacity 0.2s; } diff --git a/src/components/lazyloader/lazyedgehack.css b/src/components/lazyloader/lazyedgehack.css deleted file mode 100644 index e358872f16..0000000000 --- a/src/components/lazyloader/lazyedgehack.css +++ /dev/null @@ -1,5 +0,0 @@ -.lazy { - /* In edge, intersection observer will not fire on 0px sized elements */ - min-width: 0.1em; - min-height: 0.1em; -} diff --git a/src/components/lazyloader/lazyloader-intersectionobserver.js b/src/components/lazyloader/lazyloader-intersectionobserver.js index 8fe0d377d0..8cf5b9cd0a 100644 --- a/src/components/lazyloader/lazyloader-intersectionobserver.js +++ b/src/components/lazyloader/lazyloader-intersectionobserver.js @@ -1,103 +1,67 @@ -define(['require', 'browser'], function (require, browser) { - 'use strict'; +/* eslint-disable indent */ + export class LazyLoader { + constructor(options) { + this.options = options; + } - function LazyLoader(options) { + createObserver() { + const callback = this.options.callback; - this.options = options; - } + const observer = new IntersectionObserver( + (entries) => { + entries.forEach(entry => { + callback(entry); + }, + {rootMargin: '50%'}); + }); - if (browser.edge) { - require(['css!./lazyedgehack']); - } + this.observer = observer; + } - LazyLoader.prototype.createObserver = function () { + addElements(elements) { + let observer = this.observer; - var observerOptions = {}; - var options = this.options; - var loadedCount = 0; - var callback = options.callback; - - observerOptions.rootMargin = '50%'; - - var observerId = 'obs' + new Date().getTime(); - - var self = this; - var observer = new IntersectionObserver(function (entries) { - for (var j = 0, length2 = entries.length; j < length2; j++) { - var entry = entries[j]; - - if (entry.intersectionRatio > 0) { - - // Stop watching and load the image - var target = entry.target; - - observer.unobserve(target); - - if (!target[observerId]) { - target[observerId] = 1; - callback(target); - loadedCount++; - - if (loadedCount >= self.elementCount) { - self.destroyObserver(); - } - } - } + if (!observer) { + this.createObserver(); + observer = this.observer; } - }, - observerOptions - ); - this.observer = observer; - }; - - LazyLoader.prototype.addElements = function (elements) { - - var observer = this.observer; - - if (!observer) { - this.createObserver(); - observer = this.observer; + Array.from(elements).forEach(element => { + observer.observe(element); + }); } - this.elementCount = (this.elementCount || 0) + elements.length; + destroyObserver() { + const observer = this.observer; - for (var i = 0, length = elements.length; i < length; i++) { - observer.observe(elements[i]); + if (observer) { + observer.disconnect(); + this.observer = null; + } } - }; - LazyLoader.prototype.destroyObserver = function (elements) { - - var observer = this.observer; - - if (observer) { - observer.disconnect(); - this.observer = null; + destroy() { + this.destroyObserver(); + this.options = null; } - }; - - LazyLoader.prototype.destroy = function (elements) { - - this.destroyObserver(); - this.options = null; - }; + } function unveilElements(elements, root, callback) { - if (!elements.length) { return; } - var lazyLoader = new LazyLoader({ + const lazyLoader = new LazyLoader({ callback: callback }); lazyLoader.addElements(elements); } - LazyLoader.lazyChildren = function (elem, callback) { - + export function lazyChildren(elem, callback) { unveilElements(elem.getElementsByClassName('lazy'), elem, callback); - }; + } - return LazyLoader; -}); +/* eslint-enable indent */ +export default { + LazyLoader: LazyLoader, + lazyChildren: lazyChildren +}; diff --git a/src/components/lazyloader/lazyloader-scroll.js b/src/components/lazyloader/lazyloader-scroll.js deleted file mode 100644 index 2704c0f7be..0000000000 --- a/src/components/lazyloader/lazyloader-scroll.js +++ /dev/null @@ -1,185 +0,0 @@ -define(['visibleinviewport', 'dom', 'browser'], function (visibleinviewport, dom, browser) { - 'use strict'; - - var thresholdX; - var thresholdY; - - function resetThresholds() { - - var threshold = 0.3; - - thresholdX = screen.availWidth * threshold; - thresholdY = screen.availHeight * threshold; - } - - function resetThresholdsOnTimer() { - - setTimeout(resetThresholds, 500); - } - - if (browser.iOS) { - dom.addEventListener(window, 'orientationchange', resetThresholdsOnTimer, { passive: true }); - dom.addEventListener(window, 'resize', resetThresholdsOnTimer, { passive: true }); - } else { - dom.addEventListener(window, 'orientationchange', resetThresholds, { passive: true }); - dom.addEventListener(window, 'resize', resetThresholds, { passive: true }); - } - resetThresholds(); - - function isVisible(elem) { - return visibleinviewport(elem, true, thresholdX, thresholdY); - } - - var wheelEvent = (document.implementation.hasFeature('Event.wheel', '3.0') ? 'wheel' : 'mousewheel'); - var self = {}; - - function cancelAll(tokens) { - for (var i = 0, length = tokens.length; i < length; i++) { - - tokens[i] = true; - } - } - - function unveilElementsInternal(instance, callback) { - - var unveiledElements = []; - var cancellationTokens = []; - var loadedCount = 0; - - function unveilInternal(tokenIndex) { - - var anyFound = false; - var out = false; - - var elements = instance.elements; - // TODO: This out construct assumes left to right, top to bottom - - for (var i = 0, length = elements.length; i < length; i++) { - - if (cancellationTokens[tokenIndex]) { - return; - } - if (unveiledElements[i]) { - continue; - } - var elem = elements[i]; - if (!out && isVisible(elem)) { - anyFound = true; - unveiledElements[i] = true; - callback(elem); - loadedCount++; - } else { - - if (anyFound) { - out = true; - } - } - } - - if (loadedCount >= elements.length) { - dom.removeEventListener(document, 'focus', unveil, { - capture: true, - passive: true - }); - dom.removeEventListener(document, 'scroll', unveil, { - capture: true, - passive: true - }); - dom.removeEventListener(document, wheelEvent, unveil, { - capture: true, - passive: true - }); - dom.removeEventListener(window, 'resize', unveil, { - capture: true, - passive: true - }); - } - } - - function unveil() { - - cancelAll(cancellationTokens); - - var index = cancellationTokens.length; - cancellationTokens.length++; - - setTimeout(function () { - unveilInternal(index); - }, 1); - } - - dom.addEventListener(document, 'focus', unveil, { - capture: true, - passive: true - }); - dom.addEventListener(document, 'scroll', unveil, { - capture: true, - passive: true - }); - dom.addEventListener(document, wheelEvent, unveil, { - capture: true, - passive: true - }); - dom.addEventListener(window, 'resize', unveil, { - capture: true, - passive: true - }); - - unveil(); - } - - function LazyLoader(options) { - - this.options = options; - } - - LazyLoader.prototype.createObserver = function () { - - unveilElementsInternal(this, this.options.callback); - this.observer = 1; - }; - - LazyLoader.prototype.addElements = function (elements) { - - this.elements = this.elements || []; - - for (var i = 0, length = elements.length; i < length; i++) { - this.elements.push(elements[i]); - } - - var observer = this.observer; - - if (!observer) { - this.createObserver(); - } - - }; - - LazyLoader.prototype.destroyObserver = function (elements) { - - }; - - LazyLoader.prototype.destroy = function (elements) { - - this.destroyObserver(); - this.options = null; - }; - - function unveilElements(elements, root, callback) { - - if (!elements.length) { - return; - } - var lazyLoader = new LazyLoader({ - callback: callback - }); - lazyLoader.addElements(elements); - } - - LazyLoader.lazyChildren = function (elem, callback) { - - unveilElements(elem.getElementsByClassName('lazy'), elem, callback); - }; - - return LazyLoader; -}); diff --git a/src/components/playback/mediasession.js b/src/components/playback/mediasession.js index 937f08dbfe..2dd10b3484 100644 --- a/src/components/playback/mediasession.js +++ b/src/components/playback/mediasession.js @@ -1,45 +1,28 @@ -define(['playbackManager', 'nowPlayingHelper', 'events', 'connectionManager'], function (playbackManager, nowPlayingHelper, events, connectionManager) { - 'use strict'; - - // no support for mediaSession - if (!navigator.mediaSession && !window.NativeShell) { - return; - } +import playbackManager from 'playbackManager'; +import nowPlayingHelper from 'nowPlayingHelper'; +import events from 'events'; +import connectionManager from 'connectionManager'; +/* eslint-disable indent */ // Reports media playback to the device for lock screen control - var currentPlayer; - var lastUpdateTime = 0; + let currentPlayer; - function seriesImageUrl(item, options) { + function seriesImageUrl(item, options = {}) { + options.type = options.type || 'Primary'; if (item.Type !== 'Episode') { return null; - } - - options = options || {}; - 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); - } - } - - if (options.type === 'Thumb') { + } else if (options.type === 'Primary' && item.SeriesPrimaryImageTag) { + options.tag = item.SeriesPrimaryImageTag; + return connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options); + } else if (options.type === 'Thumb') { if (item.SeriesThumbImageTag) { - options.tag = item.SeriesThumbImageTag; return connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options); - } - if (item.ParentThumbImageTag) { - + } else if (item.ParentThumbImageTag) { options.tag = item.ParentThumbImageTag; return connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.ParentThumbItemId, options); @@ -49,122 +32,101 @@ define(['playbackManager', 'nowPlayingHelper', 'events', 'connectionManager'], f return null; } - function imageUrl(item, options) { - - options = options || {}; + function imageUrl(item, options = {}) { 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.Id, options); - } - - if (item.AlbumId && item.AlbumPrimaryImageTag) { - + } else if (item.AlbumId && item.AlbumPrimaryImageTag) { options.tag = item.AlbumPrimaryImageTag; + return connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.AlbumId, options); } return null; } - function pushImageUrl(item, imageOptions, list) { - var url = seriesImageUrl(item, imageOptions) || imageUrl(item, imageOptions); + function getImageUrl(item, imageOptions = {}) { + const url = seriesImageUrl(item, imageOptions) || imageUrl(item, imageOptions); if (url) { - var height = imageOptions.height || imageOptions.maxHeight; + const height = imageOptions.height || imageOptions.maxHeight; - list.push({ + return { src: url, sizes: height + 'x' + height - }); + }; + } else { + return null; } } - function getImageUrls(item) { + function getImageUrls(item, imageSizes = [96, 128, 192, 256, 384, 512]) { + const list = []; - var list = []; - - pushImageUrl(item, {height: 96}, list); - pushImageUrl(item, {height: 128}, list); - pushImageUrl(item, {height: 192}, list); - pushImageUrl(item, {height: 256}, list); - pushImageUrl(item, {height: 384}, list); - pushImageUrl(item, {height: 512}, list); + imageSizes.forEach((size) => { + const url = getImageUrl(item, {height: size}); + if (url !== null) { + list.push(url); + } + }); return list; } function updatePlayerState(player, state, eventName) { // Don't go crazy reporting position changes - if (eventName == 'timeupdate') { + if (eventName === 'timeupdate') { // Only report if this item hasn't been reported yet, or if there's an actual playback change. // Don't report on simple time updates return; } - var item = state.NowPlayingItem; + const item = state.NowPlayingItem; if (!item) { hideMediaControls(); return; } - if (eventName == 'init') { // transform "init" event into "timeupdate" to restraint update rate + if (eventName === 'init') { // transform "init" event into "timeupdate" to restraint update rate eventName = 'timeupdate'; } - var isVideo = item.MediaType === 'Video'; - var isLocalPlayer = player.isLocalPlayer || false; + const isVideo = item.MediaType === 'Video'; + const isLocalPlayer = player.isLocalPlayer || false; // Local players do their own notifications if (isLocalPlayer && isVideo) { return; } - var playState = state.PlayState || {}; - var parts = nowPlayingHelper.getNowPlayingNames(item); - var artist = parts[parts.length - 1].text; - var title = parts.length === 1 ? '' : parts[0].text; - var albumArtist; + const playState = state.PlayState || {}; + const parts = nowPlayingHelper.getNowPlayingNames(item); + const artist = parts[parts.length - 1].text; + const title = parts.length === 1 ? '' : parts[0].text; - if (item.AlbumArtists && item.AlbumArtists[0]) { - albumArtist = item.AlbumArtists[0].Name; - } - - var album = item.Album || ''; - var itemId = item.Id; + const album = item.Album || ''; + const itemId = item.Id; // Convert to ms - var duration = parseInt(item.RunTimeTicks ? (item.RunTimeTicks / 10000) : 0); - var currentTime = parseInt(playState.PositionTicks ? (playState.PositionTicks / 10000) : 0); + const duration = parseInt(item.RunTimeTicks ? (item.RunTimeTicks / 10000) : 0); + const currentTime = parseInt(playState.PositionTicks ? (playState.PositionTicks / 10000) : 0); - var isPaused = playState.IsPaused || false; - var canSeek = playState.CanSeek || false; + const isPaused = playState.IsPaused || false; + const canSeek = playState.CanSeek || false; - if (navigator.mediaSession) { + if ('mediaSession' in navigator) { navigator.mediaSession.metadata = new MediaMetadata({ title: title, artist: artist, album: album, - artwork: getImageUrls(item), - albumArtist: albumArtist, - currentTime: currentTime, - duration: duration, - paused: isPaused, - itemId: itemId, - mediaType: item.MediaType + artwork: getImageUrls(item) }); } else { - var imageUrl = []; - pushImageUrl(item, {maxHeight: 400}, imageUrl); - - if (imageUrl.length) { - imageUrl = imageUrl[0].src; - } else { - imageUrl = null; - } + let itemImageUrl = seriesImageUrl(item, { maxHeight: 3000 }) || imageUrl(item, { maxHeight: 3000 }); window.NativeShell.updateMediaSession({ action: eventName, @@ -175,7 +137,7 @@ define(['playbackManager', 'nowPlayingHelper', 'events', 'connectionManager'], f album: album, duration: duration, position: currentTime, - imageUrl: imageUrl, + imageUrl: itemImageUrl, canSeek: canSeek, isPaused: isPaused }); @@ -183,37 +145,25 @@ define(['playbackManager', 'nowPlayingHelper', 'events', 'connectionManager'], f } function onGeneralEvent(e) { + const state = playbackManager.getPlayerState(this); - var player = this; - var state = playbackManager.getPlayerState(player); - - updatePlayerState(player, state, e.type); + updatePlayerState(this, state, e.type); } function onStateChanged(e, state) { - - var player = this; - updatePlayerState(player, state, 'statechange'); + updatePlayerState(this, state, 'statechange'); } function onPlaybackStart(e, state) { - - var player = this; - - updatePlayerState(player, state, e.type); + updatePlayerState(this, state, e.type); } - function onPlaybackStopped(e, state) { - - var player = this; - + function onPlaybackStopped() { hideMediaControls(); } function releaseCurrentPlayer() { - if (currentPlayer) { - events.off(currentPlayer, 'playbackstart', onPlaybackStart); events.off(currentPlayer, 'playbackstop', onPlaybackStopped); events.off(currentPlayer, 'unpause', onGeneralEvent); @@ -228,9 +178,7 @@ define(['playbackManager', 'nowPlayingHelper', 'events', 'connectionManager'], f } function hideMediaControls() { - lastUpdateTime = 0; - - if (navigator.mediaSession) { + if ('mediaSession' in navigator) { navigator.mediaSession.metadata = null; } else { window.NativeShell.hideMediaSession(); @@ -238,7 +186,6 @@ define(['playbackManager', 'nowPlayingHelper', 'events', 'connectionManager'], f } function bindToPlayer(player) { - releaseCurrentPlayer(); if (!player) { @@ -247,7 +194,7 @@ define(['playbackManager', 'nowPlayingHelper', 'events', 'connectionManager'], f currentPlayer = player; - var state = playbackManager.getPlayerState(player); + const state = playbackManager.getPlayerState(player); updatePlayerState(player, state, 'init'); events.on(currentPlayer, 'playbackstart', onPlaybackStart); @@ -261,8 +208,8 @@ define(['playbackManager', 'nowPlayingHelper', 'events', 'connectionManager'], f function execute(name) { playbackManager[name](currentPlayer); } - if (navigator.mediaSession) { + if ('mediaSession' in navigator) { navigator.mediaSession.setActionHandler('previoustrack', function () { execute('previousTrack'); }); @@ -289,9 +236,9 @@ define(['playbackManager', 'nowPlayingHelper', 'events', 'connectionManager'], f } events.on(playbackManager, 'playerchange', function () { - bindToPlayer(playbackManager.getCurrentPlayer()); }); bindToPlayer(playbackManager.getCurrentPlayer()); -}); + +/* eslint-enable indent */ diff --git a/src/controllers/itemdetailpage.js b/src/controllers/itemdetailpage.js index ade68234a2..45342208ea 100644 --- a/src/controllers/itemdetailpage.js +++ b/src/controllers/itemdetailpage.js @@ -487,7 +487,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti tag: item.ImageTags.Thumb }); page.classList.remove('noBackdrop'); - imageLoader.lazyImage(itemBackdropElement, imgUrl, false); + imageLoader.lazyImage(itemBackdropElement, imgUrl); hasbackdrop = true; } else if (usePrimaryImage && item.ImageTags && item.ImageTags.Primary) { imgUrl = apiClient.getScaledImageUrl(item.Id, { @@ -497,7 +497,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti tag: item.ImageTags.Primary }); page.classList.remove('noBackdrop'); - imageLoader.lazyImage(itemBackdropElement, imgUrl, false); + imageLoader.lazyImage(itemBackdropElement, imgUrl); hasbackdrop = true; } else if (item.BackdropImageTags && item.BackdropImageTags.length) { imgUrl = apiClient.getScaledImageUrl(item.Id, { @@ -507,7 +507,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti tag: item.BackdropImageTags[0] }); page.classList.remove('noBackdrop'); - imageLoader.lazyImage(itemBackdropElement, imgUrl, false); + imageLoader.lazyImage(itemBackdropElement, imgUrl); hasbackdrop = true; } else if (item.ParentBackdropItemId && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) { imgUrl = apiClient.getScaledImageUrl(item.ParentBackdropItemId, { @@ -517,7 +517,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti tag: item.ParentBackdropImageTags[0] }); page.classList.remove('noBackdrop'); - imageLoader.lazyImage(itemBackdropElement, imgUrl, false); + imageLoader.lazyImage(itemBackdropElement, imgUrl); hasbackdrop = true; } else if (item.ImageTags && item.ImageTags.Thumb) { imgUrl = apiClient.getScaledImageUrl(item.Id, { @@ -527,7 +527,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti tag: item.ImageTags.Thumb }); page.classList.remove('noBackdrop'); - imageLoader.lazyImage(itemBackdropElement, imgUrl, false); + imageLoader.lazyImage(itemBackdropElement, imgUrl); hasbackdrop = true; } else { itemBackdropElement.style.backgroundImage = ''; diff --git a/src/controllers/movies/moviegenres.js b/src/controllers/movies/moviegenres.js index 073697625c..e8e49ff9da 100644 --- a/src/controllers/movies/moviegenres.js +++ b/src/controllers/movies/moviegenres.js @@ -50,7 +50,8 @@ define(['layoutManager', 'loading', 'libraryBrowser', 'cardBuilder', 'lazyLoader return enableScrollX() ? 'overflowPortrait' : 'portrait'; } - function fillItemsContainer(elem) { + function fillItemsContainer(entry) { + var elem = entry.target; var id = elem.getAttribute('data-id'); var viewStyle = self.getCurrentViewStyle(); var limit = 'Thumb' == viewStyle || 'ThumbCard' == viewStyle ? 5 : 9; diff --git a/src/controllers/shows/tvgenres.js b/src/controllers/shows/tvgenres.js index f6fa1e62ae..de38763e99 100644 --- a/src/controllers/shows/tvgenres.js +++ b/src/controllers/shows/tvgenres.js @@ -50,7 +50,8 @@ define(['layoutManager', 'loading', 'libraryBrowser', 'cardBuilder', 'lazyLoader return enableScrollX() ? 'overflowPortrait' : 'portrait'; } - function fillItemsContainer(elem) { + function fillItemsContainer(entry) { + var elem = entry.target; var id = elem.getAttribute('data-id'); var viewStyle = self.getCurrentViewStyle(); var limit = 'Thumb' == viewStyle || 'ThumbCard' == viewStyle ? 5 : 9; diff --git a/src/libraries/visibleinviewport.js b/src/libraries/visibleinviewport.js deleted file mode 100644 index a48dbd3a1d..0000000000 --- a/src/libraries/visibleinviewport.js +++ /dev/null @@ -1,41 +0,0 @@ -define(['dom'], function (dom) { - 'use strict'; - - /** - * Copyright 2012, Digital Fusion - * Licensed under the MIT license. - * http://teamdf.com/jquery-plugins/license/ - * - * @author Sam Sehnert - * @desc A small plugin that checks whether elements are within - * the user visible viewport of a web browser. - * only accounts for vertical position, not horizontal. - */ - function visibleInViewport(elem, partial, thresholdX, thresholdY) { - - thresholdX = thresholdX || 0; - thresholdY = thresholdY || 0; - - if (!elem.getBoundingClientRect) { - return true; - } - - var windowSize = dom.getWindowSize(); - - var vpWidth = windowSize.innerWidth; - var vpHeight = windowSize.innerHeight; - - // Use this native browser method, if available. - var rec = elem.getBoundingClientRect(); - var tViz = rec.top >= 0 && rec.top < vpHeight + thresholdY; - var bViz = rec.bottom > 0 && rec.bottom <= vpHeight + thresholdY; - var lViz = rec.left >= 0 && rec.left < vpWidth + thresholdX; - var rViz = rec.right > 0 && rec.right <= vpWidth + thresholdX; - var vVisible = partial ? tViz || bViz : tViz && bViz; - var hVisible = partial ? lViz || rViz : lViz && rViz; - - return vVisible && hVisible; - } - - return visibleInViewport; -}); diff --git a/src/scripts/settings/userSettings.js b/src/scripts/settings/userSettings.js index 12748eac20..072e3f3062 100644 --- a/src/scripts/settings/userSettings.js +++ b/src/scripts/settings/userSettings.js @@ -265,3 +265,33 @@ import events from 'events'; } /* eslint-enable indent */ +export default { + setUserInfo: setUserInfo, + getData: getData, + importFrom: importFrom, + set: set, + get: get, + serverConfig: serverConfig, + enableCinemaMode: enableCinemaMode, + enableNextVideoInfoOverlay: enableNextVideoInfoOverlay, + enableThemeSongs: enableThemeSongs, + enableThemeVideos: enableThemeVideos, + enableFastFadein: enableFastFadein, + enableBackdrops: enableBackdrops, + language: language, + dateTimeLocale: dateTimeLocale, + skipBackLength: skipBackLength, + skipForwardLength: skipForwardLength, + dashboardTheme: dashboardTheme, + skin: skin, + theme: theme, + screensaver: screensaver, + libraryPageSize: libraryPageSize, + soundEffects: soundEffects, + loadQuerySettings: loadQuerySettings, + saveQuerySettings: saveQuerySettings, + getSubtitleAppearanceSettings: getSubtitleAppearanceSettings, + setSubtitleAppearanceSettings: setSubtitleAppearanceSettings, + setFilter: setFilter, + getFilter: getFilter +}; diff --git a/src/scripts/site.js b/src/scripts/site.js index 0727139660..7c884d73d9 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -375,12 +375,7 @@ var AppInfo = {}; define('filesystem', [scriptsPath + '/filesystem'], returnFirstDependency); - if (window.IntersectionObserver && !browser.edge) { - define('lazyLoader', [componentsPath + '/lazyloader/lazyloader-intersectionobserver'], returnFirstDependency); - } else { - define('lazyLoader', [componentsPath + '/lazyloader/lazyloader-scroll'], returnFirstDependency); - } - + define('lazyLoader', [componentsPath + '/lazyloader/lazyloader-intersectionobserver'], returnFirstDependency); define('shell', [componentsPath + '/shell'], returnFirstDependency); if ('registerElement' in document) { @@ -391,13 +386,10 @@ var AppInfo = {}; define('registerElement', ['document-register-element'], returnFirstDependency); } - define('imageFetcher', [componentsPath + '/images/imageFetcher'], returnFirstDependency); - - var preferNativeAlerts = browser.tv; - define('alert', [componentsPath + '/alert'], returnFirstDependency); defineResizeObserver(); + define('dialog', [componentsPath + '/dialog/dialog'], returnFirstDependency); define('confirm', [componentsPath + '/confirm/confirm'], returnFirstDependency); @@ -563,7 +555,10 @@ var AppInfo = {}; require(['components/playback/volumeosd']); } - require(['mediaSession', 'serverNotifications']); + if (navigator.mediaSession || window.NativeShell) { + require(['mediaSession']); + } + require(['serverNotifications']); require(['date-fns', 'date-fns/locale']); if (!browser.tv && !browser.xboxOne) {