diff --git a/package.json b/package.json index 8fb21e0068..c6735a31d5 100644 --- a/package.json +++ b/package.json @@ -154,6 +154,8 @@ "src/components/playlisteditor/playlisteditor.js", "src/components/playmenu.js", "src/components/prompt/prompt.js", + "src/components/recordingcreator/seriesrecordingeditor.js", + "src/components/recordingcreator/recordinghelper.js", "src/components/refreshdialog/refreshdialog.js", "src/components/sanatizefilename.js", "src/components/scrollManager.js", @@ -169,6 +171,8 @@ "src/components/syncPlay/syncPlayManager.js", "src/components/syncPlay/timeSyncManager.js", "src/components/themeMediaPlayer.js", + "src/components/tvproviders/schedulesdirect.js", + "src/components/tvproviders/xmltv.js", "src/components/toast/toast.js", "src/components/upnextdialog/upnextdialog.js", "src/components/viewContainer.js", diff --git a/src/components/recordingcreator/recordingbutton.js b/src/components/recordingcreator/recordingbutton.js index 3ad4ffa594..1207208e90 100644 --- a/src/components/recordingcreator/recordingbutton.js +++ b/src/components/recordingcreator/recordingbutton.js @@ -1,6 +1,8 @@ define(['globalize', 'connectionManager', 'require', 'loading', 'apphost', 'dom', 'recordingHelper', 'events', 'paper-icon-button-light', 'emby-button', 'css!./recordingfields'], function (globalize, connectionManager, require, loading, appHost, dom, recordingHelper, events) { 'use strict'; + recordingHelper = recordingHelper.default || recordingHelper; + function onRecordingButtonClick(e) { var item = this.item; diff --git a/src/components/recordingcreator/recordingeditor.js b/src/components/recordingcreator/recordingeditor.js index 2086129a9e..2e54b3601c 100644 --- a/src/components/recordingcreator/recordingeditor.js +++ b/src/components/recordingcreator/recordingeditor.js @@ -12,6 +12,8 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c function deleteTimer(apiClient, timerId) { return new Promise(function (resolve, reject) { require(['recordingHelper'], function (recordingHelper) { + recordingHelper = recordingHelper.default || recordingHelper; + recordingHelper.cancelTimerWithConfirmation(timerId, apiClient.serverId()).then(resolve, reject); }); }); diff --git a/src/components/recordingcreator/recordingfields.js b/src/components/recordingcreator/recordingfields.js index e3739f1cfe..741570581e 100644 --- a/src/components/recordingcreator/recordingfields.js +++ b/src/components/recordingcreator/recordingfields.js @@ -1,6 +1,7 @@ define(['globalize', 'connectionManager', 'serverNotifications', 'require', 'loading', 'apphost', 'dom', 'recordingHelper', 'events', 'paper-icon-button-light', 'emby-button', 'css!./recordingfields', 'flexStyles'], function (globalize, connectionManager, serverNotifications, require, loading, appHost, dom, recordingHelper, events) { 'use strict'; + recordingHelper = recordingHelper.default || recordingHelper; loading = loading.default || loading; function loadData(parent, program, apiClient) { diff --git a/src/components/recordingcreator/recordinghelper.js b/src/components/recordingcreator/recordinghelper.js index 5d72394282..13359de2bc 100644 --- a/src/components/recordingcreator/recordinghelper.js +++ b/src/components/recordingcreator/recordinghelper.js @@ -1,194 +1,195 @@ -define(['globalize', 'loading', 'connectionManager'], function (globalize, loading, connectionManager) { - 'use strict'; +import globalize from 'globalize'; +import loading from 'loading'; +import connectionManager from 'connectionManager'; - loading = loading.default || loading; +/*eslint prefer-const: "error"*/ - function changeRecordingToSeries(apiClient, timerId, programId, confirmTimerCancellation) { - loading.show(); +function changeRecordingToSeries(apiClient, timerId, programId, confirmTimerCancellation) { + loading.show(); - return apiClient.getItem(apiClient.getCurrentUserId(), programId).then(function (item) { - if (item.IsSeries) { - // create series - return apiClient.getNewLiveTvTimerDefaults({ programId: programId }).then(function (timerDefaults) { - return apiClient.createLiveTvSeriesTimer(timerDefaults).then(function () { - loading.hide(); - sendToast(globalize.translate('SeriesRecordingScheduled')); + return apiClient.getItem(apiClient.getCurrentUserId(), programId).then(function (item) { + if (item.IsSeries) { + // create series + return apiClient.getNewLiveTvTimerDefaults({ programId: programId }).then(function (timerDefaults) { + return apiClient.createLiveTvSeriesTimer(timerDefaults).then(function () { + loading.hide(); + sendToast(globalize.translate('SeriesRecordingScheduled')); + }); + }); + } else { + // cancel + if (confirmTimerCancellation) { + return cancelTimerWithConfirmation(timerId, apiClient.serverId()); + } + + return cancelTimer(apiClient.serverId(), timerId, true); + } + }); +} + +function cancelTimerWithConfirmation(timerId, serverId) { + return new Promise(function (resolve, reject) { + import('confirm').then(({ default: confirm }) => { + confirm.default({ + + text: globalize.translate('MessageConfirmRecordingCancellation'), + primary: 'delete', + confirmText: globalize.translate('HeaderCancelRecording'), + cancelText: globalize.translate('HeaderKeepRecording') + + }).then(function () { + loading.show(); + + const apiClient = connectionManager.getApiClient(serverId); + cancelTimer(apiClient, timerId, true).then(resolve, reject); + }, reject); + }); + }); +} + +function cancelSeriesTimerWithConfirmation(timerId, serverId) { + return new Promise(function (resolve, reject) { + import('confirm').then(({ default: confirm }) => { + confirm.default({ + + text: globalize.translate('MessageConfirmRecordingCancellation'), + primary: 'delete', + confirmText: globalize.translate('HeaderCancelSeries'), + cancelText: globalize.translate('HeaderKeepSeries') + + }).then(function () { + loading.show(); + + const apiClient = connectionManager.getApiClient(serverId); + apiClient.cancelLiveTvSeriesTimer(timerId).then(function () { + import('toast').then(({default: toast}) => { + toast(globalize.translate('SeriesCancelled')); }); + + loading.hide(); + resolve(); + }, reject); + }, reject); + }); + }); +} + +function cancelTimer(apiClient, timerId, hideLoading) { + loading.show(); + return apiClient.cancelLiveTvTimer(timerId).then(function () { + if (hideLoading !== false) { + loading.hide(); + sendToast(globalize.translate('RecordingCancelled')); + } + }); +} + +function createRecording(apiClient, programId, isSeries) { + loading.show(); + return apiClient.getNewLiveTvTimerDefaults({ programId: programId }).then(function (item) { + const promise = isSeries ? + apiClient.createLiveTvSeriesTimer(item) : + apiClient.createLiveTvTimer(item); + + return promise.then(function () { + loading.hide(); + sendToast(globalize.translate('RecordingScheduled')); + }); + }); +} + +function sendToast(msg) { + import('toast').then(({ default: toast }) => { + toast(msg); + }); +} + +function showMultiCancellationPrompt(serverId, programId, timerId, timerStatus, seriesTimerId) { + return new Promise(function (resolve, reject) { + import('dialog').then(({ default: dialog }) => { + const items = []; + + items.push({ + name: globalize.translate('HeaderKeepRecording'), + id: 'cancel', + type: 'submit' + }); + + if (timerStatus === 'InProgress') { + items.push({ + name: globalize.translate('HeaderStopRecording'), + id: 'canceltimer', + type: 'cancel' }); } else { - // cancel - if (confirmTimerCancellation) { - return cancelTimerWithConfirmation(timerId, apiClient.serverId()); - } - - return cancelTimer(apiClient.serverId(), timerId, true); + items.push({ + name: globalize.translate('HeaderCancelRecording'), + id: 'canceltimer', + type: 'cancel' + }); } - }); - } - function cancelTimerWithConfirmation(timerId, serverId) { - return new Promise(function (resolve, reject) { - require(['confirm'], function (confirm) { - confirm.default({ - - text: globalize.translate('MessageConfirmRecordingCancellation'), - primary: 'delete', - confirmText: globalize.translate('HeaderCancelRecording'), - cancelText: globalize.translate('HeaderKeepRecording') - - }).then(function () { - loading.show(); - - var apiClient = connectionManager.getApiClient(serverId); - cancelTimer(apiClient, timerId, true).then(resolve, reject); - }, reject); + items.push({ + name: globalize.translate('HeaderCancelSeries'), + id: 'cancelseriestimer', + type: 'cancel' }); - }); - } - function cancelSeriesTimerWithConfirmation(timerId, serverId) { - return new Promise(function (resolve, reject) { - require(['confirm'], function (confirm) { - confirm.default({ + dialog({ - text: globalize.translate('MessageConfirmRecordingCancellation'), - primary: 'delete', - confirmText: globalize.translate('HeaderCancelSeries'), - cancelText: globalize.translate('HeaderKeepSeries') + text: globalize.translate('MessageConfirmRecordingCancellation'), + buttons: items - }).then(function () { + }).then(function (result) { + const apiClient = connectionManager.getApiClient(serverId); + + if (result === 'canceltimer') { loading.show(); - var apiClient = connectionManager.getApiClient(serverId); - apiClient.cancelLiveTvSeriesTimer(timerId).then(function () { - require(['toast'], function (toast) { + cancelTimer(apiClient, timerId, true).then(resolve, reject); + } else if (result === 'cancelseriestimer') { + loading.show(); + + apiClient.cancelLiveTvSeriesTimer(seriesTimerId).then(function () { + import('toast').then(({ default: toast }) => { toast(globalize.translate('SeriesCancelled')); }); loading.hide(); resolve(); }, reject); - }, reject); - }); - }); - } - - function cancelTimer(apiClient, timerId, hideLoading) { - loading.show(); - return apiClient.cancelLiveTvTimer(timerId).then(function () { - if (hideLoading !== false) { - loading.hide(); - sendToast(globalize.translate('RecordingCancelled')); - } - }); - } - - function createRecording(apiClient, programId, isSeries) { - loading.show(); - return apiClient.getNewLiveTvTimerDefaults({ programId: programId }).then(function (item) { - var promise = isSeries ? - apiClient.createLiveTvSeriesTimer(item) : - apiClient.createLiveTvTimer(item); - - return promise.then(function () { - loading.hide(); - sendToast(globalize.translate('RecordingScheduled')); - }); - }); - } - - function sendToast(msg) { - require(['toast'], function (toast) { - toast(msg); - }); - } - - function showMultiCancellationPrompt(serverId, programId, timerId, timerStatus, seriesTimerId) { - return new Promise(function (resolve, reject) { - require(['dialog'], function (dialog) { - var items = []; - - items.push({ - name: globalize.translate('HeaderKeepRecording'), - id: 'cancel', - type: 'submit' - }); - - if (timerStatus === 'InProgress') { - items.push({ - name: globalize.translate('HeaderStopRecording'), - id: 'canceltimer', - type: 'cancel' - }); } else { - items.push({ - name: globalize.translate('HeaderCancelRecording'), - id: 'canceltimer', - type: 'cancel' - }); + resolve(); } - - items.push({ - name: globalize.translate('HeaderCancelSeries'), - id: 'cancelseriestimer', - type: 'cancel' - }); - - dialog({ - - text: globalize.translate('MessageConfirmRecordingCancellation'), - buttons: items - - }).then(function (result) { - var apiClient = connectionManager.getApiClient(serverId); - - if (result === 'canceltimer') { - loading.show(); - - cancelTimer(apiClient, timerId, true).then(resolve, reject); - } else if (result === 'cancelseriestimer') { - loading.show(); - - apiClient.cancelLiveTvSeriesTimer(seriesTimerId).then(function () { - require(['toast'], function (toast) { - toast(globalize.translate('SeriesCancelled')); - }); - - loading.hide(); - resolve(); - }, reject); - } else { - resolve(); - } - }, reject); - }); + }, reject); }); - } + }); +} - function toggleRecording(serverId, programId, timerId, timerStatus, seriesTimerId) { - var apiClient = connectionManager.getApiClient(serverId); - var hasTimer = timerId && timerStatus !== 'Cancelled'; - if (seriesTimerId && hasTimer) { - // cancel - return showMultiCancellationPrompt(serverId, programId, timerId, timerStatus, seriesTimerId); - } else if (hasTimer && programId) { - // change to series recording, if possible - // otherwise cancel individual recording - return changeRecordingToSeries(apiClient, timerId, programId, true); - } else if (programId) { - // schedule recording - return createRecording(apiClient, programId); - } else { - return Promise.reject(); - } +function toggleRecording(serverId, programId, timerId, timerStatus, seriesTimerId) { + const apiClient = connectionManager.getApiClient(serverId); + const hasTimer = timerId && timerStatus !== 'Cancelled'; + if (seriesTimerId && hasTimer) { + // cancel + return showMultiCancellationPrompt(serverId, programId, timerId, timerStatus, seriesTimerId); + } else if (hasTimer && programId) { + // change to series recording, if possible + // otherwise cancel individual recording + return changeRecordingToSeries(apiClient, timerId, programId, true); + } else if (programId) { + // schedule recording + return createRecording(apiClient, programId); + } else { + return Promise.reject(); } +} + +export default { + cancelTimer: cancelTimer, + createRecording: createRecording, + changeRecordingToSeries: changeRecordingToSeries, + toggleRecording: toggleRecording, + cancelTimerWithConfirmation: cancelTimerWithConfirmation, + cancelSeriesTimerWithConfirmation: cancelSeriesTimerWithConfirmation +}; - return { - cancelTimer: cancelTimer, - createRecording: createRecording, - changeRecordingToSeries: changeRecordingToSeries, - toggleRecording: toggleRecording, - cancelTimerWithConfirmation: cancelTimerWithConfirmation, - cancelSeriesTimerWithConfirmation: cancelSeriesTimerWithConfirmation - }; -}); diff --git a/src/components/recordingcreator/seriesrecordingeditor.js b/src/components/recordingcreator/seriesrecordingeditor.js index b115e273e6..48fbbcf22c 100644 --- a/src/components/recordingcreator/seriesrecordingeditor.js +++ b/src/components/recordingcreator/seriesrecordingeditor.js @@ -1,143 +1,200 @@ -define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'connectionManager', 'require', 'loading', 'scrollHelper', 'imageLoader', 'datetime', 'scrollStyles', 'emby-button', 'emby-checkbox', 'emby-input', 'emby-select', 'paper-icon-button-light', 'css!./../formdialog', 'css!./recordingcreator', 'material-icons', 'flexStyles'], function (dialogHelper, globalize, layoutManager, mediaInfo, appHost, connectionManager, require, loading, scrollHelper, imageLoader, datetime) { - 'use strict'; +import dialogHelper from 'dialogHelper'; +import globalize from 'globalize'; +import layoutManager from 'layoutManager'; +import connectionManager from 'connectionManager'; +import loading from 'loading'; +import scrollHelper from 'scrollHelper'; +import datetime from 'datetime'; +import 'scrollStyles'; +import 'emby-button'; +import 'emby-checkbox'; +import 'emby-input'; +import 'emby-select'; +import 'paper-icon-button-light'; +import 'css!./../formdialog'; +import 'css!./recordingcreator'; +import 'material-icons'; +import 'flexStyles'; - loading = loading.default || loading; +/*eslint prefer-const: "error"*/ - var currentDialog; - var recordingUpdated = false; - var recordingDeleted = false; - var currentItemId; - var currentServerId; +let currentDialog; +let recordingUpdated = false; +let recordingDeleted = false; +let currentItemId; +let currentServerId; - function deleteTimer(apiClient, timerId) { - return new Promise(function (resolve, reject) { - require(['recordingHelper'], function (recordingHelper) { - recordingHelper.cancelSeriesTimerWithConfirmation(timerId, apiClient.serverId()).then(resolve, reject); - }); +function deleteTimer(apiClient, timerId) { + return new Promise(function (resolve, reject) { + import('recordingHelper').then(({ default: recordingHelper }) => { + recordingHelper.cancelSeriesTimerWithConfirmation(timerId, apiClient.serverId()).then(resolve, reject); }); + }); +} + +function renderTimer(context, item) { + context.querySelector('#txtPrePaddingMinutes').value = item.PrePaddingSeconds / 60; + context.querySelector('#txtPostPaddingMinutes').value = item.PostPaddingSeconds / 60; + + context.querySelector('.selectChannels').value = item.RecordAnyChannel ? 'all' : 'one'; + context.querySelector('.selectAirTime').value = item.RecordAnyTime ? 'any' : 'original'; + + context.querySelector('.selectShowType').value = item.RecordNewOnly ? 'new' : 'all'; + context.querySelector('.chkSkipEpisodesInLibrary').checked = item.SkipEpisodesInLibrary; + context.querySelector('.selectKeepUpTo').value = item.KeepUpTo || 0; + + if (item.ChannelName || item.ChannelNumber) { + context.querySelector('.optionChannelOnly').innerHTML = globalize.translate('ChannelNameOnly', item.ChannelName || item.ChannelNumber); + } else { + context.querySelector('.optionChannelOnly').innerHTML = globalize.translate('OneChannel'); } - function renderTimer(context, item, apiClient) { - context.querySelector('#txtPrePaddingMinutes').value = item.PrePaddingSeconds / 60; - context.querySelector('#txtPostPaddingMinutes').value = item.PostPaddingSeconds / 60; + context.querySelector('.optionAroundTime').innerHTML = globalize.translate('AroundTime', datetime.getDisplayTime(datetime.parseISO8601Date(item.StartDate))); - context.querySelector('.selectChannels').value = item.RecordAnyChannel ? 'all' : 'one'; - context.querySelector('.selectAirTime').value = item.RecordAnyTime ? 'any' : 'original'; + loading.hide(); +} - context.querySelector('.selectShowType').value = item.RecordNewOnly ? 'new' : 'all'; - context.querySelector('.chkSkipEpisodesInLibrary').checked = item.SkipEpisodesInLibrary; - context.querySelector('.selectKeepUpTo').value = item.KeepUpTo || 0; +function closeDialog(isDeleted) { + recordingUpdated = true; + recordingDeleted = isDeleted; - if (item.ChannelName || item.ChannelNumber) { - context.querySelector('.optionChannelOnly').innerHTML = globalize.translate('ChannelNameOnly', item.ChannelName || item.ChannelNumber); - } else { - context.querySelector('.optionChannelOnly').innerHTML = globalize.translate('OneChannel'); - } + dialogHelper.close(currentDialog); +} - context.querySelector('.optionAroundTime').innerHTML = globalize.translate('AroundTime', datetime.getDisplayTime(datetime.parseISO8601Date(item.StartDate))); +function onSubmit(e) { + const form = this; + const apiClient = connectionManager.getApiClient(currentServerId); + + apiClient.getLiveTvSeriesTimer(currentItemId).then(function (item) { + item.PrePaddingSeconds = form.querySelector('#txtPrePaddingMinutes').value * 60; + item.PostPaddingSeconds = form.querySelector('#txtPostPaddingMinutes').value * 60; + item.RecordAnyChannel = form.querySelector('.selectChannels').value === 'all'; + item.RecordAnyTime = form.querySelector('.selectAirTime').value === 'any'; + item.RecordNewOnly = form.querySelector('.selectShowType').value === 'new'; + item.SkipEpisodesInLibrary = form.querySelector('.chkSkipEpisodesInLibrary').checked; + item.KeepUpTo = form.querySelector('.selectKeepUpTo').value; + + apiClient.updateLiveTvSeriesTimer(item); + }); + + e.preventDefault(); + + // Disable default form submission + return false; +} + +function init(context) { + fillKeepUpTo(context); + + context.querySelector('.btnCancel').addEventListener('click', function () { + closeDialog(false); + }); + + context.querySelector('.btnCancelRecording').addEventListener('click', function () { + const apiClient = connectionManager.getApiClient(currentServerId); + deleteTimer(apiClient, currentItemId).then(function () { + closeDialog(true); + }); + }); + + context.querySelector('form').addEventListener('submit', onSubmit); +} + +function reload(context, id) { + const apiClient = connectionManager.getApiClient(currentServerId); + + loading.show(); + if (typeof id === 'string') { + currentItemId = id; + + apiClient.getLiveTvSeriesTimer(id).then(function (result) { + renderTimer(context, result); + loading.hide(); + }); + } else if (id) { + currentItemId = id.Id; + + renderTimer(context, id); loading.hide(); } +} - function closeDialog(isDeleted) { - recordingUpdated = true; - recordingDeleted = isDeleted; +function fillKeepUpTo(context) { + let html = ''; - dialogHelper.close(currentDialog); - } + for (let i = 0; i <= 50; i++) { + let text; - function onSubmit(e) { - var form = this; - - var apiClient = connectionManager.getApiClient(currentServerId); - - apiClient.getLiveTvSeriesTimer(currentItemId).then(function (item) { - item.PrePaddingSeconds = form.querySelector('#txtPrePaddingMinutes').value * 60; - item.PostPaddingSeconds = form.querySelector('#txtPostPaddingMinutes').value * 60; - item.RecordAnyChannel = form.querySelector('.selectChannels').value === 'all'; - item.RecordAnyTime = form.querySelector('.selectAirTime').value === 'any'; - item.RecordNewOnly = form.querySelector('.selectShowType').value === 'new'; - item.SkipEpisodesInLibrary = form.querySelector('.chkSkipEpisodesInLibrary').checked; - item.KeepUpTo = form.querySelector('.selectKeepUpTo').value; - - apiClient.updateLiveTvSeriesTimer(item); - }); - - e.preventDefault(); - - // Disable default form submission - return false; - } - - function init(context) { - fillKeepUpTo(context); - - context.querySelector('.btnCancel').addEventListener('click', function () { - closeDialog(false); - }); - - context.querySelector('.btnCancelRecording').addEventListener('click', function () { - var apiClient = connectionManager.getApiClient(currentServerId); - deleteTimer(apiClient, currentItemId).then(function () { - closeDialog(true); - }); - }); - - context.querySelector('form').addEventListener('submit', onSubmit); - } - - function reload(context, id) { - var apiClient = connectionManager.getApiClient(currentServerId); - - loading.show(); - if (typeof id === 'string') { - currentItemId = id; - - apiClient.getLiveTvSeriesTimer(id).then(function (result) { - renderTimer(context, result, apiClient); - loading.hide(); - }); - } else if (id) { - currentItemId = id.Id; - - renderTimer(context, id, apiClient); - loading.hide(); - } - } - - function fillKeepUpTo(context) { - var html = ''; - - for (var i = 0; i <= 50; i++) { - var text; - - if (i === 0) { - text = globalize.translate('AsManyAsPossible'); - } else if (i === 1) { - text = globalize.translate('ValueOneEpisode'); - } else { - text = globalize.translate('ValueEpisodeCount', i); - } - - html += ''; + if (i === 0) { + text = globalize.translate('AsManyAsPossible'); + } else if (i === 1) { + text = globalize.translate('ValueOneEpisode'); + } else { + text = globalize.translate('ValueEpisodeCount', i); } - context.querySelector('.selectKeepUpTo').innerHTML = html; + html += ''; } - function onFieldChange(e) { - this.querySelector('.btnSubmit').click(); - } + context.querySelector('.selectKeepUpTo').innerHTML = html; +} - function embed(itemId, serverId, options) { +function onFieldChange() { + this.querySelector('.btnSubmit').click(); +} + +function embed(itemId, serverId, options) { + recordingUpdated = false; + recordingDeleted = false; + currentServerId = serverId; + loading.show(); + options = options || {}; + + import('text!./seriesrecordingeditor.template.html').then(({ default: template }) => { + const dialogOptions = { + removeOnClose: true, + scrollY: false + }; + + if (layoutManager.tv) { + dialogOptions.size = 'fullscreen'; + } else { + dialogOptions.size = 'small'; + } + + const dlg = options.context; + + dlg.classList.add('hide'); + dlg.innerHTML = globalize.translateHtml(template, 'core'); + + dlg.querySelector('.formDialogHeader').classList.add('hide'); + dlg.querySelector('.formDialogFooter').classList.add('hide'); + dlg.querySelector('.formDialogContent').className = ''; + dlg.querySelector('.dialogContentInner').className = ''; + dlg.classList.remove('hide'); + + dlg.removeEventListener('change', onFieldChange); + dlg.addEventListener('change', onFieldChange); + + currentDialog = dlg; + + init(dlg); + + reload(dlg, itemId); + }); +} + +function showEditor(itemId, serverId, options) { + return new Promise(function (resolve, reject) { recordingUpdated = false; recordingDeleted = false; currentServerId = serverId; loading.show(); options = options || {}; - require(['text!./seriesrecordingeditor.template.html'], function (template) { - var dialogOptions = { + import('text!./seriesrecordingeditor.template.html').then(({ default: template }) => { + const dialogOptions = { removeOnClose: true, scrollY: false }; @@ -148,101 +205,58 @@ define(['dialogHelper', 'globalize', 'layoutManager', 'mediaInfo', 'apphost', 'c dialogOptions.size = 'small'; } - var dlg = options.context; + const dlg = dialogHelper.createDialog(dialogOptions); - dlg.classList.add('hide'); - dlg.innerHTML = globalize.translateHtml(template, 'core'); + dlg.classList.add('formDialog'); + dlg.classList.add('recordingDialog'); - dlg.querySelector('.formDialogHeader').classList.add('hide'); - dlg.querySelector('.formDialogFooter').classList.add('hide'); - dlg.querySelector('.formDialogContent').className = ''; - dlg.querySelector('.dialogContentInner').className = ''; - dlg.classList.remove('hide'); + if (!layoutManager.tv) { + dlg.style['min-width'] = '20%'; + } - dlg.removeEventListener('change', onFieldChange); - dlg.addEventListener('change', onFieldChange); + let html = ''; + + html += globalize.translateHtml(template, 'core'); + + dlg.innerHTML = html; + + if (options.enableCancel === false) { + dlg.querySelector('.formDialogFooter').classList.add('hide'); + } currentDialog = dlg; + dlg.addEventListener('closing', function () { + if (!recordingDeleted) { + this.querySelector('.btnSubmit').click(); + } + }); + + dlg.addEventListener('close', function () { + if (recordingUpdated) { + resolve({ + updated: true, + deleted: recordingDeleted + }); + } else { + reject(); + } + }); + + if (layoutManager.tv) { + scrollHelper.centerFocus.on(dlg.querySelector('.formDialogContent'), false); + } + init(dlg); reload(dlg, itemId); + + dialogHelper.open(dlg); }); - } + }); +} - function showEditor(itemId, serverId, options) { - return new Promise(function (resolve, reject) { - recordingUpdated = false; - recordingDeleted = false; - currentServerId = serverId; - loading.show(); - options = options || {}; - - require(['text!./seriesrecordingeditor.template.html'], function (template) { - var dialogOptions = { - removeOnClose: true, - scrollY: false - }; - - if (layoutManager.tv) { - dialogOptions.size = 'fullscreen'; - } else { - dialogOptions.size = 'small'; - } - - var dlg = dialogHelper.createDialog(dialogOptions); - - dlg.classList.add('formDialog'); - dlg.classList.add('recordingDialog'); - - if (!layoutManager.tv) { - dlg.style['min-width'] = '20%'; - } - - var html = ''; - - html += globalize.translateHtml(template, 'core'); - - dlg.innerHTML = html; - - if (options.enableCancel === false) { - dlg.querySelector('.formDialogFooter').classList.add('hide'); - } - - currentDialog = dlg; - - dlg.addEventListener('closing', function () { - if (!recordingDeleted) { - this.querySelector('.btnSubmit').click(); - } - }); - - dlg.addEventListener('close', function () { - if (recordingUpdated) { - resolve({ - updated: true, - deleted: recordingDeleted - }); - } else { - reject(); - } - }); - - if (layoutManager.tv) { - scrollHelper.centerFocus.on(dlg.querySelector('.formDialogContent'), false); - } - - init(dlg); - - reload(dlg, itemId); - - dialogHelper.open(dlg); - }); - }); - } - - return { - show: showEditor, - embed: embed - }; -}); +export default { + show: showEditor, + embed: embed +}; diff --git a/src/components/tvproviders/schedulesdirect.js b/src/components/tvproviders/schedulesdirect.js index a0c29f48b8..de469e1845 100644 --- a/src/components/tvproviders/schedulesdirect.js +++ b/src/components/tvproviders/schedulesdirect.js @@ -1,299 +1,304 @@ -define(['jQuery', 'loading', 'globalize', 'emby-checkbox', 'listViewStyle', 'emby-input', 'emby-select', 'emby-button', 'flexStyles'], function ($, loading, globalize) { - 'use strict'; +import $ from 'jQuery'; +import loading from 'loading'; +import globalize from 'globalize'; +import 'emby-checkbox'; +import 'emby-input'; +import 'listViewStyle'; +import 'paper-icon-button-light'; +import 'emby-select'; +import 'emby-button'; +import 'flexStyles'; - loading = loading.default || loading; +export default function (page, providerId, options) { + function reload() { + loading.show(); + ApiClient.getNamedConfiguration('livetv').then(function (config) { + const info = config.ListingProviders.filter(function (i) { + return i.Id === providerId; + })[0] || {}; + listingsId = info.ListingsId; + $('#selectListing', page).val(info.ListingsId || ''); + page.querySelector('.txtUser').value = info.Username || ''; + page.querySelector('.txtPass').value = ''; + page.querySelector('.txtZipCode').value = info.ZipCode || ''; - return function (page, providerId, options) { - function reload() { - loading.show(); - ApiClient.getNamedConfiguration('livetv').then(function (config) { - var info = config.ListingProviders.filter(function (i) { - return i.Id === providerId; - })[0] || {}; - listingsId = info.ListingsId; - $('#selectListing', page).val(info.ListingsId || ''); - page.querySelector('.txtUser').value = info.Username || ''; - page.querySelector('.txtPass').value = ''; - page.querySelector('.txtZipCode').value = info.ZipCode || ''; - - if (info.Username && info.Password) { - page.querySelector('.listingsSection').classList.remove('hide'); - } else { - page.querySelector('.listingsSection').classList.add('hide'); - } - - page.querySelector('.chkAllTuners').checked = info.EnableAllTuners; - - if (info.EnableAllTuners) { - page.querySelector('.selectTunersSection').classList.add('hide'); - } else { - page.querySelector('.selectTunersSection').classList.remove('hide'); - } - - setCountry(info); - refreshTunerDevices(page, info, config.TunerHosts); - }); - } - - function setCountry(info) { - ApiClient.getJSON(ApiClient.getUrl('LiveTv/ListingProviders/SchedulesDirect/Countries')).then(function (result) { - var i; - var length; - var countryList = []; - - for (var region in result) { - var countries = result[region]; - - if (countries.length && region !== 'ZZZ') { - for (i = 0, length = countries.length; i < length; i++) { - countryList.push({ - name: countries[i].fullName, - value: countries[i].shortName - }); - } - } - } - - countryList.sort(function (a, b) { - if (a.name > b.name) { - return 1; - } - - if (a.name < b.name) { - return -1; - } - - return 0; - }); - $('#selectCountry', page).html(countryList.map(function (c) { - return ''; - }).join('')).val(info.Country || ''); - $(page.querySelector('.txtZipCode')).trigger('change'); - }, function () { // ApiClient.getJSON() error handler - Dashboard.alert({ - message: globalize.translate('ErrorGettingTvLineups') - }); - }); - loading.hide(); - } - - function sha256(str) { - if (!self.TextEncoder) { - return Promise.resolve(''); + if (info.Username && info.Password) { + page.querySelector('.listingsSection').classList.remove('hide'); + } else { + page.querySelector('.listingsSection').classList.add('hide'); } - var buffer = new TextEncoder('utf-8').encode(str); - return crypto.subtle.digest('SHA-256', buffer).then(function (hash) { - return hex(hash); - }); - } + page.querySelector('.chkAllTuners').checked = info.EnableAllTuners; - function hex(buffer) { - var hexCodes = []; - var view = new DataView(buffer); - - for (var i = 0; i < view.byteLength; i += 4) { - var value = view.getUint32(i); - var stringValue = value.toString(16); - var paddedValue = ('00000000' + stringValue).slice(-'00000000'.length); - hexCodes.push(paddedValue); + if (info.EnableAllTuners) { + page.querySelector('.selectTunersSection').classList.add('hide'); + } else { + page.querySelector('.selectTunersSection').classList.remove('hide'); } - return hexCodes.join(''); - } + setCountry(info); + refreshTunerDevices(page, info, config.TunerHosts); + }); + } - function submitLoginForm() { - loading.show(); - sha256(page.querySelector('.txtPass').value).then(function (passwordHash) { - var info = { - Type: 'SchedulesDirect', - Username: page.querySelector('.txtUser').value, - EnableAllTuners: true, - Password: passwordHash, - Pw: page.querySelector('.txtPass').value - }; - var id = providerId; + function setCountry(info) { + ApiClient.getJSON(ApiClient.getUrl('LiveTv/ListingProviders/SchedulesDirect/Countries')).then(function (result) { + let i; + let length; + const countryList = []; - if (id) { - info.Id = id; + for (const region in result) { + const countries = result[region]; + + if (countries.length && region !== 'ZZZ') { + for (i = 0, length = countries.length; i < length; i++) { + countryList.push({ + name: countries[i].fullName, + value: countries[i].shortName + }); + } + } + } + + countryList.sort(function (a, b) { + if (a.name > b.name) { + return 1; } - ApiClient.ajax({ - type: 'POST', - url: ApiClient.getUrl('LiveTv/ListingProviders', { - ValidateLogin: true - }), - data: JSON.stringify(info), - contentType: 'application/json', - dataType: 'json' - }).then(function (result) { - Dashboard.processServerConfigurationUpdateResult(); - providerId = result.Id; - reload(); - }, function () { - Dashboard.alert({ // ApiClient.ajax() error handler - message: globalize.translate('ErrorSavingTvProvider') - }); - }); + if (a.name < b.name) { + return -1; + } + + return 0; }); + $('#selectCountry', page).html(countryList.map(function (c) { + return ''; + }).join('')).val(info.Country || ''); + $(page.querySelector('.txtZipCode')).trigger('change'); + }, function () { // ApiClient.getJSON() error handler + Dashboard.alert({ + message: globalize.translate('ErrorGettingTvLineups') + }); + }); + loading.hide(); + } + + function sha256(str) { + if (!self.TextEncoder) { + return Promise.resolve(''); } - function submitListingsForm() { - var selectedListingsId = $('#selectListing', page).val(); + const buffer = new TextEncoder('utf-8').encode(str); + return crypto.subtle.digest('SHA-256', buffer).then(function (hash) { + return hex(hash); + }); + } - if (!selectedListingsId) { - return void Dashboard.alert({ - message: globalize.translate('ErrorPleaseSelectLineup') - }); - } + function hex(buffer) { + const hexCodes = []; + const view = new DataView(buffer); - loading.show(); - var id = providerId; - ApiClient.getNamedConfiguration('livetv').then(function (config) { - var info = config.ListingProviders.filter(function (i) { - return i.Id === id; - })[0]; - info.ZipCode = page.querySelector('.txtZipCode').value; - info.Country = $('#selectCountry', page).val(); - info.ListingsId = selectedListingsId; - info.EnableAllTuners = page.querySelector('.chkAllTuners').checked; - info.EnabledTuners = info.EnableAllTuners ? [] : $('.chkTuner', page).get().filter(function (i) { - return i.checked; - }).map(function (i) { - return i.getAttribute('data-id'); - }); - ApiClient.ajax({ - type: 'POST', - url: ApiClient.getUrl('LiveTv/ListingProviders', { - ValidateListings: true - }), - data: JSON.stringify(info), - contentType: 'application/json' - }).then(function (result) { - loading.hide(); - - if (options.showConfirmation) { - Dashboard.processServerConfigurationUpdateResult(); - } - - Events.trigger(self, 'submitted'); - }, function () { - loading.hide(); - Dashboard.alert({ - message: globalize.translate('ErrorAddingListingsToSchedulesDirect') - }); - }); - }); + for (let i = 0; i < view.byteLength; i += 4) { + const value = view.getUint32(i); + const stringValue = value.toString(16); + const paddedValue = ('00000000' + stringValue).slice(-'00000000'.length); + hexCodes.push(paddedValue); } - function refreshListings(value) { - if (!value) { - return void $('#selectListing', page).html(''); + return hexCodes.join(''); + } + + function submitLoginForm() { + loading.show(); + sha256(page.querySelector('.txtPass').value).then(function (passwordHash) { + const info = { + Type: 'SchedulesDirect', + Username: page.querySelector('.txtUser').value, + EnableAllTuners: true, + Password: passwordHash, + Pw: page.querySelector('.txtPass').value + }; + const id = providerId; + + if (id) { + info.Id = id; } - loading.show(); ApiClient.ajax({ - type: 'GET', - url: ApiClient.getUrl('LiveTv/ListingProviders/Lineups', { - Id: providerId, - Location: value, - Country: $('#selectCountry', page).val() + type: 'POST', + url: ApiClient.getUrl('LiveTv/ListingProviders', { + ValidateLogin: true }), + data: JSON.stringify(info), + contentType: 'application/json', dataType: 'json' }).then(function (result) { - $('#selectListing', page).html(result.map(function (o) { - return ''; - })); - - if (listingsId) { - $('#selectListing', page).val(listingsId); - } - - loading.hide(); - }, function (result) { - Dashboard.alert({ - message: globalize.translate('ErrorGettingTvLineups') + Dashboard.processServerConfigurationUpdateResult(); + providerId = result.Id; + reload(); + }, function () { + Dashboard.alert({ // ApiClient.ajax() error handler + message: globalize.translate('ErrorSavingTvProvider') }); - refreshListings(''); + }); + }); + } + + function submitListingsForm() { + const selectedListingsId = $('#selectListing', page).val(); + + if (!selectedListingsId) { + return void Dashboard.alert({ + message: globalize.translate('ErrorPleaseSelectLineup') + }); + } + + loading.show(); + const id = providerId; + ApiClient.getNamedConfiguration('livetv').then(function (config) { + const info = config.ListingProviders.filter(function (i) { + return i.Id === id; + })[0]; + info.ZipCode = page.querySelector('.txtZipCode').value; + info.Country = $('#selectCountry', page).val(); + info.ListingsId = selectedListingsId; + info.EnableAllTuners = page.querySelector('.chkAllTuners').checked; + info.EnabledTuners = info.EnableAllTuners ? [] : $('.chkTuner', page).get().filter(function (i) { + return i.checked; + }).map(function (i) { + return i.getAttribute('data-id'); + }); + ApiClient.ajax({ + type: 'POST', + url: ApiClient.getUrl('LiveTv/ListingProviders', { + ValidateListings: true + }), + data: JSON.stringify(info), + contentType: 'application/json' + }).then(function (result) { loading.hide(); - }); - } - function getTunerName(providerId) { - switch (providerId = providerId.toLowerCase()) { - case 'm3u': - return 'M3U Playlist'; - case 'hdhomerun': - return 'HDHomerun'; - case 'satip': - return 'DVB'; - default: - return 'Unknown'; - } - } - - function refreshTunerDevices(page, providerInfo, devices) { - var html = ''; - - for (var i = 0, length = devices.length; i < length; i++) { - var device = devices[i]; - html += '
'; - var enabledTuners = providerInfo.EnabledTuners || []; - var isChecked = providerInfo.EnableAllTuners || enabledTuners.indexOf(device.Id) !== -1; - var checkedAttribute = isChecked ? ' checked' : ''; - html += ''; - html += '
'; - html += '
'; - html += device.FriendlyName || getTunerName(device.Type); - html += '
'; - html += '
'; - html += device.Url; - html += '
'; - html += '
'; - html += '
'; - } - - page.querySelector('.tunerList').innerHTML = html; - } - - var listingsId; - var self = this; - - self.submit = function () { - page.querySelector('.btnSubmitListingsContainer').click(); - }; - - self.init = function () { - options = options || {}; - - // Only hide the buttons if explicitly set to false; default to showing if undefined or null - // FIXME: rename this option to clarify logic - var hideCancelButton = options.showCancelButton === false; - page.querySelector('.btnCancel').classList.toggle('hide', hideCancelButton); - - var hideSubmitButton = options.showSubmitButton === false; - page.querySelector('.btnSubmitListings').classList.toggle('hide', hideSubmitButton); - - $('.formLogin', page).on('submit', function () { - submitLoginForm(); - return false; - }); - $('.formListings', page).on('submit', function () { - submitListingsForm(); - return false; - }); - $('.txtZipCode', page).on('change', function () { - refreshListings(this.value); - }); - page.querySelector('.chkAllTuners').addEventListener('change', function (e) { - if (e.target.checked) { - page.querySelector('.selectTunersSection').classList.add('hide'); - } else { - page.querySelector('.selectTunersSection').classList.remove('hide'); + if (options.showConfirmation) { + Dashboard.processServerConfigurationUpdateResult(); } + + Events.trigger(self, 'submitted'); + }, function () { + loading.hide(); + Dashboard.alert({ + message: globalize.translate('ErrorAddingListingsToSchedulesDirect') + }); }); - $('.createAccountHelp', page).html(globalize.translate('MessageCreateAccountAt', 'http://www.schedulesdirect.org')); - reload(); - }; + }); + } + + function refreshListings(value) { + if (!value) { + return void $('#selectListing', page).html(''); + } + + loading.show(); + ApiClient.ajax({ + type: 'GET', + url: ApiClient.getUrl('LiveTv/ListingProviders/Lineups', { + Id: providerId, + Location: value, + Country: $('#selectCountry', page).val() + }), + dataType: 'json' + }).then(function (result) { + $('#selectListing', page).html(result.map(function (o) { + return ''; + })); + + if (listingsId) { + $('#selectListing', page).val(listingsId); + } + + loading.hide(); + }, function (result) { + Dashboard.alert({ + message: globalize.translate('ErrorGettingTvLineups') + }); + refreshListings(''); + loading.hide(); + }); + } + + function getTunerName(providerId) { + switch (providerId = providerId.toLowerCase()) { + case 'm3u': + return 'M3U Playlist'; + case 'hdhomerun': + return 'HDHomerun'; + case 'satip': + return 'DVB'; + default: + return 'Unknown'; + } + } + + function refreshTunerDevices(page, providerInfo, devices) { + let html = ''; + + for (let i = 0, length = devices.length; i < length; i++) { + const device = devices[i]; + html += '
'; + const enabledTuners = providerInfo.EnabledTuners || []; + const isChecked = providerInfo.EnableAllTuners || enabledTuners.indexOf(device.Id) !== -1; + const checkedAttribute = isChecked ? ' checked' : ''; + html += ''; + html += '
'; + html += '
'; + html += device.FriendlyName || getTunerName(device.Type); + html += '
'; + html += '
'; + html += device.Url; + html += '
'; + html += '
'; + html += '
'; + } + + page.querySelector('.tunerList').innerHTML = html; + } + + let listingsId; + const self = this; + + self.submit = function () { + page.querySelector('.btnSubmitListingsContainer').click(); }; -}); + + self.init = function () { + options = options || {}; + + // Only hide the buttons if explicitly set to false; default to showing if undefined or null + // FIXME: rename this option to clarify logic + const hideCancelButton = options.showCancelButton === false; + page.querySelector('.btnCancel').classList.toggle('hide', hideCancelButton); + + const hideSubmitButton = options.showSubmitButton === false; + page.querySelector('.btnSubmitListings').classList.toggle('hide', hideSubmitButton); + + $('.formLogin', page).on('submit', function () { + submitLoginForm(); + return false; + }); + $('.formListings', page).on('submit', function () { + submitListingsForm(); + return false; + }); + $('.txtZipCode', page).on('change', function () { + refreshListings(this.value); + }); + page.querySelector('.chkAllTuners').addEventListener('change', function (e) { + if (e.target.checked) { + page.querySelector('.selectTunersSection').classList.add('hide'); + } else { + page.querySelector('.selectTunersSection').classList.remove('hide'); + } + }); + $('.createAccountHelp', page).html(globalize.translate('MessageCreateAccountAt', 'http://www.schedulesdirect.org')); + reload(); + }; +} diff --git a/src/components/tvproviders/xmltv.js b/src/components/tvproviders/xmltv.js index 2203bc1fea..a75b29eeb3 100644 --- a/src/components/tvproviders/xmltv.js +++ b/src/components/tvproviders/xmltv.js @@ -1,191 +1,193 @@ -define(['jQuery', 'loading', 'globalize', 'emby-checkbox', 'emby-input', 'listViewStyle', 'paper-icon-button-light'], function ($, loading, globalize) { - 'use strict'; +import $ from 'jQuery'; +import loading from 'loading'; +import globalize from 'globalize'; +import 'emby-checkbox'; +import 'emby-input'; +import 'listViewStyle'; +import 'paper-icon-button-light'; - loading = loading.default || loading; +export default function (page, providerId, options) { + function getListingProvider(config, id) { + if (config && id) { + const result = config.ListingProviders.filter(function (provider) { + return provider.Id === id; + })[0]; - return function (page, providerId, options) { - function getListingProvider(config, id) { - if (config && id) { - var result = config.ListingProviders.filter(function (provider) { - return provider.Id === id; - })[0]; - - if (result) { - return Promise.resolve(result); - } - - return getListingProvider(); + if (result) { + return Promise.resolve(result); } - return ApiClient.getJSON(ApiClient.getUrl('LiveTv/ListingProviders/Default')); + return getListingProvider(); } - function reload() { - loading.show(); - ApiClient.getNamedConfiguration('livetv').then(function (config) { - getListingProvider(config, providerId).then(function (info) { - page.querySelector('.txtPath').value = info.Path || ''; - page.querySelector('.txtKids').value = (info.KidsCategories || []).join('|'); - page.querySelector('.txtNews').value = (info.NewsCategories || []).join('|'); - page.querySelector('.txtSports').value = (info.SportsCategories || []).join('|'); - page.querySelector('.txtMovies').value = (info.MovieCategories || []).join('|'); - page.querySelector('.txtMoviePrefix').value = info.MoviePrefix || ''; - page.querySelector('.txtUserAgent').value = info.UserAgent || ''; - page.querySelector('.chkAllTuners').checked = info.EnableAllTuners; + return ApiClient.getJSON(ApiClient.getUrl('LiveTv/ListingProviders/Default')); + } - if (page.querySelector('.chkAllTuners').checked) { - page.querySelector('.selectTunersSection').classList.add('hide'); - } else { - page.querySelector('.selectTunersSection').classList.remove('hide'); - } + function reload() { + loading.show(); + ApiClient.getNamedConfiguration('livetv').then(function (config) { + getListingProvider(config, providerId).then(function (info) { + page.querySelector('.txtPath').value = info.Path || ''; + page.querySelector('.txtKids').value = (info.KidsCategories || []).join('|'); + page.querySelector('.txtNews').value = (info.NewsCategories || []).join('|'); + page.querySelector('.txtSports').value = (info.SportsCategories || []).join('|'); + page.querySelector('.txtMovies').value = (info.MovieCategories || []).join('|'); + page.querySelector('.txtMoviePrefix').value = info.MoviePrefix || ''; + page.querySelector('.txtUserAgent').value = info.UserAgent || ''; + page.querySelector('.chkAllTuners').checked = info.EnableAllTuners; - refreshTunerDevices(page, info, config.TunerHosts); - loading.hide(); - }); - }); - } - - function getCategories(txtInput) { - var value = txtInput.value; - - if (value) { - return value.split('|'); - } - - return []; - } - - function submitListingsForm() { - loading.show(); - var id = providerId; - ApiClient.getNamedConfiguration('livetv').then(function (config) { - var info = config.ListingProviders.filter(function (provider) { - return provider.Id === id; - })[0] || {}; - info.Type = 'xmltv'; - info.Path = page.querySelector('.txtPath').value; - info.MoviePrefix = page.querySelector('.txtMoviePrefix').value || null; - info.UserAgent = page.querySelector('.txtUserAgent').value || null; - info.MovieCategories = getCategories(page.querySelector('.txtMovies')); - info.KidsCategories = getCategories(page.querySelector('.txtKids')); - info.NewsCategories = getCategories(page.querySelector('.txtNews')); - info.SportsCategories = getCategories(page.querySelector('.txtSports')); - info.EnableAllTuners = page.querySelector('.chkAllTuners').checked; - info.EnabledTuners = info.EnableAllTuners ? [] : $('.chkTuner', page).get().filter(function (tuner) { - return tuner.checked; - }).map(function (tuner) { - return tuner.getAttribute('data-id'); - }); - ApiClient.ajax({ - type: 'POST', - url: ApiClient.getUrl('LiveTv/ListingProviders', { - ValidateListings: true - }), - data: JSON.stringify(info), - contentType: 'application/json' - }).then(function (result) { - loading.hide(); - - if (options.showConfirmation !== false) { - Dashboard.processServerConfigurationUpdateResult(); - } - - Events.trigger(self, 'submitted'); - }, function () { - loading.hide(); - Dashboard.alert({ - message: globalize.translate('ErrorAddingXmlTvFile') - }); - }); - }); - } - - function getTunerName(providerId) { - switch (providerId = providerId.toLowerCase()) { - case 'm3u': - return 'M3U Playlist'; - case 'hdhomerun': - return 'HDHomerun'; - case 'satip': - return 'DVB'; - default: - return 'Unknown'; - } - } - - function refreshTunerDevices(page, providerInfo, devices) { - var html = ''; - - for (var i = 0, length = devices.length; i < length; i++) { - var device = devices[i]; - html += '
'; - var enabledTuners = providerInfo.EnabledTuners || []; - var isChecked = providerInfo.EnableAllTuners || enabledTuners.indexOf(device.Id) !== -1; - var checkedAttribute = isChecked ? ' checked' : ''; - html += ''; - html += '
'; - html += '
'; - html += device.FriendlyName || getTunerName(device.Type); - html += '
'; - html += '
'; - html += device.Url; - html += '
'; - html += '
'; - html += '
'; - } - - page.querySelector('.tunerList').innerHTML = html; - } - - function onSelectPathClick(e) { - var page = $(e.target).parents('.xmltvForm')[0]; - - require(['directorybrowser'], function (directoryBrowser) { - var picker = new directoryBrowser.default(); - picker.show({ - includeFiles: true, - callback: function (path) { - if (path) { - var txtPath = page.querySelector('.txtPath'); - txtPath.value = path; - txtPath.focus(); - } - picker.close(); - } - }); - }); - } - - var self = this; - - self.submit = function () { - page.querySelector('.btnSubmitListings').click(); - }; - - self.init = function () { - options = options || {}; - - // Only hide the buttons if explicitly set to false; default to showing if undefined or null - // FIXME: rename this option to clarify logic - var hideCancelButton = options.showCancelButton === false; - page.querySelector('.btnCancel').classList.toggle('hide', hideCancelButton); - - var hideSubmitButton = options.showSubmitButton === false; - page.querySelector('.btnSubmitListings').classList.toggle('hide', hideSubmitButton); - - $('form', page).on('submit', function () { - submitListingsForm(); - return false; - }); - page.querySelector('#btnSelectPath').addEventListener('click', onSelectPathClick); - page.querySelector('.chkAllTuners').addEventListener('change', function (evt) { - if (evt.target.checked) { + if (page.querySelector('.chkAllTuners').checked) { page.querySelector('.selectTunersSection').classList.add('hide'); } else { page.querySelector('.selectTunersSection').classList.remove('hide'); } + + refreshTunerDevices(page, info, config.TunerHosts); + loading.hide(); }); - reload(); - }; + }); + } + + function getCategories(txtInput) { + const value = txtInput.value; + + if (value) { + return value.split('|'); + } + + return []; + } + + function submitListingsForm() { + loading.show(); + const id = providerId; + ApiClient.getNamedConfiguration('livetv').then(function (config) { + const info = config.ListingProviders.filter(function (provider) { + return provider.Id === id; + })[0] || {}; + info.Type = 'xmltv'; + info.Path = page.querySelector('.txtPath').value; + info.MoviePrefix = page.querySelector('.txtMoviePrefix').value || null; + info.UserAgent = page.querySelector('.txtUserAgent').value || null; + info.MovieCategories = getCategories(page.querySelector('.txtMovies')); + info.KidsCategories = getCategories(page.querySelector('.txtKids')); + info.NewsCategories = getCategories(page.querySelector('.txtNews')); + info.SportsCategories = getCategories(page.querySelector('.txtSports')); + info.EnableAllTuners = page.querySelector('.chkAllTuners').checked; + info.EnabledTuners = info.EnableAllTuners ? [] : $('.chkTuner', page).get().filter(function (tuner) { + return tuner.checked; + }).map(function (tuner) { + return tuner.getAttribute('data-id'); + }); + ApiClient.ajax({ + type: 'POST', + url: ApiClient.getUrl('LiveTv/ListingProviders', { + ValidateListings: true + }), + data: JSON.stringify(info), + contentType: 'application/json' + }).then(function (result) { + loading.hide(); + + if (options.showConfirmation !== false) { + Dashboard.processServerConfigurationUpdateResult(); + } + + Events.trigger(self, 'submitted'); + }, function () { + loading.hide(); + Dashboard.alert({ + message: globalize.translate('ErrorAddingXmlTvFile') + }); + }); + }); + } + + function getTunerName(providerId) { + switch (providerId = providerId.toLowerCase()) { + case 'm3u': + return 'M3U Playlist'; + case 'hdhomerun': + return 'HDHomerun'; + case 'satip': + return 'DVB'; + default: + return 'Unknown'; + } + } + + function refreshTunerDevices(page, providerInfo, devices) { + let html = ''; + + for (let i = 0, length = devices.length; i < length; i++) { + const device = devices[i]; + html += '
'; + const enabledTuners = providerInfo.EnabledTuners || []; + const isChecked = providerInfo.EnableAllTuners || enabledTuners.indexOf(device.Id) !== -1; + const checkedAttribute = isChecked ? ' checked' : ''; + html += ''; + html += '
'; + html += '
'; + html += device.FriendlyName || getTunerName(device.Type); + html += '
'; + html += '
'; + html += device.Url; + html += '
'; + html += '
'; + html += '
'; + } + + page.querySelector('.tunerList').innerHTML = html; + } + + function onSelectPathClick(e) { + const page = $(e.target).parents('.xmltvForm')[0]; + + import('directorybrowser').then(({default: directoryBrowser}) => { + const picker = new directoryBrowser(); + picker.show({ + includeFiles: true, + callback: function (path) { + if (path) { + const txtPath = page.querySelector('.txtPath'); + txtPath.value = path; + txtPath.focus(); + } + picker.close(); + } + }); + }); + } + + const self = this; + + self.submit = function () { + page.querySelector('.btnSubmitListings').click(); }; -}); + + self.init = function () { + options = options || {}; + + // Only hide the buttons if explicitly set to false; default to showing if undefined or null + // FIXME: rename this option to clarify logic + const hideCancelButton = options.showCancelButton === false; + page.querySelector('.btnCancel').classList.toggle('hide', hideCancelButton); + + const hideSubmitButton = options.showSubmitButton === false; + page.querySelector('.btnSubmitListings').classList.toggle('hide', hideSubmitButton); + + $('form', page).on('submit', function () { + submitListingsForm(); + return false; + }); + page.querySelector('#btnSelectPath').addEventListener('click', onSelectPathClick); + page.querySelector('.chkAllTuners').addEventListener('change', function (evt) { + if (evt.target.checked) { + page.querySelector('.selectTunersSection').classList.add('hide'); + } else { + page.querySelector('.selectTunersSection').classList.remove('hide'); + } + }); + reload(); + }; +} diff --git a/src/strings/he.json b/src/strings/he.json index c61bfe9e1a..58eb6ee1b4 100644 --- a/src/strings/he.json +++ b/src/strings/he.json @@ -157,7 +157,7 @@ "LabelBirthYear": "שנת לידה:", "LabelBlastMessageInterval": "תדירות הודעות דחיפה", "LabelBlastMessageIntervalHelp": "מגדיר את משך הזמן בשניות בין הודעות דחיפה של השרת.", - "LabelCachePath": "נתיב cache:", + "LabelCachePath": "נתיב מטמון:", "LabelChannels": "ערוצים:", "LabelCollection": "אוספים:", "LabelCommunityRating": "דירוג הקהילה:", @@ -204,7 +204,7 @@ "LabelMaxScreenshotsPerItem": "מספר תמונות מסך מקסימאלי לפריט:", "LabelMessageTitle": "כותרת הודעה:", "LabelMetadataDownloadLanguage": "שפת הורדה מועדפת:", - "LabelMetadataPath": "נתיב Metadata:", + "LabelMetadataPath": "נתיב מטא-דאטה:", "LabelMinBackdropDownloadWidth": "רוחב תמונת רקע מינימאלי להורדה:", "LabelMinResumeDuration": "משך המשכה מינימאלי:", "LabelMinResumeDurationHelp": "קובץ קצר מזה לא יהיה ניתן להמשך ניגון מנקודת העצירה", @@ -302,7 +302,7 @@ "OptionAlbumArtist": "אמן אלבום", "OptionAllUsers": "כל המשתמשים", "OptionAllowLinkSharing": "אפשר שיתוף ברשתות חברתיות", - "OptionAllowMediaPlayback": "הרשה נגינת מדיה", + "OptionAllowMediaPlayback": "אפשר ניגון מדיה", "OptionAllowUserToManageServer": "אפשר למשתמש זה לנהל את השרת", "OptionArtist": "אמן", "OptionAscending": "סדר עולה", @@ -314,7 +314,7 @@ "OptionContinuing": "ממשיך", "OptionCriticRating": "ציון מבקרים", "OptionCustomUsers": "מותאם אישית", - "OptionDaily": "יומי", + "OptionDaily": "כל יום", "OptionDateAdded": "תאריך הוספה", "OptionDatePlayed": "תאריך ניגון", "OptionDescending": "סדר יורד", @@ -337,7 +337,7 @@ "OptionHasSubtitles": "כתוביות", "OptionHasThemeSong": "שיר נושא", "OptionHasThemeVideo": "סרט נושא", - "OptionHasTrailer": "טריילר", + "OptionHasTrailer": "קדימון", "OptionHideUser": "הסתר משתמש זה בחלון ההתחברות", "OptionImdbRating": "דירוג IMDb", "OptionLikes": "נבחרים", @@ -348,27 +348,27 @@ "OptionOnAppStartup": "בהפעלת התוכנה", "OptionOnInterval": "כל פרק זמן", "OptionParentalRating": "דירוג בקרת הורים", - "OptionPlayCount": "מספר השמעות", + "OptionPlayCount": "כמות ניגונים", "OptionPlayed": "נוגן", - "OptionPremiereDate": "תאריך שידור ראשון", + "OptionPremiereDate": "תאריך בכורה", "OptionProfileAudio": "צליל", "OptionProfilePhoto": "תמונה", "OptionProfileVideo": "וידאו", "OptionProfileVideoAudio": "צליל וידאו", "OptionResumable": "ניתן להמשיך", - "OptionRuntime": "משך", + "OptionRuntime": "זמן ריצה", "OptionSaturday": "שבת", "OptionSpecialEpisode": "ספיישלים", "OptionSunday": "ראשון", "OptionThursday": "חמישי", - "OptionTrackName": "שם השיר", + "OptionTrackName": "שם הרצועה", "OptionTuesday": "שלישי", "OptionTvdbRating": "דירוג TVDB", "OptionUnairedEpisode": "פרקים שלא שודרו", "OptionUnplayed": "לא נוגן", "OptionWakeFromSleep": "הער ממצב שינה", "OptionWednesday": "רביעי", - "OptionWeekly": "שבועי", + "OptionWeekly": "כל שבוע", "OriginalAirDateValue": "תאריך אוויר מקורי: {0}", "Overview": "סקירה כללית", "PackageInstallCancelled": "ההתקנה של {0} (גירסה {1}) בוטלה.", @@ -419,7 +419,7 @@ "SeriesSettings": "הגדרות סדרה", "SeriesYearToPresent": "{0} - היום", "ServerNameIsRestarting": "שרת Jellyfin - {0} מופעל מחדש.", - "ServerNameIsShuttingDown": "שרת Jellyfin - {0} נכבה.", + "ServerNameIsShuttingDown": "שרת Jellyfin - {0} בתהליך כיבוי.", "ServerUpdateNeeded": "שרת אמבי זה צריך להיות מעודכן. כדי להוריד את הגרסה העדכנית ביותר, בקר בכתובת {0}", "Settings": "הגדרות", "SettingsSaved": "ההגדרות נשמרו.", @@ -800,5 +800,72 @@ "LabelForgotPasswordUsernameHelp": "הכנס/י את שם המשתמש שלך, אם את/ה זוכר/ת אותו.", "LabelFont": "גופן:", "LabelFolder": "תיקייה:", - "LabelFileOrUrl": "קובץ או כתובת אינטרנט:" + "LabelFileOrUrl": "קובץ או כתובת אינטרנט:", + "Season": "עונה", + "OptionEnableAccessFromAllDevices": "אפשר גישה מכל המכשירים", + "Primary": "ראשי", + "Menu": "תפריט", + "LiveTV": "שידורים חיים", + "ManageLibrary": "נהל ספרייה", + "Logo": "לוגו", + "OptionDateAddedImportTime": "השתמש בתאריך הסריקה לתוך הספרייה", + "OptionDateAddedFileTime": "השתמש בתאריך יצירת הקובץ", + "OptionBlockTrailers": "קדימונים", + "OptionBlockMusic": "מוזיקה", + "OptionBlockLiveTvChannels": "ערוצי שידורים חיים", + "OptionBlockBooks": "ספרים", + "OptionAllowRemoteSharedDevices": "אפשר שליטה מרחוק על מכשירים משותפים", + "OptionAllowRemoteControlOthers": "אפשר שליטה מרחוק על משתמשים אחרים", + "SelectAdminUsername": "נא לבחור שם משתמש עבור חשבון המנהל.", + "OptionHideUserFromLoginHelp": "שימושי עבור חשבונות פרטיים או חשבונות מנהל מוסתרים. המשתמש יצטרך להזין את שם המשתמש והסיסמה ידנית על מנת להתחבר.", + "MessagePlayAccessRestricted": "התוכן הזה לא ניתן לניגון כרגע. למידע נוסף, נא ליצור קשר עם מנהל המערכת שלך.", + "MessageContactAdminToResetPassword": "נא ליצור קשר עם מנהל המערכת שלך על מנת לאפס את הסיסמה שלך.", + "HeaderAdmin": "מנהל", + "TabDisplay": "תצוגה", + "HeaderDisplay": "תצוגה", + "Suggestions": "המלצות", + "MessageSyncPlayNoGroupsAvailable": "אין קבוצות זמינות. התחל לנגן משהו קודם.", + "OptionHomeVideos": "תמונות", + "Home": "בית", + "LabelServerName": "שם השרת:", + "TabPlugins": "תוספים", + "MessageNoPluginsInstalled": "אין לך תוספים מותקנים.", + "MessageNoAvailablePlugins": "אין תוספים זמינים.", + "TabLogs": "יומני רישום", + "LabelLogs": "יומני רישום:", + "TabNetworking": "תקשורת", + "TabDVR": "ממיר-מקליט", + "HeaderDVR": "ממיר-מקליט", + "LabelScheduledTaskLastRan": "רץ לאחרונה {0}, במשך {1}.", + "LabelTheme": "ערכת נושא:", + "LabelTextSize": "גודל טקסט:", + "LabelTextColor": "צבע טקסט:", + "LabelSyncPlayAccessNone": "מבוטל עבור משתמש זה", + "LabelSyncPlayAccessJoinGroups": "אפשר למשתמש להצטרף לקבוצות", + "LabelSyncPlayAccessCreateAndJoinGroups": "אפשר למשתמש ליצור קבוצות ולהצטרף אליהן", + "LabelSyncPlayLeaveGroup": "עזוב קבוצה", + "LabelSyncPlayNewGroupDescription": "צור קבוצה חדשה", + "LabelSyncPlayNewGroup": "קבוצה חדשה", + "MoreFromValue": "עוד מ{0}", + "Writers": "תסריטאים", + "DailyAt": "כל יום ב-{0}", + "OptionWeekends": "סופי שבוע", + "OptionWeekdays": "ימי חול", + "Unplayed": "לא נוגן", + "OptionSubstring": "מחרוזת משנה", + "OptionReleaseDate": "תאריך שחרור", + "OptionRegex": "ביטוי-רגולרי", + "OptionRandom": "אקראי", + "OptionPoster": "פוסטר", + "OptionNone": "כלום", + "OptionMax": "מקסימום", + "List": "רשימה", + "OptionList": "רשימה", + "OptionIsSD": "הבחנה רגילה (SD)", + "OptionIsHD": "הבחנה גבוהה (HD)", + "OptionExternallyDownloaded": "הורדה חיצונית", + "OptionEveryday": "כל יום", + "OptionEnableExternalContentInSuggestions": "הפעל תוכן חיצוני בהמלצות", + "OptionEnableAccessToAllLibraries": "אפשר גישה לכל הספריות", + "OptionEnableAccessToAllChannels": "אפשר גישה לכל הערוצים" } diff --git a/src/strings/ru.json b/src/strings/ru.json index 24d5cdd90f..199d0f24ae 100644 --- a/src/strings/ru.json +++ b/src/strings/ru.json @@ -1521,7 +1521,7 @@ "EnableBlurHashHelp": "Рисунки, которые всё ещё загружаются, будут отображаться с размытым заполнением", "EnableBlurHash": "Включить размытые заполнители для изображений", "ButtonSyncPlay": "SyncPlay", - "ButtonCast": "В ролях", + "ButtonCast": "Транслировать", "TabRepositories": "Репозитории", "MessageNoGenresAvailable": "Разрешить поставщикам метаданных получать жанры из интернета.", "MessageAddRepository": "Если вы хотите добавить репозиторий, нажмите кнопку рядом с заголовком и заполните необходимую информацию.",