diff --git a/dashboard-ui/components/directorybrowser/directorybrowser.js b/dashboard-ui/components/directorybrowser/directorybrowser.js index 7962cdb142..9582d8d1cb 100644 --- a/dashboard-ui/components/directorybrowser/directorybrowser.js +++ b/dashboard-ui/components/directorybrowser/directorybrowser.js @@ -221,7 +221,7 @@ var html = ''; html += '

'; - html += ''; + html += ''; html += '
' + (options.header || Globalize.translate('HeaderSelectPath')) + '
'; html += '

'; diff --git a/dashboard-ui/components/itemidentifier/itemidentifier.js b/dashboard-ui/components/itemidentifier/itemidentifier.js index d95849e677..87edcc91dd 100644 --- a/dashboard-ui/components/itemidentifier/itemidentifier.js +++ b/dashboard-ui/components/itemidentifier/itemidentifier.js @@ -2,7 +2,8 @@ var currentItem; var currentItemType; - var currentDeferred; + var currentResolve; + var currentReject; var hasChanges = false; var currentSearchResult; @@ -288,7 +289,8 @@ currentItemType = currentItem.Type; var dlg = dialogHelper.createDialog({ - size: 'medium' + size: 'medium', + removeOnClose: true }); dlg.classList.add('ui-body-b'); @@ -336,9 +338,12 @@ function onDialogClosed() { - $(this).remove(); loading.hide(); - currentDeferred.resolveWith(null, [hasChanges]); + if (hasChanges) { + currentResolve(); + } else { + currentReject(); + } } function showEditorFindNew(itemName, itemYear, itemType, resolveFunc) { @@ -417,13 +422,14 @@ return { show: function (itemId) { - var deferred = jQuery.Deferred(); + return new Promise(function (resolve, reject) { - currentDeferred = deferred; - hasChanges = false; + currentResolve = resolve; + currentReject = reject; + hasChanges = false; - showEditor(itemId); - return deferred.promise(); + showEditor(itemId); + }); }, showFindNew: function (itemName, itemYear, itemType) { diff --git a/dashboard-ui/components/metadataeditor/metadataeditor.js b/dashboard-ui/components/metadataeditor/metadataeditor.js index d1d4069118..74e84971be 100644 --- a/dashboard-ui/components/metadataeditor/metadataeditor.js +++ b/dashboard-ui/components/metadataeditor/metadataeditor.js @@ -311,7 +311,9 @@ switch (id) { case 'identify': - LibraryBrowser.identifyItem(currentItem.Id); + LibraryBrowser.identifyItem(currentItem.Id).then(function () { + reload(context, currentItem.Id); + }); break; case 'refresh': showRefreshMenu(context, button); diff --git a/dashboard-ui/encodingsettings.html b/dashboard-ui/encodingsettings.html index 6672e7aa7a..5b81d25548 100644 --- a/dashboard-ui/encodingsettings.html +++ b/dashboard-ui/encodingsettings.html @@ -43,7 +43,6 @@
${LabelffmpegPathHelp}
-
${LabelffmpegPathHelp2}
diff --git a/dashboard-ui/scripts/encodingsettings.js b/dashboard-ui/scripts/encodingsettings.js index cd716098bf..c5dc1d25a0 100644 --- a/dashboard-ui/scripts/encodingsettings.js +++ b/dashboard-ui/scripts/encodingsettings.js @@ -13,6 +13,20 @@ Dashboard.hideLoadingMsg(); } + function onSaveEncodingPathFailure(response) { + + Dashboard.hideLoadingMsg(); + + var msg = ''; + + // This is a fallback that handles both 404 and 400 (no path entered) + msg = Globalize.translate('FFmpegSavePathNotFound'); + + require(['alert'], function (alert) { + alert(msg); + }); + } + function onSubmit() { var form = this; @@ -24,13 +38,22 @@ config.DownMixAudioBoost = $('#txtDownMixAudioBoost', form).val(); config.TranscodingTempPath = $('#txtTranscodingTempPath', form).val(); - config.EncoderAppPath = $('.txtEncoderPath', form).val(); config.EncodingThreadCount = $('#selectThreadCount', form).val(); config.HardwareAccelerationType = $('#selectVideoDecoder', form).val(); config.EnableThrottling = form.querySelector('#chkEnableThrottle').checked; - ApiClient.updateNamedConfiguration("encoding", config).then(Dashboard.processServerConfigurationUpdateResult); + ApiClient.updateNamedConfiguration("encoding", config).then(function () { + + ApiClient.ajax({ + url: ApiClient.getUrl('System/MediaEncoder/Path'), + type: 'POST', + data: { + Path: form.querySelector('.txtEncoderPath').value + } + }).then(Dashboard.processServerConfigurationUpdateResult, onSaveEncodingPathFailure); + + }); }); }; @@ -80,12 +103,11 @@ require(['directorybrowser'], function (directoryBrowser) { - var picker = new directoryBrowser({ - includeFiles: true - }); + var picker = new directoryBrowser(); picker.show({ + includeFiles: true, callback: function (path) { if (path) { diff --git a/dashboard-ui/scripts/librarybrowser.js b/dashboard-ui/scripts/librarybrowser.js index b5f92fa1c2..2cd31a6603 100644 --- a/dashboard-ui/scripts/librarybrowser.js +++ b/dashboard-ui/scripts/librarybrowser.js @@ -981,9 +981,12 @@ identifyItem: function (itemId) { - require(['components/itemidentifier/itemidentifier'], function (itemidentifier) { + return new Promise(function (resolve, reject) { - itemidentifier.show(itemId); + require(['components/itemidentifier/itemidentifier'], function (itemidentifier) { + + itemidentifier.show(itemId).then(resolve, reject); + }); }); }, diff --git a/dashboard-ui/scripts/librarymenu.js b/dashboard-ui/scripts/librarymenu.js index 34dd4dc57a..6f3c5e910e 100644 --- a/dashboard-ui/scripts/librarymenu.js +++ b/dashboard-ui/scripts/librarymenu.js @@ -27,7 +27,7 @@ html += ''; html += '
'; html += '
'; - html += ''; + html += ''; html += ''; html += '
'; html += '
'; diff --git a/dashboard-ui/scripts/search.js b/dashboard-ui/scripts/search.js index ecb3f442ea..f086e990cc 100644 --- a/dashboard-ui/scripts/search.js +++ b/dashboard-ui/scripts/search.js @@ -1,4 +1,4 @@ -define(['libraryBrowser', 'events', 'scrollStyles'], function (libraryBrowser, events) { +define(['libraryBrowser', 'events', 'scrollStyles', 'scripts/librarymenu'], function (libraryBrowser, events) { var searchHintTimeout; @@ -233,7 +233,6 @@ require(['searchmenu'], function (searchmenu) { events.on(window.SearchMenu, 'closed', closeSearchResults); events.on(window.SearchMenu, 'change', function (e, value) { - onHeaderSearchChange(value); }); }); @@ -259,10 +258,7 @@ document.addEventListener('viewbeforehide', closeSearchResults); - document.addEventListener('headercreated', function () { - - bindSearchEvents(); - }); + bindSearchEvents(); // dismiss search UI if user clicks a play button on a search result events.on(MediaController, 'beforeplaybackstart', closeSearchResults); diff --git a/dashboard-ui/scripts/searchmenu.js b/dashboard-ui/scripts/searchmenu.js index bffecdf7d7..03e20b28f3 100644 --- a/dashboard-ui/scripts/searchmenu.js +++ b/dashboard-ui/scripts/searchmenu.js @@ -12,12 +12,13 @@ function searchMenu() { var self = this; + var headerSearchInput = document.querySelector('.headerSearchInput'); self.show = function () { require(['css!css/search.css'], function () { - document.querySelector('.headerSearchInput').value = ''; + headerSearchInput.value = ''; document.querySelector('.btnCloseSearch').classList.add('hide'); var elem = document.querySelector('.viewMenuSearch'); @@ -25,7 +26,7 @@ elem.classList.remove('hide'); var onFinish = function() { - document.querySelector('.headerSearchInput').focus(); + headerSearchInput.focus(); document.querySelector('.btnCloseSearch').classList.remove('hide'); }; @@ -62,24 +63,8 @@ Events.trigger(self, 'closed'); }); - document.querySelector('.headerSearchInput').addEventListener('keyup', function (e) { - - // Down key - if (e.keyCode == 40) { - - e.preventDefault(); - return false; - - } else { - - Events.trigger(self, 'change', [this.value]); - } - }); - - document.querySelector('.headerSearchInput').addEventListener('search', function (e) { - if (!this.value) { - Events.trigger(self, 'change', ['']); - } + headerSearchInput.addEventListener('input', function (e) { + Events.trigger(self, 'change', [this.value]); }); } diff --git a/dashboard-ui/scripts/site.js b/dashboard-ui/scripts/site.js index d29e2a9e58..2790cd241e 100644 --- a/dashboard-ui/scripts/site.js +++ b/dashboard-ui/scripts/site.js @@ -3019,6 +3019,14 @@ var AppInfo = {}; anonymous: true }); + defineRoute({ + path: '/wizardcomponents.html', + dependencies: ['dashboardcss', 'emby-button', 'emby-input'], + autoFocus: false, + anonymous: true, + controller: 'scripts/wizardcomponents' + }); + defineRoute({ path: '/wizardfinish.html', dependencies: ['emby-button', 'dashboardcss'], diff --git a/dashboard-ui/scripts/wizardcomponents.js b/dashboard-ui/scripts/wizardcomponents.js new file mode 100644 index 0000000000..7162cbc232 --- /dev/null +++ b/dashboard-ui/scripts/wizardcomponents.js @@ -0,0 +1,88 @@ +define([], function () { + + function goNext() { + require(['scripts/wizardcontroller'], function (wizardcontroller) { + wizardcontroller.navigateToService(); + }); + } + + function loadDownloadInfo(view) { + ApiClient.getSystemInfo().then(function (systemInfo) { + + if (systemInfo.OperatingSystem == 'Windows' && systemInfo.SystemArchitecture != 'Arm') { + view.querySelector('.suggestedLocation').innerHTML = Globalize.translate('FFmpegSuggestedDownload', 'https://ffmpeg.zeranoe.com'); + + var instructions = ''; + + if (systemInfo.SystemArchitecture == 'X86') { + instructions = 'Download 32-Bit Static'; + } + else if (systemInfo.SystemArchitecture == 'X64') { + instructions = 'Download 64-Bit Static'; + } + + view.querySelector('.downloadInstructions').innerHTML = instructions; + } else { + view.querySelector('.suggestedLocation').innerHTML = Globalize.translate('FFmpegSuggestedDownload', 'http://ffmpeg.org'); + view.querySelector('.downloadInstructions').innerHTML = ''; + } + }); + } + + function onSaveEncodingPathFailure(response) { + + var msg = ''; + + // This is a fallback that handles both 404 and 400 (no path entered) + msg = Globalize.translate('FFmpegSavePathNotFound'); + + require(['alert'], function (alert) { + alert(msg); + }); + } + + return function (view, params) { + + view.querySelector('#btnSelectEncoderPath').addEventListener("click", function () { + + require(['directorybrowser'], function (directoryBrowser) { + + var picker = new directoryBrowser(); + + picker.show({ + + includeFiles: true, + callback: function (path) { + + if (path) { + view.querySelector('.txtEncoderPath').value = path; + } + picker.close(); + } + }); + }); + }); + + view.querySelector('form').addEventListener('submit', function (e) { + + var form = this; + + ApiClient.ajax({ + url: ApiClient.getUrl('System/MediaEncoder/Path'), + type: 'POST', + data: { + Path: form.querySelector('.txtEncoderPath').value + } + }).then(goNext, onSaveEncodingPathFailure); + + e.preventDefault(); + return false; + }); + + + view.addEventListener('viewbeforeshow', function (e) { + + loadDownloadInfo(view); + }); + }; +}); \ No newline at end of file diff --git a/dashboard-ui/scripts/wizardcontroller.js b/dashboard-ui/scripts/wizardcontroller.js new file mode 100644 index 0000000000..d98bdfb2ba --- /dev/null +++ b/dashboard-ui/scripts/wizardcontroller.js @@ -0,0 +1,35 @@ +define([], function () { + + function navigateToComponents() { + var apiClient = ApiClient; + + apiClient.getJSON(apiClient.getUrl('Startup/Info')).then(function (info) { + + if (info.HasMediaEncoder) { + navigateToService(); + + } else { + Dashboard.navigate('wizardcomponents.html'); + } + }); + } + + function navigateToService() { + var apiClient = ApiClient; + + apiClient.getJSON(apiClient.getUrl('Startup/Info')).then(function (info) { + + if (info.SupportsRunningAsService) { + Dashboard.navigate('wizardservice.html'); + + } else { + Dashboard.navigate('wizardagreement.html'); + } + }); + } + + return { + navigateToComponents: navigateToComponents, + navigateToService: navigateToService + }; +}); \ No newline at end of file diff --git a/dashboard-ui/scripts/wizardlivetvguide.js b/dashboard-ui/scripts/wizardlivetvguide.js index e41bacf300..bd0a4e435d 100644 --- a/dashboard-ui/scripts/wizardlivetvguide.js +++ b/dashboard-ui/scripts/wizardlivetvguide.js @@ -56,17 +56,8 @@ } function skip() { - var apiClient = ApiClient; - - apiClient.getJSON(apiClient.getUrl('Startup/Info')).then(function (info) { - - if (info.SupportsRunningAsService) { - Dashboard.navigate('wizardservice.html'); - - } else { - Dashboard.navigate('wizardagreement.html'); - } - + require(['scripts/wizardcontroller'], function (wizardcontroller) { + wizardcontroller.navigateToComponents(); }); } diff --git a/dashboard-ui/scripts/wizardlivetvtuner.js b/dashboard-ui/scripts/wizardlivetvtuner.js index 6ab57415d5..89a862f6aa 100644 --- a/dashboard-ui/scripts/wizardlivetvtuner.js +++ b/dashboard-ui/scripts/wizardlivetvtuner.js @@ -60,16 +60,8 @@ } function skip() { - var apiClient = ApiClient; - - apiClient.getJSON(apiClient.getUrl('Startup/Info')).then(function (info) { - - if (info.SupportsRunningAsService) { - Dashboard.navigate('wizardservice.html'); - - } else { - Dashboard.navigate('wizardagreement.html'); - } + require(['scripts/wizardcontroller'], function (wizardcontroller) { + wizardcontroller.navigateToComponents(); }); } diff --git a/dashboard-ui/strings/en-US.json b/dashboard-ui/strings/en-US.json index 0f9d94b7f5..3564d575fa 100644 --- a/dashboard-ui/strings/en-US.json +++ b/dashboard-ui/strings/en-US.json @@ -2373,7 +2373,13 @@ "TitleHostingSettings": "Hosting Settings", "SettingsWarning": "Changing these values may cause instability or connectivity failures. If you experience any problems, we recommend changing them back to default.", "MapChannels": "Map Channels", - "LabelffmpegPath": "FFMpeg path:", - "LabelffmpegPathHelp": "The path to your ffmpeg application, or folder containing ffmpeg.", - "LabelffmpegPathHelp2": "Important: FFProbe must also exist within the same folder." + "LabelffmpegPath": "FFmpeg path:", + "LabelffmpegPathHelp": "The path to your downloaded FFmpeg application, or folder containing FFmpeg.", + "SetupFFmpeg": "Setup FFmpeg", + "SetupFFmpegHelp": "FFmpeg is a required component and needs to be configured.", + "EnterFFmpegLocation": "Enter FFmpeg path", + "DownloadFFmpeg": "Download FFmpeg", + "FFmpegSuggestedDownload": "Suggested download: {0}", + "UnzipFFmpegFile": "Unzip the downloaded file to a folder of your choice.", + "FFmpegSavePathNotFound": "We're unable to locaate FFmpeg using the path you've entered. FFprobe is also required and must exist in the same folder. These components are normally bundled together in the same download. Please check the path and try again." } diff --git a/dashboard-ui/wizardcomponents.html b/dashboard-ui/wizardcomponents.html new file mode 100644 index 0000000000..c05910b49b --- /dev/null +++ b/dashboard-ui/wizardcomponents.html @@ -0,0 +1,53 @@ +
+ +
+ +
+
+ +

+ ${SetupFFmpeg} +

+ +
${SetupFFmpegHelp}
+
+
+
+
1
+
${DownloadFFmpeg}
+
+
+

+
+
+
+
+
2
+
${UnzipFFmpegFile}
+
+
+
+
3
+
${EnterFFmpegLocation}
+
+ +
+
+
+ +
+ +
+
+
${LabelffmpegPathHelp}
+
+
+ +
+ + +
+
+
+
+
\ No newline at end of file