import { appHost } from '../apphost'; import dialogHelper from '../dialogHelper/dialogHelper'; import layoutManager from '../layoutManager'; import globalize from '../../scripts/globalize'; import * as userSettings from '../../scripts/settings/userSettings'; import loading from '../loading/loading'; import focusManager from '../focusManager'; import dom from '../../scripts/dom'; import '../../elements/emby-select/emby-select'; import '../listview/listview.css'; import '../../elements/emby-button/paper-icon-button-light'; import '../formdialog.css'; import 'material-design-icons-iconfont'; import './subtitleeditor.css'; import '../../elements/emby-button/emby-button'; import '../../assets/css/flexstyles.scss'; import ServerConnections from '../ServerConnections'; import toast from '../toast/toast'; import confirm from '../confirm/confirm'; import template from './subtitleeditor.template.html'; let currentItem; let hasChanges; function downloadRemoteSubtitles(context, id) { const url = 'Items/' + currentItem.Id + '/RemoteSearch/Subtitles/' + id; const apiClient = ServerConnections.getApiClient(currentItem.ServerId); apiClient.ajax({ type: 'POST', url: apiClient.getUrl(url) }).then(function () { hasChanges = true; toast(globalize.translate('MessageDownloadQueued')); focusManager.autoFocus(context); }); } function deleteLocalSubtitle(context, index) { const msg = globalize.translate('MessageAreYouSureDeleteSubtitles'); confirm({ title: globalize.translate('ConfirmDeletion'), text: msg, confirmText: globalize.translate('Delete'), primary: 'delete' }).then(function () { loading.show(); const itemId = currentItem.Id; const url = 'Videos/' + itemId + '/Subtitles/' + index; const apiClient = ServerConnections.getApiClient(currentItem.ServerId); apiClient.ajax({ type: 'DELETE', url: apiClient.getUrl(url) }).then(function () { hasChanges = true; reload(context, apiClient, itemId); }); }); } function fillSubtitleList(context, item) { const streams = item.MediaStreams || []; const subs = streams.filter(function (s) { return s.Type === 'Subtitle'; }); let html = ''; if (subs.length) { html += '

' + globalize.translate('MySubtitles') + '

'; html += '
'; html += subs.map(function (s) { let itemHtml = ''; const tagName = layoutManager.tv ? 'button' : 'div'; let className = layoutManager.tv && s.Path ? 'listItem listItem-border btnDelete' : 'listItem listItem-border'; if (layoutManager.tv) { className += ' listItem-focusscale listItem-button'; } className += ' listItem-noborder'; itemHtml += '<' + tagName + ' class="' + className + '" data-index="' + s.Index + '">'; itemHtml += ''; itemHtml += '
'; itemHtml += '
'; itemHtml += s.DisplayTitle || ''; itemHtml += '
'; if (s.Path) { itemHtml += '
' + (s.Path) + '
'; } itemHtml += ''; itemHtml += '
'; if (!layoutManager.tv) { if (s.Path) { itemHtml += ''; } } itemHtml += ''; return itemHtml; }).join(''); html += '
'; } const elem = context.querySelector('.subtitleList'); if (subs.length) { elem.classList.remove('hide'); } else { elem.classList.add('hide'); } elem.innerHTML = html; } function fillLanguages(context, apiClient, languages) { const selectLanguage = context.querySelector('#selectLanguage'); selectLanguage.innerHTML = languages.map(function (l) { return ''; }); const lastLanguage = userSettings.get('subtitleeditor-language'); if (lastLanguage) { selectLanguage.value = lastLanguage; } else { apiClient.getCurrentUser().then(function (user) { const lang = user.Configuration.SubtitleLanguagePreference; if (lang) { selectLanguage.value = lang; } }); } } function renderSearchResults(context, results) { let lastProvider = ''; let html = ''; if (!results.length) { context.querySelector('.noSearchResults').classList.remove('hide'); context.querySelector('.subtitleResults').innerHTML = ''; loading.hide(); return; } context.querySelector('.noSearchResults').classList.add('hide'); for (let i = 0, length = results.length; i < length; i++) { const result = results[i]; const provider = result.ProviderName; if (provider !== lastProvider) { if (i > 0) { html += ''; } html += '

' + provider + '

'; html += '
'; lastProvider = provider; } const tagName = layoutManager.tv ? 'button' : 'div'; let className = layoutManager.tv ? 'listItem listItem-border btnOptions' : 'listItem listItem-border'; if (layoutManager.tv) { className += ' listItem-focusscale listItem-button'; } html += '<' + tagName + ' class="' + className + '" data-subid="' + result.Id + '">'; html += ''; const bodyClass = result.Comment || result.IsHashMatch ? 'three-line' : 'two-line'; html += '
'; html += '
' + (result.Name) + '
'; html += '
'; if (result.Format) { html += '' + globalize.translate('FormatValue', result.Format) + ''; } if (result.DownloadCount != null) { html += '' + globalize.translate('DownloadsValue', result.DownloadCount) + ''; } html += '
'; if (result.Comment) { html += '
' + (result.Comment) + '
'; } if (result.IsHashMatch) { html += '
' + globalize.translate('PerfectMatch') + '
'; } html += '
'; if (!layoutManager.tv) { html += ''; } html += ''; } if (results.length) { html += '
'; } const elem = context.querySelector('.subtitleResults'); elem.innerHTML = html; loading.hide(); } function searchForSubtitles(context, language) { userSettings.set('subtitleeditor-language', language); loading.show(); const apiClient = ServerConnections.getApiClient(currentItem.ServerId); const url = apiClient.getUrl('Items/' + currentItem.Id + '/RemoteSearch/Subtitles/' + language); apiClient.getJSON(url).then(function (results) { renderSearchResults(context, results); }); } function reload(context, apiClient, itemId) { context.querySelector('.noSearchResults').classList.add('hide'); function onGetItem(item) { currentItem = item; fillSubtitleList(context, item); let file = item.Path || ''; const index = Math.max(file.lastIndexOf('/'), file.lastIndexOf('\\')); if (index > -1) { file = file.substring(index + 1); } if (file) { context.querySelector('.pathValue').innerHTML = file; context.querySelector('.originalFile').classList.remove('hide'); } else { context.querySelector('.pathValue').innerHTML = ''; context.querySelector('.originalFile').classList.add('hide'); } loading.hide(); } if (typeof itemId === 'string') { apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(onGetItem); } else { onGetItem(itemId); } } function onSearchSubmit(e) { const form = this; const lang = form.querySelector('#selectLanguage', form).value; searchForSubtitles(dom.parentWithClass(form, 'formDialogContent'), lang); e.preventDefault(); return false; } function onSubtitleListClick(e) { const btnDelete = dom.parentWithClass(e.target, 'btnDelete'); if (btnDelete) { const index = btnDelete.getAttribute('data-index'); const context = dom.parentWithClass(btnDelete, 'subtitleEditorDialog'); deleteLocalSubtitle(context, index); } } function onSubtitleResultsClick(e) { let subtitleId; let context; const btnOptions = dom.parentWithClass(e.target, 'btnOptions'); if (btnOptions) { subtitleId = btnOptions.getAttribute('data-subid'); context = dom.parentWithClass(btnOptions, 'subtitleEditorDialog'); showDownloadOptions(btnOptions, context, subtitleId); } const btnDownload = dom.parentWithClass(e.target, 'btnDownload'); if (btnDownload) { subtitleId = btnDownload.getAttribute('data-subid'); context = dom.parentWithClass(btnDownload, 'subtitleEditorDialog'); downloadRemoteSubtitles(context, subtitleId); } } function showDownloadOptions(button, context, subtitleId) { const items = []; items.push({ name: globalize.translate('Download'), id: 'download' }); import('../actionSheet/actionSheet').then((actionsheet) => { actionsheet.show({ items: items, positionTo: button }).then(function (id) { switch (id) { case 'download': downloadRemoteSubtitles(context, subtitleId); break; default: break; } }); }); } function centerFocus(elem, horiz, on) { import('../../scripts/scrollHelper').then(({default: scrollHelper}) => { const fn = on ? 'on' : 'off'; scrollHelper.centerFocus[fn](elem, horiz); }); } function onOpenUploadMenu(e) { const dialog = dom.parentWithClass(e.target, 'subtitleEditorDialog'); const selectLanguage = dialog.querySelector('#selectLanguage'); const apiClient = ServerConnections.getApiClient(currentItem.ServerId); import('../subtitleuploader/subtitleuploader').then(({default: subtitleUploader}) => { subtitleUploader.show({ languages: { list: selectLanguage.innerHTML, value: selectLanguage.value }, itemId: currentItem.Id, serverId: currentItem.ServerId }).then(function (hasChanged) { if (hasChanged) { hasChanges = true; reload(dialog, apiClient, currentItem.Id); } }); }); } function showEditorInternal(itemId, serverId) { hasChanges = false; const apiClient = ServerConnections.getApiClient(serverId); return apiClient.getItem(apiClient.getCurrentUserId(), itemId).then(function (item) { const dialogOptions = { removeOnClose: true, scrollY: false }; if (layoutManager.tv) { dialogOptions.size = 'fullscreen'; } else { dialogOptions.size = 'small'; } const dlg = dialogHelper.createDialog(dialogOptions); dlg.classList.add('formDialog'); dlg.classList.add('subtitleEditorDialog'); dlg.innerHTML = globalize.translateHtml(template, 'core'); dlg.querySelector('.originalSubtitleFileLabel').innerHTML = globalize.translate('File'); dlg.querySelector('.subtitleSearchForm').addEventListener('submit', onSearchSubmit); dlg.querySelector('.btnOpenUploadMenu').addEventListener('click', onOpenUploadMenu); const btnSubmit = dlg.querySelector('.btnSubmit'); if (layoutManager.tv) { centerFocus(dlg.querySelector('.formDialogContent'), false, true); dlg.querySelector('.btnSearchSubtitles').classList.add('hide'); } else { btnSubmit.classList.add('hide'); } // Don't allow redirection to other websites from the TV layout if (layoutManager.tv || !appHost.supports('externallinks')) { dlg.querySelector('.btnHelp').remove(); } const editorContent = dlg.querySelector('.formDialogContent'); dlg.querySelector('.subtitleList').addEventListener('click', onSubtitleListClick); dlg.querySelector('.subtitleResults').addEventListener('click', onSubtitleResultsClick); apiClient.getCultures().then(function (languages) { fillLanguages(editorContent, apiClient, languages); }); dlg.querySelector('.btnCancel').addEventListener('click', function () { dialogHelper.close(dlg); }); return new Promise(function (resolve, reject) { dlg.addEventListener('close', function () { if (layoutManager.tv) { centerFocus(dlg.querySelector('.formDialogContent'), false, false); } if (hasChanges) { resolve(); } else { reject(); } }); dialogHelper.open(dlg); reload(editorContent, apiClient, item); }); }); } function showEditor(itemId, serverId) { loading.show(); return showEditorInternal(itemId, serverId); } export default { show: showEditor };