diff --git a/dashboard-ui/components/directorybrowser/directorybrowser.js b/dashboard-ui/components/directorybrowser/directorybrowser.js
index 7962cdb14..9582d8d1c 100644
--- a/dashboard-ui/components/directorybrowser/directorybrowser.js
+++ b/dashboard-ui/components/directorybrowser/directorybrowser.js
@@ -221,7 +221,7 @@
var html = '';
html += '
';
diff --git a/dashboard-ui/components/itemidentifier/itemidentifier.js b/dashboard-ui/components/itemidentifier/itemidentifier.js
index d95849e67..87edcc91d 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 d1d406911..74e84971b 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 6672e7aa7..5b81d2554 100644
--- a/dashboard-ui/encodingsettings.html
+++ b/dashboard-ui/encodingsettings.html
@@ -43,7 +43,6 @@
diff --git a/dashboard-ui/scripts/encodingsettings.js b/dashboard-ui/scripts/encodingsettings.js
index cd716098b..c5dc1d25a 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 b5f92fa1c..2cd31a660 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 34dd4dc57..6f3c5e910 100644
--- a/dashboard-ui/scripts/librarymenu.js
+++ b/dashboard-ui/scripts/librarymenu.js
@@ -27,7 +27,7 @@
html += '';
html += '';
diff --git a/dashboard-ui/scripts/search.js b/dashboard-ui/scripts/search.js
index ecb3f442e..f086e990c 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 bffecdf7d..03e20b28f 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 d29e2a9e5..2790cd241 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 000000000..7162cbc23
--- /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 000000000..d98bdfb2b
--- /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 e41bacf30..bd0a4e435 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 6ab57415d..89a862f6a 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 0f9d94b7f..3564d575f 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 000000000..c05910b49
--- /dev/null
+++ b/dashboard-ui/wizardcomponents.html
@@ -0,0 +1,53 @@
+
\ No newline at end of file