From 985396af14ce0fc37a1f418561f60c92fbf40664 Mon Sep 17 00:00:00 2001 From: grafixeyehero Date: Tue, 30 Jun 2020 00:47:34 +0300 Subject: [PATCH 001/232] Move tvlatest tab to suggestions section --- src/controllers/shows/tvlatest.js | 64 ------ src/controllers/shows/tvrecommended.js | 276 +++++++++++++++---------- src/tv.html | 28 ++- 3 files changed, 176 insertions(+), 192 deletions(-) delete mode 100644 src/controllers/shows/tvlatest.js diff --git a/src/controllers/shows/tvlatest.js b/src/controllers/shows/tvlatest.js deleted file mode 100644 index 08e420a595..0000000000 --- a/src/controllers/shows/tvlatest.js +++ /dev/null @@ -1,64 +0,0 @@ -define(['loading', 'components/groupedcards', 'cardBuilder', 'apphost', 'imageLoader'], function (loading, groupedcards, cardBuilder, appHost, imageLoader) { - 'use strict'; - - function getLatestPromise(context, params) { - loading.show(); - var userId = ApiClient.getCurrentUserId(); - var parentId = params.topParentId; - var options = { - IncludeItemTypes: 'Episode', - Limit: 30, - Fields: 'PrimaryImageAspectRatio,BasicSyncInfo', - ParentId: parentId, - ImageTypeLimit: 1, - EnableImageTypes: 'Primary,Backdrop,Thumb' - }; - return ApiClient.getJSON(ApiClient.getUrl('Users/' + userId + '/Items/Latest', options)); - } - - function loadLatest(context, params, promise) { - promise.then(function (items) { - var html = ''; - appHost.supports('imageanalysis'); - html += cardBuilder.getCardsHtml({ - items: items, - shape: 'backdrop', - preferThumb: true, - showTitle: true, - showSeriesYear: true, - showParentTitle: true, - overlayText: false, - cardLayout: false, - showUnplayedIndicator: false, - showChildCountIndicator: true, - centerText: true, - lazy: true, - overlayPlayButton: true, - lines: 2 - }); - var elem = context.querySelector('#latestEpisodes'); - elem.innerHTML = html; - imageLoader.lazyChildren(elem); - loading.hide(); - - require(['autoFocuser'], function (autoFocuser) { - autoFocuser.autoFocus(context); - }); - }); - } - - return function (view, params, tabContent) { - var self = this; - var latestPromise; - - self.preRender = function () { - latestPromise = getLatestPromise(view, params); - }; - - self.renderTab = function () { - loadLatest(tabContent, params, latestPromise); - }; - - tabContent.querySelector('#latestEpisodes').addEventListener('click', groupedcards.onItemsContainerClick); - }; -}); diff --git a/src/controllers/shows/tvrecommended.js b/src/controllers/shows/tvrecommended.js index 8087a03096..fc165cf1e5 100644 --- a/src/controllers/shows/tvrecommended.js +++ b/src/controllers/shows/tvrecommended.js @@ -6,8 +6,6 @@ define(['events', 'inputManager', 'libraryMenu', 'layoutManager', 'loading', 'do name: globalize.translate('TabShows') }, { name: globalize.translate('TabSuggestions') - }, { - name: globalize.translate('TabLatest') }, { name: globalize.translate('TabUpcoming') }, { @@ -27,14 +25,11 @@ define(['events', 'inputManager', 'libraryMenu', 'layoutManager', 'loading', 'do case 'suggestions': return 1; - case 'latest': - return 2; - case 'favorites': return 1; case 'genres': - return 4; + return 3; default: return 0; @@ -59,101 +54,159 @@ define(['events', 'inputManager', 'libraryMenu', 'layoutManager', 'loading', 'do } } + function initSuggestedTab(page, tabContent) { + var containers = tabContent.querySelectorAll('.itemsContainer'); + + for (var i = 0, length = containers.length; i < length; i++) { + setScrollClasses(containers[i], enableScrollX()); + } + } + + function loadSuggestionsTab(view, params, tabContent) { + var parentId = params.topParentId; + var userId = ApiClient.getCurrentUserId(); + console.debug('loadSuggestionsTab'); + loadResume(tabContent, userId, parentId); + loadLatest(tabContent, userId, parentId); + loadNextUp(tabContent, userId, parentId); + } + + function loadResume(view, userId, parentId) { + var screenWidth = dom.getWindowSize().innerWidth; + var options = { + SortBy: 'DatePlayed', + SortOrder: 'Descending', + IncludeItemTypes: 'Episode', + Filters: 'IsResumable', + Limit: screenWidth >= 1920 ? 5 : screenWidth >= 1600 ? 5 : 3, + Recursive: true, + Fields: 'PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo', + CollapseBoxSetItems: false, + ParentId: parentId, + ImageTypeLimit: 1, + EnableImageTypes: 'Primary,Backdrop,Banner,Thumb', + EnableTotalRecordCount: false + }; + ApiClient.getItems(userId, options).then(function (result) { + if (result.Items.length) { + view.querySelector('#resumableSection').classList.remove('hide'); + } else { + view.querySelector('#resumableSection').classList.add('hide'); + } + + var allowBottomPadding = !enableScrollX(); + var container = view.querySelector('#resumableItems'); + cardBuilder.buildCards(result.Items, { + itemsContainer: container, + preferThumb: true, + shape: getThumbShape(), + scalable: true, + overlayPlayButton: true, + allowBottomPadding: allowBottomPadding, + cardLayout: false, + showTitle: true, + showYear: true, + centerText: true + }); + loading.hide(); + + require(['autoFocuser'], function (autoFocuser) { + autoFocuser.autoFocus(view); + }); + }); + } + + function loadLatest(view, userId, parentId) { + var options = { + userId: userId, + IncludeItemTypes: 'Episode', + Limit: 30, + Fields: 'PrimaryImageAspectRatio,BasicSyncInfo', + ParentId: parentId, + ImageTypeLimit: 1, + EnableImageTypes: 'Primary,Backdrop,Thumb' + }; + ApiClient.getLatestItems(options).then(function (items) { + var section = view.querySelector('#latestItemsSection'); + var allowBottomPadding = !enableScrollX(); + var container = section.querySelector('#latestEpisodesItems'); + cardBuilder.buildCards(items, { + parentContainer: section, + itemsContainer: container, + items: items, + shape: 'backdrop', + preferThumb: true, + showTitle: true, + showSeriesYear: true, + showParentTitle: true, + overlayText: false, + cardLayout: false, + allowBottomPadding: allowBottomPadding, + showUnplayedIndicator: false, + showChildCountIndicator: true, + centerText: true, + lazy: true, + overlayPlayButton: true, + lines: 2 + }); + loading.hide(); + + require(['autoFocuser'], function (autoFocuser) { + autoFocuser.autoFocus(view); + }); + }); + } + + function loadNextUp(view, userId, parentId) { + var query = { + userId: userId, + Limit: 24, + Fields: 'PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo', + ParentId: parentId, + ImageTypeLimit: 1, + EnableImageTypes: 'Primary,Backdrop,Thumb', + EnableTotalRecordCount: false + }; + query.ParentId = libraryMenu.getTopParentId(); + ApiClient.getNextUpEpisodes(query).then(function (result) { + if (result.Items.length) { + view.querySelector('.noNextUpItems').classList.add('hide'); + } else { + view.querySelector('.noNextUpItems').classList.remove('hide'); + } + + var section = view.querySelector('#nextUpItemsSection'); + var container = section.querySelector('#nextUpItems'); + cardBuilder.buildCards(result.Items, { + parentContainer: section, + itemsContainer: container, + preferThumb: true, + shape: 'backdrop', + scalable: true, + showTitle: true, + showParentTitle: true, + overlayText: false, + centerText: true, + overlayPlayButton: true, + cardLayout: false + }); + loading.hide(); + + require(['autoFocuser'], function (autoFocuser) { + autoFocuser.autoFocus(view); + }); + }); + } + + function enableScrollX() { + return !layoutManager.desktop; + } + + function getThumbShape() { + return enableScrollX() ? 'overflowBackdrop' : 'backdrop'; + } + return function (view, params) { - function reload() { - loading.show(); - loadResume(); - loadNextUp(); - } - - function loadNextUp() { - var query = { - Limit: 24, - Fields: 'PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo', - UserId: ApiClient.getCurrentUserId(), - ImageTypeLimit: 1, - EnableImageTypes: 'Primary,Backdrop,Thumb', - EnableTotalRecordCount: false - }; - query.ParentId = libraryMenu.getTopParentId(); - ApiClient.getNextUpEpisodes(query).then(function (result) { - if (result.Items.length) { - view.querySelector('.noNextUpItems').classList.add('hide'); - } else { - view.querySelector('.noNextUpItems').classList.remove('hide'); - } - - var container = view.querySelector('#nextUpItems'); - cardBuilder.buildCards(result.Items, { - itemsContainer: container, - preferThumb: true, - shape: 'backdrop', - scalable: true, - showTitle: true, - showParentTitle: true, - overlayText: false, - centerText: true, - overlayPlayButton: true, - cardLayout: false - }); - loading.hide(); - - require(['autoFocuser'], function (autoFocuser) { - autoFocuser.autoFocus(view); - }); - }); - } - - function enableScrollX() { - return !layoutManager.desktop; - } - - function getThumbShape() { - return enableScrollX() ? 'overflowBackdrop' : 'backdrop'; - } - - function loadResume() { - var parentId = libraryMenu.getTopParentId(); - var screenWidth = dom.getWindowSize().innerWidth; - var limit = screenWidth >= 1600 ? 5 : 6; - var options = { - SortBy: 'DatePlayed', - SortOrder: 'Descending', - IncludeItemTypes: 'Episode', - Filters: 'IsResumable', - Limit: limit, - Recursive: true, - Fields: 'PrimaryImageAspectRatio,SeriesInfo,UserData,BasicSyncInfo', - ExcludeLocationTypes: 'Virtual', - ParentId: parentId, - ImageTypeLimit: 1, - EnableImageTypes: 'Primary,Backdrop,Thumb', - EnableTotalRecordCount: false - }; - ApiClient.getItems(ApiClient.getCurrentUserId(), options).then(function (result) { - if (result.Items.length) { - view.querySelector('#resumableSection').classList.remove('hide'); - } else { - view.querySelector('#resumableSection').classList.add('hide'); - } - - var allowBottomPadding = !enableScrollX(); - var container = view.querySelector('#resumableItems'); - cardBuilder.buildCards(result.Items, { - itemsContainer: container, - preferThumb: true, - shape: getThumbShape(), - scalable: true, - showTitle: true, - showParentTitle: true, - overlayText: false, - centerText: true, - overlayPlayButton: true, - allowBottomPadding: allowBottomPadding, - cardLayout: false - }); - }); - } function onBeforeTabChange(e) { preLoadTab(view, parseInt(e.detail.selectedTabIndex)); @@ -184,26 +237,22 @@ define(['events', 'inputManager', 'libraryMenu', 'layoutManager', 'loading', 'do break; case 2: - depends.push('controllers/shows/tvlatest'); - break; - - case 3: depends.push('controllers/shows/tvupcoming'); break; - case 4: + case 3: depends.push('controllers/shows/tvgenres'); break; - case 5: + case 4: depends.push('controllers/shows/tvstudios'); break; - case 6: + case 5: depends.push('controllers/shows/episodes'); break; - case 7: + case 6: depends.push('scripts/searchtab'); } @@ -222,7 +271,7 @@ define(['events', 'inputManager', 'libraryMenu', 'layoutManager', 'loading', 'do if (index === 1) { controller = self; - } else if (index === 7) { + } else if (index === 6) { controller = new controllerFactory(view, tabContent, { collectionType: 'tvshows', parentId: params.topParentId @@ -289,19 +338,20 @@ define(['events', 'inputManager', 'libraryMenu', 'layoutManager', 'loading', 'do var self = this; var currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId)); var initialTabIndex = currentTabIndex; + var suggestionsTabIndex = 1; self.initTab = function () { - var tabContent = self.tabContent; - setScrollClasses(tabContent.querySelector('#resumableItems'), enableScrollX()); + var tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']"); + initSuggestedTab(view, tabContent); }; self.renderTab = function () { - reload(); + var tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']"); + loadSuggestionsTab(view, params, tabContent); }; var tabControllers = []; var renderedTabs = []; - setScrollClasses(view.querySelector('#resumableItems'), enableScrollX()); view.addEventListener('viewshow', function (e) { isViewRestored = e.detail.isRestored; initTabs(); diff --git a/src/tv.html b/src/tv.html index ceb5c51b44..c646ecdb44 100644 --- a/src/tv.html +++ b/src/tv.html @@ -23,8 +23,15 @@
+
+
+

${HeaderLatestEpisodes}

+
-
+
+
+ +

${HeaderNextUp}

@@ -33,16 +40,7 @@
-
-
-
-

${HeaderLatestEpisodes}

-
-
-
-
-
-
+
-
+
-
+
-
+
@@ -69,6 +67,6 @@
-
+
From 6d5ed18386ec407f8c9216ac6e145237d89a3fe0 Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Thu, 20 Aug 2020 12:27:25 +0200 Subject: [PATCH 002/232] Redesign OSD and Up Next dialog --- src/assets/css/videoosd.css | 34 +++-- src/components/upnextdialog/upnextdialog.css | 10 +- src/components/upnextdialog/upnextdialog.js | 75 ----------- src/controllers/playback/video/index.html | 42 +++--- src/controllers/playback/video/index.js | 135 ++----------------- 5 files changed, 57 insertions(+), 239 deletions(-) diff --git a/src/assets/css/videoosd.css b/src/assets/css/videoosd.css index 808915e58b..7273121f53 100644 --- a/src/assets/css/videoosd.css +++ b/src/assets/css/videoosd.css @@ -14,21 +14,23 @@ } .osdHeader { - -webkit-transition: opacity 0.3s ease-out; - -o-transition: opacity 0.3s ease-out; transition: opacity 0.3s ease-out; position: relative; z-index: 1; - background: rgba(0, 0, 0, 0.7) !important; - -webkit-backdrop-filter: none !important; - backdrop-filter: none !important; - color: #eee !important; + background: linear-gradient(180deg, rgba(16, 16 16, 0.75) 0%, rgba(16, 16, 16, 0.15) 80%, rgba(16, 16, 16, 0) 100%); + backdrop-filter: none; + color: #eee; + height: 7.5em; } .osdHeader-hidden { opacity: 0; } +.osdHeader .headerTop { + max-height: 3.5em; +} + .osdHeader .headerButton:not(.headerBackButton):not(.headerCastButton):not(.headerSyncButton) { display: none; } @@ -88,18 +90,13 @@ .videoOsdBottom { position: fixed; - background-color: rgba(0, 0, 0, 0.7); - padding: 1%; - display: -webkit-box; - display: -webkit-flex; + background: linear-gradient(0deg, rgba(16, 16, 16, 0.75) 0%, rgba(16, 16, 16, 0.15) 80%, rgba(16, 16, 16, 0) 100%); + padding-top: 10em; + padding-bottom: 1.75em; display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -webkit-flex-direction: row; flex-direction: row; + justify-content: center; will-change: opacity; - -webkit-transition: opacity 0.3s ease-out; - -o-transition: opacity 0.3s ease-out; transition: opacity 0.3s ease-out; color: #fff; user-select: none; @@ -111,9 +108,9 @@ } .osdControls { - -webkit-box-flex: 1; - -webkit-flex-grow: 1; flex-grow: 1; + max-width: calc(100vh * 1.77); + padding: 0 0.8em; } .videoOsdBottom .buttons { @@ -145,7 +142,7 @@ } .volumeButtons { - margin: 0 0.5em 0 auto; + margin: 0 1em 0 0.29em; display: flex; -webkit-align-items: center; align-items: center; @@ -153,6 +150,7 @@ .osdTimeText { margin-left: 1em; + margin-right: auto; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; diff --git a/src/components/upnextdialog/upnextdialog.css b/src/components/upnextdialog/upnextdialog.css index 05e3b10f57..067804919f 100644 --- a/src/components/upnextdialog/upnextdialog.css +++ b/src/components/upnextdialog/upnextdialog.css @@ -1,6 +1,7 @@ .upNextDialog { + width: 30vw; position: fixed; - left: 0; + left: auto; bottom: 0; right: 0; padding: 1%; @@ -23,6 +24,7 @@ } .upNextDialog-poster { + display: none; max-width: 40%; max-height: 15%; position: relative; @@ -31,6 +33,10 @@ margin-bottom: 0.5em; } +.upNextDialog-buttons { + justify-content: end; +} + .upNextDialog-button { background: #404040; color: #fff; @@ -44,7 +50,7 @@ .upNextDialog-poster { max-width: initial; max-height: initial; - width: 10%; + width: 30%; margin-bottom: 0; } } diff --git a/src/components/upnextdialog/upnextdialog.js b/src/components/upnextdialog/upnextdialog.js index e28bb03abe..c665d81173 100644 --- a/src/components/upnextdialog/upnextdialog.js +++ b/src/components/upnextdialog/upnextdialog.js @@ -1,6 +1,5 @@ import dom from 'dom'; import playbackManager from 'playbackManager'; -import connectionManager from 'connectionManager'; import events from 'events'; import mediaInfo from 'mediaInfo'; import layoutManager from 'layoutManager'; @@ -15,78 +14,6 @@ import 'flexStyles'; const transitionEndEventName = dom.whichTransitionEvent(); - function seriesImageUrl(item, options) { - 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') { - 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); - } - } - - return null; - } - - function imageUrl(item, options) { - options = 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.PrimaryImageItemId || item.Id, options); - } - - if (options.type === 'Primary') { - if (item.AlbumId && item.AlbumPrimaryImageTag) { - options.tag = item.AlbumPrimaryImageTag; - return connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.AlbumId, options); - } - } - - return null; - } - - function setPoster(osdPoster, item, secondaryItem) { - if (item) { - let imgUrl = seriesImageUrl(item, { type: 'Primary' }) || - seriesImageUrl(item, { type: 'Thumb' }) || - imageUrl(item, { type: 'Primary' }); - - if (!imgUrl && secondaryItem) { - imgUrl = seriesImageUrl(secondaryItem, { type: 'Primary' }) || - seriesImageUrl(secondaryItem, { type: 'Thumb' }) || - imageUrl(secondaryItem, { type: 'Primary' }); - } - - if (imgUrl) { - osdPoster.innerHTML = ''; - return; - } - } - - osdPoster.innerHTML = ''; - } - function getHtml() { let html = ''; @@ -146,8 +73,6 @@ import 'flexStyles'; const elem = instance.options.parent; - setPoster(elem.querySelector('.upNextDialog-poster'), item); - elem.querySelector('.upNextDialog-overview').innerHTML = item.Overview || ''; elem.querySelector('.upNextDialog-mediainfo').innerHTML = mediaInfo.getPrimaryMediaInfoHtml(item, { diff --git a/src/controllers/playback/video/index.html b/src/controllers/playback/video/index.html index 77274230e4..6651fc3da2 100644 --- a/src/controllers/playback/video/index.html +++ b/src/controllers/playback/video/index.html @@ -1,11 +1,9 @@
-

-
${FetchingData} @@ -16,7 +14,7 @@
-
+
@@ -47,32 +45,18 @@ - - - - - - - -
+ +
+ + + +
diff --git a/src/controllers/playback/video/index.js b/src/controllers/playback/video/index.js index 420268ea75..5da8ec45d8 100644 --- a/src/controllers/playback/video/index.js +++ b/src/controllers/playback/video/index.js @@ -21,50 +21,6 @@ import 'css!assets/css/videoosd'; /* eslint-disable indent */ - function seriesImageUrl(item, options) { - if (item.Type !== 'Episode') { - return null; - } - - options = options || {}; - options.type = options.type || 'Primary'; - if (options.type === 'Primary' && item.SeriesPrimaryImageTag) { - options.tag = item.SeriesPrimaryImageTag; - return connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options); - } - - 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); - } - } - - return null; - } - - function imageUrl(item, options) { - options = 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.PrimaryImageItemId || item.Id, options); - } - - if (options.type === 'Primary' && item.AlbumId && item.AlbumPrimaryImageTag) { - options.tag = item.AlbumPrimaryImageTag; - return connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.AlbumId, options); - } - - return null; - } - function getOpenedDialog() { return document.querySelector('.dialogContainer .dialog.opened'); } @@ -164,7 +120,6 @@ import 'css!assets/css/videoosd'; currentItem = item; const displayItem = itemInfo.displayItem || item; updateRecordingButton(displayItem); - setPoster(displayItem, item); let parentName = displayItem.SeriesName || displayItem.Album; if (displayItem.EpisodeTitle || displayItem.IsSeries) { @@ -172,42 +127,6 @@ import 'css!assets/css/videoosd'; } setTitle(displayItem, parentName); - const titleElement = view.querySelector('.osdTitle'); - let displayName = itemHelper.getDisplayName(displayItem, { - includeParentInfo: displayItem.Type !== 'Program', - includeIndexNumber: displayItem.Type !== 'Program' - }); - - if (!displayName) { - displayName = displayItem.Type; - } - - titleElement.innerHTML = displayName; - - if (displayName) { - titleElement.classList.remove('hide'); - } else { - titleElement.classList.add('hide'); - } - - const mediaInfoHtml = mediaInfo.getPrimaryMediaInfoHtml(displayItem, { - runtime: false, - subtitles: false, - tomatoes: false, - endsAt: false, - episodeTitle: false, - originalAirDate: displayItem.Type !== 'Program', - episodeTitleIndexNumber: displayItem.Type !== 'Program', - programIndicator: false - }); - const osdMediaInfo = view.querySelector('.osdMediaInfo'); - osdMediaInfo.innerHTML = mediaInfoHtml; - - if (mediaInfoHtml) { - osdMediaInfo.classList.remove('hide'); - } else { - osdMediaInfo.classList.add('hide'); - } const secondaryMediaInfo = view.querySelector('.osdSecondaryMediaInfo'); const secondaryMediaInfoHtml = mediaInfo.getSecondaryMediaInfoHtml(displayItem, { @@ -222,12 +141,6 @@ import 'css!assets/css/videoosd'; secondaryMediaInfo.classList.add('hide'); } - if (displayName) { - view.querySelector('.osdMainTextContainer').classList.remove('hide'); - } else { - view.querySelector('.osdMainTextContainer').classList.add('hide'); - } - if (enableProgressByTimeOfDay) { setDisplayTime(startTimeText, displayItem.StartDate); setDisplayTime(endTimeText, displayItem.EndDate); @@ -277,7 +190,6 @@ import 'css!assets/css/videoosd'; currentItem = item; if (!item) { - setPoster(null); updateRecordingButton(null); Emby.Page.setTitle(''); nowPlayingVolumeSlider.disabled = true; @@ -314,7 +226,20 @@ import 'css!assets/css/videoosd'; } function setTitle(item, parentName) { - Emby.Page.setTitle(parentName || ''); + let itemName = itemHelper.getDisplayName(item, { + includeParentInfo: item.Type !== 'Program', + includeIndexNumber: item.Type !== 'Program' + }); + + if (itemName && parentName) { + itemName = `${parentName} - ${itemName}`; + } + + if (!itemName) { + itemName = parentName || ''; + } + + Emby.Page.setTitle(itemName); const documentTitle = parentName || (item ? item.Name : null); @@ -323,38 +248,6 @@ import 'css!assets/css/videoosd'; } } - function setPoster(item, secondaryItem) { - const osdPoster = view.querySelector('.osdPoster'); - - if (item) { - let imgUrl = seriesImageUrl(item, { - maxWidth: osdPoster.clientWidth, - type: 'Primary' - }) || seriesImageUrl(item, { - maxWidth: osdPoster.clientWidth, - type: 'Thumb' - }) || imageUrl(item, { - maxWidth: osdPoster.clientWidth, - type: 'Primary' - }); - - if (!imgUrl && secondaryItem && (imgUrl = seriesImageUrl(secondaryItem, { - maxWidth: osdPoster.clientWidth, - type: 'Primary' - }) || seriesImageUrl(secondaryItem, { - maxWidth: osdPoster.clientWidth, - type: 'Thumb' - }) || imageUrl(secondaryItem, { - maxWidth: osdPoster.clientWidth, - type: 'Primary' - })), imgUrl) { - return void (osdPoster.innerHTML = ''); - } - } - - osdPoster.innerHTML = ''; - } - let mouseIsDown = false; function showOsd() { From 3f592881583d18025f8475b58e3f2366a56225e4 Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Thu, 20 Aug 2020 20:39:33 +0200 Subject: [PATCH 003/232] Improve Up Next dialog --- src/assets/css/videoosd.css | 51 +++++--------------- src/components/mediainfo/mediainfo.js | 12 ++--- src/components/upnextdialog/upnextdialog.css | 23 +++++++-- src/components/upnextdialog/upnextdialog.js | 13 +++-- 4 files changed, 44 insertions(+), 55 deletions(-) diff --git a/src/assets/css/videoosd.css b/src/assets/css/videoosd.css index 7273121f53..9995a7ff84 100644 --- a/src/assets/css/videoosd.css +++ b/src/assets/css/videoosd.css @@ -6,18 +6,29 @@ -ms-user-select: none; } -.osdPoster img, .videoOsdBottom { bottom: 0; left: 0; right: 0; + position: fixed; + background: linear-gradient(0deg, rgba(16, 16, 16, 0.6) 0%, rgba(16, 16, 16, 0) 100%); + padding-top: 7.5em; + padding-bottom: 1.75em; + display: flex; + flex-direction: row; + justify-content: center; + will-change: opacity; + transition: opacity 0.3s ease-out; + color: #fff; + user-select: none; + -webkit-touch-callout: none; } .osdHeader { transition: opacity 0.3s ease-out; position: relative; z-index: 1; - background: linear-gradient(180deg, rgba(16, 16 16, 0.75) 0%, rgba(16, 16, 16, 0.15) 80%, rgba(16, 16, 16, 0) 100%); + background: linear-gradient(180deg, rgba(16, 16, 16, 0.6) 0%, rgba(16, 16, 16, 0) 100%); backdrop-filter: none; color: #eee; height: 7.5em; @@ -88,21 +99,6 @@ opacity: 0.6; } -.videoOsdBottom { - position: fixed; - background: linear-gradient(0deg, rgba(16, 16, 16, 0.75) 0%, rgba(16, 16, 16, 0.15) 80%, rgba(16, 16, 16, 0) 100%); - padding-top: 10em; - padding-bottom: 1.75em; - display: flex; - flex-direction: row; - justify-content: center; - will-change: opacity; - transition: opacity 0.3s ease-out; - color: #fff; - user-select: none; - -webkit-touch-callout: none; -} - .videoOsdBottom-hidden { opacity: 0; } @@ -157,27 +153,6 @@ user-select: none; } -.osdPoster { - width: 10%; - position: relative; - margin-right: 0.5em; -} - -.osdPoster img { - position: absolute; - height: auto; - width: 100%; - -webkit-box-shadow: 0 0 1.9vh #000; - box-shadow: 0 0 1.9vh #000; - border: 0.08em solid #222; - user-drag: none; - user-select: none; - -moz-user-select: none; - -webkit-user-drag: none; - -webkit-user-select: none; - -ms-user-select: none; -} - .osdTitle, .osdTitleSmall { margin: 0 1em 0 0; diff --git a/src/components/mediainfo/mediainfo.js b/src/components/mediainfo/mediainfo.js index 1d78d490a2..d5da29d3bc 100644 --- a/src/components/mediainfo/mediainfo.js +++ b/src/components/mediainfo/mediainfo.js @@ -100,11 +100,10 @@ import 'emby-button'; return html; } - export function getMediaInfoHtml(item, options) { + export function getMediaInfoHtml(item, options = {}) { let html = ''; const miscInfo = []; - options = options || {}; let text; let date; let minutes; @@ -289,7 +288,9 @@ import 'emby-button'; return getMediaInfoItem(m); }).join(''); - html += getStarIconsHtml(item); + if (options.starRating !== false) { + html += getStarIconsHtml(item); + } if (item.HasSubtitles && options.subtitles !== false) { html += '
CC
'; @@ -418,9 +419,8 @@ import 'emby-button'; return false; } - export function getPrimaryMediaInfoHtml(item, options) { - options = options || {}; - if (options.interactive == null) { + export function getPrimaryMediaInfoHtml(item, options = {}) { + if (options.interactive === undefined) { options.interactive = false; } diff --git a/src/components/upnextdialog/upnextdialog.css b/src/components/upnextdialog/upnextdialog.css index 067804919f..754fd418ca 100644 --- a/src/components/upnextdialog/upnextdialog.css +++ b/src/components/upnextdialog/upnextdialog.css @@ -1,9 +1,24 @@ -.upNextDialog { - width: 30vw; +.upNextContainer { + box-sizing: border-box; position: fixed; - left: auto; + top: 0; bottom: 0; - right: 0; + left: 50%; + transform: translateX(-50%); + padding: 1em; + display: flex; + flex-grow: 1; + width: calc(100vh * (16 / 9)); + height: 100vh; + justify-content: end; + align-items: flex-end; +} + +.upNextDialog-container { + border-radius: 5px; + width: 30em; + height: 11em; + left: auto; padding: 1%; display: flex; flex-direction: column; diff --git a/src/components/upnextdialog/upnextdialog.js b/src/components/upnextdialog/upnextdialog.js index c665d81173..8d3202cc1c 100644 --- a/src/components/upnextdialog/upnextdialog.js +++ b/src/components/upnextdialog/upnextdialog.js @@ -17,9 +17,7 @@ import 'flexStyles'; function getHtml() { let html = ''; - html += '
'; - html += '
'; - + html += '
'; html += '
'; html += '

 

'; @@ -29,8 +27,6 @@ import 'flexStyles'; html += '
'; html += '
'; - html += '
'; - html += '
'; html += '
'; + html += '
'; return html; } @@ -73,9 +70,11 @@ import 'flexStyles'; const elem = instance.options.parent; - elem.querySelector('.upNextDialog-overview').innerHTML = item.Overview || ''; - elem.querySelector('.upNextDialog-mediainfo').innerHTML = mediaInfo.getPrimaryMediaInfoHtml(item, { + criticRating: false, + originalAirDate: false, + starRating: false, + subtitles: false }); let title = itemHelper.getDisplayName(item); From e38fa15e4d40d1ccc6e51e10bb6052502317adea Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Sat, 22 Aug 2020 02:38:06 +0200 Subject: [PATCH 004/232] Constrain width only on desktop --- src/assets/css/videoosd.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/assets/css/videoosd.css b/src/assets/css/videoosd.css index 9995a7ff84..a23a4cf8ee 100644 --- a/src/assets/css/videoosd.css +++ b/src/assets/css/videoosd.css @@ -105,10 +105,13 @@ .osdControls { flex-grow: 1; - max-width: calc(100vh * 1.77); padding: 0 0.8em; } +.layout-desktop .osdControls { + max-width: calc(100vh * 1.77 - 2vh); +} + .videoOsdBottom .buttons { padding: 0.25em 0 0; display: -webkit-box; From 1812df57ad9a45c40b24378f5bc35953bceead40 Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Sat, 22 Aug 2020 14:07:54 +0200 Subject: [PATCH 005/232] Fix up next dialog on Chrome --- src/components/upnextdialog/upnextdialog.css | 67 ++++---------------- src/components/upnextdialog/upnextdialog.js | 2 - 2 files changed, 11 insertions(+), 58 deletions(-) diff --git a/src/components/upnextdialog/upnextdialog.css b/src/components/upnextdialog/upnextdialog.css index 754fd418ca..efb0366488 100644 --- a/src/components/upnextdialog/upnextdialog.css +++ b/src/components/upnextdialog/upnextdialog.css @@ -1,25 +1,10 @@ .upNextContainer { - box-sizing: border-box; position: fixed; - top: 0; + right: 0; bottom: 0; - left: 50%; - transform: translateX(-50%); - padding: 1em; - display: flex; - flex-grow: 1; - width: calc(100vh * (16 / 9)); - height: 100vh; - justify-content: end; - align-items: flex-end; -} - -.upNextDialog-container { - border-radius: 5px; width: 30em; - height: 11em; - left: auto; - padding: 1%; + padding: 1em; + margin: 0 2em 2em 0; display: flex; flex-direction: column; will-change: transform, opacity; @@ -38,18 +23,18 @@ font-weight: 500; } -.upNextDialog-poster { - display: none; - max-width: 40%; - max-height: 15%; - position: relative; - margin-right: 1em; - flex-shrink: 0; - margin-bottom: 0.5em; +.upNextDialog-nextVideoText, +.upNextDialog-title { + width: 25.5em; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } .upNextDialog-buttons { + width: 29.75em; justify-content: end; + align-content: flex-end; } .upNextDialog-button { @@ -61,34 +46,4 @@ .upNextDialog { flex-direction: row; } - - .upNextDialog-poster { - max-width: initial; - max-height: initial; - width: 30%; - margin-bottom: 0; - } -} - -@media all and (max-width: 50em) { - .upNextDialog-overview { - display: none !important; - } -} - -.upNextDialog-poster-img { - position: absolute; - bottom: 0; - left: 0; - right: 0; - height: auto; - width: 100%; - box-shadow: 0 0.0725em 0.29em 0 rgba(0, 0, 0, 0.37); - user-drag: none; - border: 0; - user-select: none; - -moz-user-select: none; - -webkit-user-drag: none; - -webkit-user-select: none; - -ms-user-select: none; } diff --git a/src/components/upnextdialog/upnextdialog.js b/src/components/upnextdialog/upnextdialog.js index 8d3202cc1c..1d55556710 100644 --- a/src/components/upnextdialog/upnextdialog.js +++ b/src/components/upnextdialog/upnextdialog.js @@ -17,7 +17,6 @@ import 'flexStyles'; function getHtml() { let html = ''; - html += '
'; html += '
'; html += '

 

'; @@ -42,7 +41,6 @@ import 'flexStyles'; // main html += '
'; - html += '
'; return html; } From 02015aaa9c60e727242c34363a7130d2c069a831 Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Sat, 29 Aug 2020 18:32:42 +0200 Subject: [PATCH 006/232] Adjust OSD color for WCAG compliance --- src/assets/css/videoosd.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/css/videoosd.css b/src/assets/css/videoosd.css index a23a4cf8ee..f0792c2c45 100644 --- a/src/assets/css/videoosd.css +++ b/src/assets/css/videoosd.css @@ -11,7 +11,7 @@ left: 0; right: 0; position: fixed; - background: linear-gradient(0deg, rgba(16, 16, 16, 0.6) 0%, rgba(16, 16, 16, 0) 100%); + background: linear-gradient(0deg, rgba(16, 16, 16, 0.75) 0%, rgba(16, 16, 16, 0) 100%); padding-top: 7.5em; padding-bottom: 1.75em; display: flex; @@ -28,7 +28,7 @@ transition: opacity 0.3s ease-out; position: relative; z-index: 1; - background: linear-gradient(180deg, rgba(16, 16, 16, 0.6) 0%, rgba(16, 16, 16, 0) 100%); + background: linear-gradient(180deg, rgba(16, 16, 16, 0.75) 0%, rgba(16, 16, 16, 0) 100%); backdrop-filter: none; color: #eee; height: 7.5em; From 0db000e5b51b1a66cb7b6150879314b8e3d2918e Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Sun, 30 Aug 2020 13:47:37 +0200 Subject: [PATCH 007/232] Fix CSS selector for top OSD header --- src/assets/css/videoosd.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assets/css/videoosd.css b/src/assets/css/videoosd.css index f0792c2c45..b2446d5d48 100644 --- a/src/assets/css/videoosd.css +++ b/src/assets/css/videoosd.css @@ -24,7 +24,7 @@ -webkit-touch-callout: none; } -.osdHeader { +.skinHeader-withBackground.osdHeader { transition: opacity 0.3s ease-out; position: relative; z-index: 1; From f7d0b9491619262a8e420552872d16a6a5b9ca49 Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Tue, 1 Sep 2020 13:32:12 +0300 Subject: [PATCH 008/232] Babel libarchive --- webpack.dev.js | 2 +- webpack.prod.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/webpack.dev.js b/webpack.dev.js index 3d0c2a48a0..33e171daa8 100644 --- a/webpack.dev.js +++ b/webpack.dev.js @@ -15,7 +15,7 @@ module.exports = merge(common, { rules: [ { test: /\.js$/, - exclude: /node_modules[\\/](?!date-fns|epubjs|jellyfin-apiclient|query-string|split-on-first|strict-uri-encode|xmldom)/, + exclude: /node_modules[\\/](?!date-fns|epubjs|libarchive|jellyfin-apiclient|query-string|split-on-first|strict-uri-encode|xmldom)/, use: { loader: 'babel-loader', options: { diff --git a/webpack.prod.js b/webpack.prod.js index 52d6d0a865..408eb4bb59 100644 --- a/webpack.prod.js +++ b/webpack.prod.js @@ -8,7 +8,7 @@ module.exports = merge(common, { rules: [ { test: /\.js$/, - exclude: /node_modules[\\/](?!date-fns|epubjs|jellyfin-apiclient|query-string|split-on-first|strict-uri-encode|xmldom)/, + exclude: /node_modules[\\/](?!date-fns|epubjs|libarchive|jellyfin-apiclient|query-string|split-on-first|strict-uri-encode|xmldom)/, use: { loader: 'babel-loader', options: { From 108ebc58a60f9df6d3e5c002e8bf34834b343771 Mon Sep 17 00:00:00 2001 From: dkanada Date: Tue, 1 Sep 2020 22:55:08 +0900 Subject: [PATCH 009/232] add basic pdf reader --- package.json | 2 + src/bundle.js | 5 + src/components/apphost.js | 2 - src/config.template.json | 1 + src/plugins/bookPlayer/plugin.js | 99 +++---- src/plugins/bookPlayer/tableOfContents.js | 19 +- src/plugins/pdfPlayer/plugin.js | 307 ++++++++++++++++++++++ src/plugins/pdfPlayer/style.css | 25 ++ src/scripts/site.js | 1 + webpack.common.js | 3 +- yarn.lock | 5 + 11 files changed, 400 insertions(+), 69 deletions(-) create mode 100644 src/plugins/pdfPlayer/plugin.js create mode 100644 src/plugins/pdfPlayer/style.css diff --git a/package.json b/package.json index 5f092d6630..b40fe54453 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "core-js": "^3.6.5", "date-fns": "^2.16.0", "epubjs": "^0.3.85", + "pdfjs-dist": "^2.4.456", "fast-text-encoding": "^1.0.3", "flv.js": "^1.5.0", "headroom.js": "^0.11.0", @@ -323,6 +324,7 @@ "src/libraries/scroller.js", "src/plugins/backdropScreensaver/plugin.js", "src/plugins/bookPlayer/plugin.js", + "src/plugins/pdfPlayer/plugin.js", "src/plugins/bookPlayer/tableOfContents.js", "src/plugins/chromecastPlayer/chromecastHelper.js", "src/plugins/photoPlayer/plugin.js", diff --git a/src/bundle.js b/src/bundle.js index 25810f58ee..c498016c44 100644 --- a/src/bundle.js +++ b/src/bundle.js @@ -101,6 +101,11 @@ _define('epubjs', function () { return epubjs; }); +var pdfjs = require('pdfjs-dist/build/pdf'); +_define('pdfjs', function () { + return pdfjs; +}); + // page.js const page = require('page'); _define('page', function() { diff --git a/src/components/apphost.js b/src/components/apphost.js index 33ca5a0b79..b44c8e621f 100644 --- a/src/components/apphost.js +++ b/src/components/apphost.js @@ -172,7 +172,6 @@ function supportsCue() { function onAppVisible() { if (isHidden) { isHidden = false; - console.debug('triggering app resume event'); events.trigger(appHost, 'resume'); } } @@ -180,7 +179,6 @@ function onAppVisible() { function onAppHidden() { if (!isHidden) { isHidden = true; - console.debug('app is hidden'); } } diff --git a/src/config.template.json b/src/config.template.json index 0f308ccc11..c999dccb83 100644 --- a/src/config.template.json +++ b/src/config.template.json @@ -32,6 +32,7 @@ "plugins/bookPlayer/plugin", "plugins/youtubePlayer/plugin", "plugins/backdropScreensaver/plugin", + "plugins/pdfPlayer/plugin", "plugins/logoScreensaver/plugin", "plugins/sessionPlayer/plugin", "plugins/chromecastPlayer/plugin" diff --git a/src/plugins/bookPlayer/plugin.js b/src/plugins/bookPlayer/plugin.js index 415bd7b958..f97610caf6 100644 --- a/src/plugins/bookPlayer/plugin.js +++ b/src/plugins/bookPlayer/plugin.js @@ -20,11 +20,13 @@ export class BookPlayer { this.onDialogClosed = this.onDialogClosed.bind(this); this.openTableOfContents = this.openTableOfContents.bind(this); this.onWindowKeyUp = this.onWindowKeyUp.bind(this); + this.onTouchStart = this.onTouchStart.bind(this); } play(options) { - this._progress = 0; - this._loaded = false; + this.progress = 0; + this.cancellationToken = false; + this.loaded = false; loading.show(); const elem = this.createMediaElement(); @@ -34,35 +36,35 @@ export class BookPlayer { stop() { this.unbindEvents(); - const elem = this._mediaElement; - const tocElement = this._tocElement; - const rendition = this._rendition; + const elem = this.mediaElement; + const tocElement = this.tocElement; + const rendition = this.rendition; if (elem) { dialogHelper.close(elem); - this._mediaElement = null; + this.mediaElement = null; } if (tocElement) { tocElement.destroy(); - this._tocElement = null; + this.tocElement = null; } if (rendition) { rendition.destroy(); } - // Hide loader in case player was not fully loaded yet + // hide loader in case player was not fully loaded yet loading.hide(); - this._cancellationToken.shouldCancel = true; + this.cancellationToken = true; } currentItem() { - return this._currentItem; + return this.item; } currentTime() { - return this._progress * 1000; + return this.progress * 1000; } duration() { @@ -94,12 +96,10 @@ export class BookPlayer { onWindowKeyUp(e) { const key = keyboardnavigation.getKeyName(e); - - // TODO: depending on the event this can be the document or the rendition itself - const rendition = this._rendition || this; + const rendition = this.rendition; const book = rendition.book; - if (this._loaded === false) return; + if (!this.loaded) return; switch (key) { case 'l': case 'ArrowRight': @@ -112,9 +112,9 @@ export class BookPlayer { book.package.metadata.direction === 'rtl' ? rendition.next() : rendition.prev(); break; case 'Escape': - if (this._tocElement) { + if (this.tocElement) { // Close table of contents on ESC if it is open - this._tocElement.destroy(); + this.tocElement.destroy(); } else { // Otherwise stop the entire book player this.stop(); @@ -124,17 +124,12 @@ export class BookPlayer { } onTouchStart(e) { - // TODO: depending on the event this can be the document or the rendition itself - const rendition = this._rendition || this; + const rendition = this.rendition; const book = rendition.book; - // check that the event is from the book or the document - if (!book || this._loaded === false) return; - // epubjs stores pages off the screen or something for preloading // get the modulus of the touch event to account for the increased width - if (!e.touches || e.touches.length === 0) return; - + if (!this.loaded || !e.touches || e.touches.length === 0) return; const touch = e.touches[0].clientX % dom.getWindowSize().innerWidth; if (touch < dom.getWindowSize().innerWidth / 2) { book.package.metadata.direction === 'rtl' ? rendition.next() : rendition.prev(); @@ -148,7 +143,7 @@ export class BookPlayer { } bindMediaElementEvents() { - const elem = this._mediaElement; + const elem = this.mediaElement; elem.addEventListener('close', this.onDialogClosed, {once: true}); elem.querySelector('.btnBookplayerExit').addEventListener('click', this.onDialogClosed, {once: true}); @@ -161,13 +156,13 @@ export class BookPlayer { document.addEventListener('keyup', this.onWindowKeyUp); document.addEventListener('touchstart', this.onTouchStart); - // FIXME: I don't really get why document keyup event is not triggered when epub is in focus - this._rendition.on('keyup', this.onWindowKeyUp); - this._rendition.on('touchstart', this.onTouchStart); + // FIXME: document keyup event is not triggered when epub is in focus + this.rendition.on('keyup', this.onWindowKeyUp); + this.rendition.on('touchstart', this.onTouchStart); } unbindMediaElementEvents() { - const elem = this._mediaElement; + const elem = this.mediaElement; elem.removeEventListener('close', this.onDialogClosed); elem.querySelector('.btnBookplayerExit').removeEventListener('click', this.onDialogClosed); @@ -175,27 +170,27 @@ export class BookPlayer { } unbindEvents() { - if (this._mediaElement) { + if (this.mediaElement) { this.unbindMediaElementEvents(); } document.removeEventListener('keyup', this.onWindowKeyUp); document.removeEventListener('touchstart', this.onTouchStart); - if (this._rendition) { - this._rendition.off('keyup', this.onWindowKeyUp); - this._rendition.off('touchstart', this.onTouchStart); + if (this.rendition) { + this.rendition.off('keyup', this.onWindowKeyUp); + this.rendition.off('touchstart', this.onTouchStart); } } openTableOfContents() { - if (this._loaded) { - this._tocElement = new TableOfContents(this); + if (this.loaded) { + this.tocElement = new TableOfContents(this); } } createMediaElement() { - let elem = this._mediaElement; + let elem = this.mediaElement; if (elem) { return elem; } @@ -211,8 +206,6 @@ export class BookPlayer { removeOnClose: true }); - elem.id = 'bookPlayer'; - let html = ''; html += '
'; html += ''; @@ -221,19 +214,19 @@ export class BookPlayer { html += ''; html += '
'; + elem.id = 'bookPlayer'; elem.innerHTML = html; dialogHelper.open(elem); } - this._mediaElement = elem; - + this.mediaElement = elem; return elem; } setCurrentSrc(elem, options) { const item = options.items[0]; - this._currentItem = item; + this.item = item; this.streamInfo = { started: true, ended: false, @@ -249,15 +242,10 @@ export class BookPlayer { import('epubjs').then(({default: epubjs}) => { const downloadHref = apiClient.getItemDownloadUrl(item.Id); const book = epubjs(downloadHref, {openAs: 'epub'}); - const rendition = book.renderTo(elem, {width: '100%', height: '97%'}); + const rendition = book.renderTo(elem, {width: '100%', height: '96%'}); - this._currentSrc = downloadHref; - this._rendition = rendition; - const cancellationToken = { - shouldCancel: false - }; - - this._cancellationToken = cancellationToken; + this.currentSrc = downloadHref; + this.rendition = rendition; return rendition.display().then(() => { const epubElem = document.querySelector('.epub-container'); @@ -265,10 +253,8 @@ export class BookPlayer { this.bindEvents(); - return this._rendition.book.locations.generate(1024).then(async () => { - if (cancellationToken.shouldCancel) { - return reject(); - } + return this.rendition.book.locations.generate(1024).then(async () => { + if (this.cancellationToken) reject(); const percentageTicks = options.startPositionTicks / 10000000; if (percentageTicks !== 0.0) { @@ -276,15 +262,14 @@ export class BookPlayer { await rendition.display(resumeLocation); } - this._loaded = true; + this.loaded = true; epubElem.style.display = 'block'; rendition.on('relocated', (locations) => { - this._progress = book.locations.percentageFromCfi(locations.start.cfi); + this.progress = book.locations.percentageFromCfi(locations.start.cfi); events.trigger(this, 'timeupdate'); }); loading.hide(); - return resolve(); }); }, () => { @@ -300,7 +285,7 @@ export class BookPlayer { } canPlayItem(item) { - if (item.Path && (item.Path.endsWith('epub'))) { + if (item.Path && item.Path.endsWith('epub')) { return true; } diff --git a/src/plugins/bookPlayer/tableOfContents.js b/src/plugins/bookPlayer/tableOfContents.js index a1c5d8f220..165c1fa9ac 100644 --- a/src/plugins/bookPlayer/tableOfContents.js +++ b/src/plugins/bookPlayer/tableOfContents.js @@ -2,8 +2,8 @@ import dialogHelper from 'dialogHelper'; export default class TableOfContents { constructor(bookPlayer) { - this._bookPlayer = bookPlayer; - this._rendition = bookPlayer._rendition; + this.bookPlayer = bookPlayer; + this.rendition = bookPlayer.rendition; this.onDialogClosed = this.onDialogClosed.bind(this); @@ -11,24 +11,24 @@ export default class TableOfContents { } destroy() { - const elem = this._elem; + const elem = this.elem; if (elem) { this.unbindEvents(); dialogHelper.close(elem); } - this._bookPlayer._tocElement = null; + this.bookPlayer.tocElement = null; } bindEvents() { - const elem = this._elem; + const elem = this.elem; elem.addEventListener('close', this.onDialogClosed, {once: true}); elem.querySelector('.btnBookplayerTocClose').addEventListener('click', this.onDialogClosed, {once: true}); } unbindEvents() { - const elem = this._elem; + const elem = this.elem; elem.removeEventListener('close', this.onDialogClosed); elem.querySelector('.btnBookplayerTocClose').removeEventListener('click', this.onDialogClosed); @@ -52,7 +52,7 @@ export default class TableOfContents { } createMediaElement() { - const rendition = this._rendition; + const rendition = this.rendition; const elem = dialogHelper.createDialog({ size: 'small', @@ -68,7 +68,8 @@ export default class TableOfContents { tocHtml += '