diff --git a/package.json b/package.json index 310c7ea8ab..9c4c7cd403 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,8 @@ "license": "GPL-2.0-or-later", "devDependencies": { "@babel/core": "^7.11.1", - "@babel/eslint-parser": "^7.11.0", - "@babel/eslint-plugin": "^7.11.0", + "@babel/eslint-parser": "^7.11.3", + "@babel/eslint-plugin": "^7.11.3", "@babel/plugin-proposal-class-properties": "^7.10.1", "@babel/plugin-proposal-private-methods": "^7.10.1", "@babel/plugin-transform-modules-amd": "^7.10.5", @@ -112,6 +112,8 @@ "src/components/filterdialog/filterdialog.js", "src/components/focusManager.js", "src/components/groupedcards.js", + "src/components/guide/guide.js", + "src/components/guide/guide-settings.js", "src/components/homeScreenSettings/homeScreenSettings.js", "src/components/homesections/homesections.js", "src/components/htmlMediaHelper.js", @@ -155,11 +157,16 @@ "src/components/playlisteditor/playlisteditor.js", "src/components/playmenu.js", "src/components/prompt/prompt.js", + "src/components/recordingcreator/recordingbutton.js", + "src/components/recordingcreator/recordingcreator.js", "src/components/recordingcreator/seriesrecordingeditor.js", "src/components/recordingcreator/recordinghelper.js", "src/components/refreshdialog/refreshdialog.js", + "src/components/remotecontrol/remotecontrol.js", "src/components/sanatizefilename.js", "src/components/scrollManager.js", + "src/plugins/htmlAudioPlayer/plugin.js", + "src/plugins/chromecastPlayer/plugin.js", "src/components/slideshow/slideshow.js", "src/components/sortmenu/sortmenu.js", "src/plugins/htmlVideoPlayer/plugin.js", @@ -177,6 +184,7 @@ "src/components/syncPlay/playbackPermissionManager.js", "src/components/syncPlay/syncPlayManager.js", "src/components/syncPlay/timeSyncManager.js", + "src/components/tabbedview/tabbedview.js", "src/components/viewManager/viewManager.js", "src/components/tvproviders/schedulesdirect.js", "src/components/tvproviders/xmltv.js", @@ -206,7 +214,7 @@ "src/controllers/music/musicplaylists.js", "src/controllers/music/musicrecommended.js", "src/controllers/music/songs.js", - "src/controllers/dashboard/mediaLibrary.js", + "src/controllers/dashboard/library.js", "src/controllers/dashboard/metadataImages.js", "src/controllers/dashboard/metadatanfo.js", "src/controllers/dashboard/networking.js", @@ -227,6 +235,7 @@ "src/controllers/dashboard/users/userparentalcontrol.js", "src/controllers/dashboard/users/userpasswordpage.js", "src/controllers/dashboard/users/userprofilespage.js", + "src/controllers/home.js", "src/controllers/list.js", "src/controllers/edititemmetadata.js", "src/controllers/favorites.js", @@ -242,6 +251,7 @@ "src/controllers/playback/queue/index.js", "src/controllers/playback/video/index.js", "src/controllers/searchpage.js", + "src/controllers/livetv/livetvguide.js", "src/controllers/livetvtuner.js", "src/controllers/livetv/livetvsuggested.js", "src/controllers/livetvstatus.js", @@ -309,11 +319,14 @@ "src/scripts/filesystem.js", "src/scripts/globalize.js", "src/scripts/imagehelper.js", + "src/scripts/itembynamedetailpage.js", "src/scripts/inputManager.js", "src/scripts/autoThemes.js", "src/scripts/themeManager.js", "src/scripts/keyboardNavigation.js", + "src/scripts/libraryMenu.js", "src/scripts/libraryBrowser.js", + "src/scripts/livetvcomponents.js", "src/scripts/mouseManager.js", "src/scripts/multiDownload.js", "src/scripts/playlists.js", diff --git a/src/components/guide/guide-settings.js b/src/components/guide/guide-settings.js index b3133ec272..35f0d3e06e 100644 --- a/src/components/guide/guide-settings.js +++ b/src/components/guide/guide-settings.js @@ -1,150 +1,149 @@ -define(['dialogHelper', 'globalize', 'userSettings', 'layoutManager', 'connectionManager', 'require', 'loading', 'scrollHelper', 'emby-checkbox', 'emby-radio', 'css!./../formdialog', 'material-icons'], function (dialogHelper, globalize, userSettings, layoutManager, connectionManager, require, loading, scrollHelper) { - 'use strict'; +import dialogHelper from 'dialogHelper'; +import globalize from 'globalize'; +import * as userSettings from 'userSettings'; +import layoutManager from 'layoutManager'; +import scrollHelper from 'scrollHelper'; +import 'emby-checkbox'; +import 'emby-radio'; +import 'css!./../formdialog'; +import 'material-icons'; - layoutManager = layoutManager.default || layoutManager; - scrollHelper = scrollHelper.default || scrollHelper; +function saveCategories(context, options) { + const categories = []; - function saveCategories(context, options) { - var categories = []; + const chkCategorys = context.querySelectorAll('.chkCategory'); + for (const chkCategory of chkCategorys) { + const type = chkCategory.getAttribute('data-type'); - 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) { - categories.push(type); - } - } - - if (categories.length >= 4) { - categories.push('series'); - } - - // differentiate between none and all - categories.push('all'); - options.categories = categories; - } - - 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; + if (chkCategory.checked) { + categories.push(type); } } - function save(context) { - var i; - var length; + if (categories.length >= 4) { + categories.push('series'); + } - 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); + // differentiate between none and all + categories.push('all'); + options.categories = categories; +} + +function loadCategories(context, options) { + const selectedCategories = options.categories || []; + + const chkCategorys = context.querySelectorAll('.chkCategory'); + for (const chkCategory of chkCategorys) { + const type = chkCategory.getAttribute('data-type'); + + chkCategory.checked = !selectedCategories.length || selectedCategories.indexOf(type) !== -1; + } +} + +function save(context) { + const chkIndicators = context.querySelectorAll('.chkIndicator'); + + for (const chkIndicator of chkIndicators) { + const type = chkIndicator.getAttribute('data-type'); + userSettings.set('guide-indicator-' + type, chkIndicator.checked); + } + + userSettings.set('guide-colorcodedbackgrounds', context.querySelector('.chkColorCodedBackgrounds').checked); + userSettings.set('livetv-favoritechannelsattop', context.querySelector('.chkFavoriteChannelsAtTop').checked); + + const sortBys = context.querySelectorAll('.chkSortOrder'); + for (const sortBy of sortBys) { + if (sortBy.checked) { + userSettings.set('livetv-channelorder', sortBy.value); + break; } + } +} - userSettings.set('guide-colorcodedbackgrounds', context.querySelector('.chkColorCodedBackgrounds').checked); - userSettings.set('livetv-favoritechannelsattop', context.querySelector('.chkFavoriteChannelsAtTop').checked); +function load(context) { + const chkIndicators = context.querySelectorAll('.chkIndicator'); - var sortBys = context.querySelectorAll('.chkSortOrder'); - for (i = 0, length = sortBys.length; i < length; i++) { - if (sortBys[i].checked) { - userSettings.set('livetv-channelorder', sortBys[i].value); - break; - } + for (const chkIndicator of chkIndicators) { + const type = chkIndicator.getAttribute('data-type'); + + if (chkIndicator.getAttribute('data-default') === 'true') { + chkIndicator.checked = userSettings.get('guide-indicator-' + type) !== 'false'; + } else { + chkIndicator.checked = userSettings.get('guide-indicator-' + type) === 'true'; } } - function load(context) { - var i; - var length; + context.querySelector('.chkColorCodedBackgrounds').checked = userSettings.get('guide-colorcodedbackgrounds') === 'true'; + context.querySelector('.chkFavoriteChannelsAtTop').checked = userSettings.get('livetv-favoritechannelsattop') !== 'false'; - var chkIndicators = context.querySelectorAll('.chkIndicator'); - for (i = 0, length = chkIndicators.length; i < length; i++) { - var type = chkIndicators[i].getAttribute('data-type'); + const sortByValue = userSettings.get('livetv-channelorder') || 'Number'; - if (chkIndicators[i].getAttribute('data-default') === 'true') { - chkIndicators[i].checked = userSettings.get('guide-indicator-' + type) !== 'false'; + const sortBys = context.querySelectorAll('.chkSortOrder'); + for (const sortBy of sortBys) { + sortBy.checked = sortBy.value === sortByValue; + } +} + +function showEditor(options) { + return new Promise(function (resolve, reject) { + let settingsChanged = false; + + import('text!./guide-settings.template.html').then(({ default: template }) => { + const dialogOptions = { + removeOnClose: true, + scrollY: false + }; + + if (layoutManager.tv) { + dialogOptions.size = 'fullscreen'; } else { - chkIndicators[i].checked = userSettings.get('guide-indicator-' + type) === 'true'; + dialogOptions.size = 'small'; } - } - context.querySelector('.chkColorCodedBackgrounds').checked = userSettings.get('guide-colorcodedbackgrounds') === 'true'; - context.querySelector('.chkFavoriteChannelsAtTop').checked = userSettings.get('livetv-favoritechannelsattop') !== 'false'; + const dlg = dialogHelper.createDialog(dialogOptions); - var sortByValue = userSettings.get('livetv-channelorder') || 'Number'; + dlg.classList.add('formDialog'); - var sortBys = context.querySelectorAll('.chkSortOrder'); - for (i = 0, length = sortBys.length; i < length; i++) { - sortBys[i].checked = sortBys[i].value === sortByValue; - } - } + let html = ''; - function showEditor(options) { - return new Promise(function (resolve, reject) { - var settingsChanged = false; + html += globalize.translateHtml(template, 'core'); - require(['text!./guide-settings.template.html'], function (template) { - var dialogOptions = { - removeOnClose: true, - scrollY: false - }; + dlg.innerHTML = html; - if (layoutManager.tv) { - dialogOptions.size = 'fullscreen'; - } else { - dialogOptions.size = 'small'; - } - - var dlg = dialogHelper.createDialog(dialogOptions); - - dlg.classList.add('formDialog'); - - var html = ''; - - html += globalize.translateHtml(template, 'core'); - - dlg.innerHTML = html; - - dlg.addEventListener('change', function () { - settingsChanged = true; - }); - - dlg.addEventListener('close', function () { - if (layoutManager.tv) { - scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false); - } - - save(dlg); - saveCategories(dlg, options); - - if (settingsChanged) { - resolve(); - } else { - reject(); - } - }); - - dlg.querySelector('.btnCancel').addEventListener('click', function () { - dialogHelper.close(dlg); - }); - - if (layoutManager.tv) { - scrollHelper.centerFocus.on(dlg.querySelector('.formDialogContent'), false); - } - - load(dlg); - loadCategories(dlg, options); - dialogHelper.open(dlg); + dlg.addEventListener('change', function () { + settingsChanged = true; }); - }); - } - return { - show: showEditor - }; -}); + dlg.addEventListener('close', function () { + if (layoutManager.tv) { + scrollHelper.centerFocus.off(dlg.querySelector('.formDialogContent'), false); + } + + save(dlg); + saveCategories(dlg, options); + + if (settingsChanged) { + resolve(); + } else { + reject(); + } + }); + + dlg.querySelector('.btnCancel').addEventListener('click', function () { + dialogHelper.close(dlg); + }); + + if (layoutManager.tv) { + scrollHelper.centerFocus.on(dlg.querySelector('.formDialogContent'), false); + } + + load(dlg); + loadCategories(dlg, options); + dialogHelper.open(dlg); + }); + }); +} + +export default { + show: showEditor +}; diff --git a/src/components/guide/guide.js b/src/components/guide/guide.js index c8fd8021e3..a7b32d887d 100644 --- a/src/components/guide/guide.js +++ b/src/components/guide/guide.js @@ -1,1182 +1,1198 @@ -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'; +import inputManager from 'inputManager'; +import browser from 'browser'; +import globalize from 'globalize'; +import connectionManager from 'connectionManager'; +import scrollHelper from 'scrollHelper'; +import serverNotifications from 'serverNotifications'; +import loading from 'loading'; +import datetime from 'datetime'; +import focusManager from 'focusManager'; +import playbackManager from 'playbackManager'; +import * as userSettings from 'userSettings'; +import imageLoader from 'imageLoader'; +import events from 'events'; +import layoutManager from 'layoutManager'; +import itemShortcuts from 'itemShortcuts'; +import dom from 'dom'; +import 'css!./guide.css'; +import 'programStyles'; +import 'material-icons'; +import 'scrollStyles'; +import 'emby-programcell'; +import 'emby-button'; +import 'paper-icon-button-light'; +import 'emby-tabs'; +import 'emby-scroller'; +import 'flexStyles'; +import 'webcomponents'; - playbackManager = playbackManager.default || playbackManager; - browser = browser.default || browser; - loading = loading.default || loading; - layoutManager = layoutManager.default || layoutManager; - 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(); - }); +function showViewSettings(instance) { + import('guide-settings-dialog').then(({default: guideSettingsDialog}) => { + guideSettingsDialog.show(instance.categoryOptions).then(function () { + instance.refresh(); }); + }); +} + +function updateProgramCellOnScroll(cell, scrollPct) { + let left = cell.posLeft; + if (!left) { + left = parseFloat(cell.style.left.replace('%', '')); + cell.posLeft = left; + } + let width = cell.posWidth; + if (!width) { + width = parseFloat(cell.style.width.replace('%', '')); + cell.posWidth = width; } - function updateProgramCellOnScroll(cell, scrollPct) { - var left = cell.posLeft; - if (!left) { - left = parseFloat(cell.style.left.replace('%', '')); - cell.posLeft = left; - } - var width = cell.posWidth; - if (!width) { - width = parseFloat(cell.style.width.replace('%', '')); - cell.posWidth = width; - } + const right = left + width; + const newPct = Math.max(Math.min(scrollPct, right), left); - var right = left + width; - var newPct = Math.max(Math.min(scrollPct, right), left); + const offset = newPct - left; + const pctOfWidth = (offset / width) * 100; - var offset = newPct - left; - var pctOfWidth = (offset / width) * 100; - - var guideProgramName = cell.guideProgramName; - if (!guideProgramName) { - guideProgramName = cell.querySelector('.guideProgramName'); - cell.guideProgramName = guideProgramName; - } - - var caret = cell.caret; - if (!caret) { - caret = cell.querySelector('.guide-programNameCaret'); - cell.caret = caret; - } - - if (guideProgramName) { - if (pctOfWidth > 0 && pctOfWidth <= 100) { - guideProgramName.style.transform = 'translateX(' + pctOfWidth + '%)'; - caret.classList.remove('hide'); - } else { - guideProgramName.style.transform = 'none'; - caret.classList.add('hide'); - } - } + let guideProgramName = cell.guideProgramName; + if (!guideProgramName) { + guideProgramName = cell.querySelector('.guideProgramName'); + cell.guideProgramName = guideProgramName; } - var isUpdatingProgramCellScroll = false; - function updateProgramCellsOnScroll(programGrid, programCells) { - if (isUpdatingProgramCellScroll) { - return; - } - - 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); - } - - isUpdatingProgramCellScroll = false; - }); + let caret = cell.caret; + if (!caret) { + caret = cell.querySelector('.guide-programNameCaret'); + cell.caret = caret; } - 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(); - endDate = datetime.parseISO8601Date(endDate, { toLocal: true }).getTime(); - - var now = new Date().getTime(); - if (now >= startDate && now < endDate) { - var channelId = programCell.getAttribute('data-channelid'); - var serverId = programCell.getAttribute('data-serverid'); - - e.preventDefault(); - e.stopPropagation(); - - playbackManager.play({ - ids: [channelId], - serverId: serverId - }); - } + if (guideProgramName) { + if (pctOfWidth > 0 && pctOfWidth <= 100) { + guideProgramName.style.transform = 'translateX(' + pctOfWidth + '%)'; + caret.classList.remove('hide'); + } else { + guideProgramName.style.transform = 'none'; + caret.classList.add('hide'); } } +} - function Guide(options) { - var self = this; - var items = {}; +let isUpdatingProgramCellScroll = false; +function updateProgramCellsOnScroll(programGrid, programCells) { + if (isUpdatingProgramCellScroll) { + return; + } - self.options = options; - self.categoryOptions = { categories: [] }; + isUpdatingProgramCellScroll = true; - // 30 mins - var cellCurationMinutes = 30; - var cellDurationMs = cellCurationMinutes * 60 * 1000; - var msPerDay = 86400000; + requestAnimationFrame(function () { + const scrollLeft = programGrid.scrollLeft; - var currentDate; - var currentStartIndex = 0; - var currentChannelLimit = 0; - var autoRefreshInterval; - var programCells; - var lastFocusDirection; - var programGrid; + const scrollPct = scrollLeft ? (scrollLeft / programGrid.scrollWidth) * 100 : 0; - self.refresh = function () { - currentDate = null; - reloadPage(options.element); - restartAutoRefresh(); - }; - - self.pause = function () { - stopAutoRefresh(); - }; - - self.resume = function (refreshData) { - if (refreshData) { - self.refresh(); - } else { - restartAutoRefresh(); - } - }; - - self.destroy = function () { - stopAutoRefresh(); - - events.off(serverNotifications, 'TimerCreated', onTimerCreated); - events.off(serverNotifications, 'SeriesTimerCreated', onSeriesTimerCreated); - events.off(serverNotifications, 'TimerCancelled', onTimerCancelled); - events.off(serverNotifications, 'SeriesTimerCancelled', onSeriesTimerCancelled); - - setScrollEvents(options.element, false); - itemShortcuts.off(options.element); - items = {}; - }; - - function restartAutoRefresh() { - stopAutoRefresh(); - - var intervalMs = 60000 * 15; // (minutes) - - autoRefreshInterval = setInterval(function () { - self.refresh(); - }, intervalMs); + for (const programCell of programCells) { + updateProgramCellOnScroll(programCell, scrollPct); } - function stopAutoRefresh() { - if (autoRefreshInterval) { - clearInterval(autoRefreshInterval); - autoRefreshInterval = null; - } - } - - 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); - } - - return date; - } - - function showLoading() { - loading.show(); - } - - function hideLoading() { - loading.hide(); - } - - function reloadGuide(context, newStartDate, scrollToTimeMs, focusToTimeMs, startTimeOfDayMs, focusProgramOnRender) { - var apiClient = connectionManager.getApiClient(options.serverId); - - var channelQuery = { - - StartIndex: 0, - EnableFavoriteSorting: userSettings.get('livetv-favoritechannelsattop') !== 'false' - }; - - channelQuery.UserId = apiClient.getCurrentUserId(); - - var channelLimit = 500; - currentChannelLimit = channelLimit; - - showLoading(); - - channelQuery.StartIndex = currentStartIndex; - channelQuery.Limit = channelLimit; - channelQuery.AddCurrentProgram = false; - channelQuery.EnableUserData = false; - channelQuery.EnableImageTypes = 'Primary'; - - var categories = self.categoryOptions.categories || []; - var displayMovieContent = !categories.length || categories.indexOf('movies') !== -1; - var displaySportsContent = !categories.length || categories.indexOf('sports') !== -1; - var displayNewsContent = !categories.length || categories.indexOf('news') !== -1; - var displayKidsContent = !categories.length || categories.indexOf('kids') !== -1; - var displaySeriesContent = !categories.length || categories.indexOf('series') !== -1; - - if (displayMovieContent && displaySportsContent && displayNewsContent && displayKidsContent) { - channelQuery.IsMovie = null; - channelQuery.IsSports = null; - channelQuery.IsKids = null; - channelQuery.IsNews = null; - channelQuery.IsSeries = null; - } else { - if (displayNewsContent) { - channelQuery.IsNews = true; - } - if (displaySportsContent) { - channelQuery.IsSports = true; - } - if (displayKidsContent) { - channelQuery.IsKids = true; - } - if (displayMovieContent) { - channelQuery.IsMovie = true; - } - if (displaySeriesContent) { - channelQuery.IsSeries = true; - } - } - - if (userSettings.get('livetv-channelorder') === 'DatePlayed') { - channelQuery.SortBy = 'DatePlayed'; - channelQuery.SortOrder = 'Descending'; - } else { - channelQuery.SortBy = null; - channelQuery.SortOrder = null; - } - - var date = newStartDate; - // Add one second to avoid getting programs that are just ending - date = new Date(date.getTime() + 1000); - - // Subtract to avoid getting programs that are starting when the grid ends - var nextDay = new Date(date.getTime() + msPerDay - 2000); - - // Normally we'd want to just let responsive css handle this, - // but since mobile browsers are often underpowered, - // it can help performance to get them out of the markup - var allowIndicators = dom.getWindowSize().innerWidth >= 600; - - var renderOptions = { - showHdIcon: allowIndicators && userSettings.get('guide-indicator-hd') === 'true', - showLiveIndicator: allowIndicators && userSettings.get('guide-indicator-live') !== 'false', - showPremiereIndicator: allowIndicators && userSettings.get('guide-indicator-premiere') !== 'false', - showNewIndicator: allowIndicators && userSettings.get('guide-indicator-new') !== 'false', - showRepeatIndicator: allowIndicators && userSettings.get('guide-indicator-repeat') === 'true', - showEpisodeTitle: layoutManager.tv ? false : true - }; - - 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'); - btnNextPage.classList.remove('hide'); - - if (channelQuery.StartIndex) { - context.querySelector('.btnPreviousPage').disabled = false; - } else { - context.querySelector('.btnPreviousPage').disabled = true; - } - - if ((channelQuery.StartIndex + channelLimit) < channelsResult.TotalRecordCount) { - btnNextPage.disabled = false; - } else { - btnNextPage.disabled = true; - } - } else { - context.querySelector('.guideOptions').classList.add('hide'); - } - - var programFields = []; - - var programQuery = { - UserId: apiClient.getCurrentUserId(), - MaxStartDate: nextDay.toISOString(), - MinEndDate: date.toISOString(), - channelIds: channelsResult.Items.map(function (c) { - return c.Id; - }).join(','), - ImageTypeLimit: 1, - EnableImages: false, - //EnableImageTypes: layoutManager.tv ? "Primary,Backdrop" : "Primary", - SortBy: 'StartDate', - EnableTotalRecordCount: false, - EnableUserData: false - }; - - if (renderOptions.showHdIcon) { - programFields.push('IsHD'); - } - - if (programFields.length) { - programQuery.Fields = programFields.join(''); - } - - 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; - } - } - - return datetime.getDisplayTime(date).toLowerCase(); - } - - function getTimeslotHeadersHtml(startDate, endDateTime) { - var html = ''; - - // clone - startDate = new Date(startDate.getTime()); - - html += '
http://example.com/<baseurl>
。",
+ "LabelBaseUrlHelp": "为服务器 URL添加自定义子目录,例如:http://example.com/<baseurl>
",
"MusicLibraryHelp": "重播 {0}音乐命名指南{1}。",
"HeaderFavoritePeople": "最喜欢的人物",
"OptionRandom": "随机",
@@ -1480,7 +1480,7 @@
"LabelRequireHttpsHelp": "开启后服务器将自动将所有 HTTP 请求重定向到 HTTPS。如果服务器没有启用 HTTPS 则不生效。",
"LabelRequireHttps": "强制 HTTPS",
"LabelStable": "稳定版",
- "LabelEnableHttpsHelp": "开启服务器对所配置 HTTPS 端口的监听。必须配置有效的证书才会生效。",
+ "LabelEnableHttpsHelp": "监听已配置的 HTTPS 端口。必须配置有效的证书才会生效。",
"LabelEnableHttps": "启用 HTTPS",
"LabelChromecastVersion": "Chromecast版本",
"HeaderDVR": "DVR",
@@ -1539,5 +1539,13 @@
"ClearQueue": "清空队列",
"StopPlayback": "停止播放",
"Writers": "作者",
- "ViewAlbumArtist": "查看专辑艺术家"
+ "ViewAlbumArtist": "查看专辑艺术家",
+ "Preview": "预览",
+ "SubtitleVerticalPositionHelp": "文字出现的行号。正数表示由上到下,负数表示由下到上。",
+ "LabelSubtitleVerticalPosition": "垂直位置:",
+ "PreviousTrack": "上一曲",
+ "MessageGetInstalledPluginsError": "获取已安装插件列表时出现错误。",
+ "MessagePluginInstallError": "安装插件时出现错误。",
+ "NextTrack": "下一曲",
+ "LabelUnstable": "不稳定"
}
diff --git a/yarn.lock b/yarn.lock
index 758ded53fc..269b3b93cd 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -40,19 +40,19 @@
semver "^5.4.1"
source-map "^0.5.0"
-"@babel/eslint-parser@^7.11.0":
- version "7.11.0"
- resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.11.0.tgz#b123924edd44508782c030066c926f1b807151cd"
- integrity sha512-dJDM2Pc01D9TwKL3Mmz2xgVF9X953RBHq9H4gywbN1q8MrfvXmNHfsCt06vvByBVQqm+9WxMs+doEH/R09TwWQ==
+"@babel/eslint-parser@^7.11.3":
+ version "7.11.3"
+ resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.11.3.tgz#ceb94cb6e2457c4a4d2d87db29925e6b48d20786"
+ integrity sha512-OdCt/CVXdR/eTNTYDEobf4e55m/AAc04ki+/Oe2/GE8ivh2FxX4yDab48lA6t7ysP4M7luap6Fxx3hUVNTwzFQ==
dependencies:
eslint-scope "5.1.0"
eslint-visitor-keys "^1.3.0"
semver "^6.3.0"
-"@babel/eslint-plugin@^7.11.0":
- version "7.11.0"
- resolved "https://registry.yarnpkg.com/@babel/eslint-plugin/-/eslint-plugin-7.11.0.tgz#55d5b6bd29859cabce152f16d01b3a8150d5b295"
- integrity sha512-+gfPM0/T6d25jKBgmxWp38W0jqRs16Vt7DPBxGOcnN/7nS2A/6QoaXOYEaccvWS5a9UpWlMIAylivp6UtH8/sQ==
+"@babel/eslint-plugin@^7.11.3":
+ version "7.11.3"
+ resolved "https://registry.yarnpkg.com/@babel/eslint-plugin/-/eslint-plugin-7.11.3.tgz#66b531f90592f8f0621d072b59ea2c37c91e8d0d"
+ integrity sha512-gmi3lgaWlYpNb+h7qPfv5GVz2ZVwzCDyV+kAGj+3il+Mv5uan5Yccvdw7m14UAAY2tdTbB0VgRF6ZLjUbrUm0g==
dependencies:
eslint-rule-composer "^0.3.0"