define(["apphost", "globalize", "connectionManager", "layoutManager", "focusManager", "scrollHelper", "appSettings", "registrationServices", "dialogHelper", "paper-icon-button-light", "formDialogStyle"], function(appHost, globalize, connectionManager, layoutManager, focusManager, scrollHelper, appSettings, registrationServices, dialogHelper) { "use strict"; function submitJob(dlg, apiClient, userId, syncOptions, form) { if (!userId) throw new Error("userId cannot be null"); if (!syncOptions) throw new Error("syncOptions cannot be null"); if (!form) throw new Error("form cannot be null"); var selectSyncTarget = form.querySelector("#selectSyncTarget"), target = selectSyncTarget ? selectSyncTarget.value : null; if (!target) return require(["toast"], function(toast) { toast(globalize.translate("sharedcomponents#PleaseSelectDeviceToSyncTo")) }), !1; var options = { userId: userId, TargetId: target, ParentId: syncOptions.ParentId, Category: syncOptions.Category }; return setJobValues(options, form), syncOptions.items && syncOptions.items.length && (options.ItemIds = (syncOptions.items || []).map(function(i) { return i.Id || i }).join(",")), apiClient.ajax({ type: "POST", url: apiClient.getUrl("Sync/Jobs"), data: JSON.stringify(options), contentType: "application/json", dataType: "json" }).then(function() { dialogHelper.close(dlg), require(["toast"], function(toast) { showSubmissionToast(target, apiClient), "download" === syncOptions.mode && syncNow() }) }), !0 } function showSubmissionToast(targetId, apiClient) { require(["toast"], function(toast) { toast(targetId === apiClient.deviceId() ? globalize.translate("sharedcomponents#DownloadingDots") : globalize.translate("sharedcomponents#SyncingDots")) }) } function syncNow() { require(["localsync"], function(localSync) { localSync.sync() }) } function submitQuickSyncJob(apiClient, userId, targetId, syncOptions) { if (!userId) throw new Error("userId cannot be null"); if (!syncOptions) throw new Error("syncOptions cannot be null"); if (!targetId) throw new Error("targetId cannot be null"); var options = { userId: userId, TargetId: targetId, ParentId: syncOptions.ParentId, Category: syncOptions.Category, Quality: syncOptions.Quality, Bitrate: syncOptions.Bitrate }; return syncOptions.items && syncOptions.items.length && (options.ItemIds = (syncOptions.items || []).map(function(i) { return i.Id || i }).join(",")), apiClient.ajax({ type: "POST", url: apiClient.getUrl("Sync/Jobs"), data: JSON.stringify(options), contentType: "application/json", dataType: "json" }).then(function() { require(["toast"], function(toast) { showSubmissionToast(targetId, apiClient), "download" === syncOptions.mode && syncNow() }) }) } function setJobValues(job, form) { var txtBitrate = form.querySelector("#txtBitrate"), bitrate = txtBitrate ? txtBitrate.value : null; bitrate && (bitrate = 1e6 * parseFloat(bitrate)), job.Bitrate = bitrate; var selectQuality = form.querySelector("#selectQuality"); selectQuality && (job.Quality = selectQuality.value, appSettings.set("sync-lastquality", job.Quality || "")); var selectProfile = form.querySelector("#selectProfile"); selectProfile && (job.Profile = selectProfile.value); var txtItemLimit = form.querySelector("#txtItemLimit"); txtItemLimit && (job.ItemLimit = txtItemLimit.value || null); var chkSyncNewContent = form.querySelector("#chkSyncNewContent"); chkSyncNewContent && (job.SyncNewContent = chkSyncNewContent.checked); var chkUnwatchedOnly = form.querySelector("#chkUnwatchedOnly"); chkUnwatchedOnly && (job.UnwatchedOnly = chkUnwatchedOnly.checked) } function renderForm(options) { return new Promise(function(resolve, reject) { require(["emby-checkbox", "emby-input", "emby-select"], function() { renderFormInternal(options, connectionManager.deviceId(), resolve) }) }) } function renderFormInternal(options, defaultTargetId, resolve) { var elem = options.elem, dialogOptions = options.dialogOptions, targets = dialogOptions.Targets, html = "", mode = options.mode, targetContainerClass = "download" === mode ? " hide" : "", syncTargetLabel = "convert" === mode ? globalize.translate("sharedcomponents#LabelConvertTo") : globalize.translate("sharedcomponents#LabelSyncTo"); options.readOnlySyncTarget ? (html += '
', html += '', html += "
") : (html += '
', html += '", targets.length || (html += '
' + globalize.translate("sharedcomponents#LabelSyncNoTargetsHelp") + "
"), appHost.supports("externallinks") && (html += '
' + globalize.translate("sharedcomponents#LearnMore") + "
"), html += "
"), html += '
', html += '", html += '
', html += "
", html += '
', html += '", html += '
', html += "
", html += '
', html += '', html += "
", -1 !== dialogOptions.Options.indexOf("UnwatchedOnly") && (html += '
', html += "", html += "convert" === mode ? '
' + globalize.translate("sharedcomponents#ConvertUnwatchedVideosOnlyHelp") + "
" : '
' + globalize.translate("sharedcomponents#SyncUnwatchedVideosOnlyHelp") + "
", html += "
"), -1 !== dialogOptions.Options.indexOf("SyncNewContent") && (html += '
', html += "", html += "convert" === mode ? '
' + globalize.translate("sharedcomponents#AutomaticallyConvertNewContentHelp") + "
" : '
' + globalize.translate("sharedcomponents#AutomaticallySyncNewContentHelp") + "
", html += "
"), -1 !== dialogOptions.Options.indexOf("ItemLimit") && (html += '
', html += '', html += "convert" === mode ? '
' + globalize.translate("sharedcomponents#ConvertItemLimitHelp") + "
" : '
' + globalize.translate("sharedcomponents#DownloadItemLimitHelp") + "
", html += "
"), elem.innerHTML = html; var selectSyncTarget = elem.querySelector("#selectSyncTarget"); selectSyncTarget && (selectSyncTarget.addEventListener("change", function() { loadQualityOptions(elem, this.value, options.dialogOptionsFn).then(resolve) }), selectSyncTarget.dispatchEvent(new CustomEvent("change", { bubbles: !0 }))); var selectProfile = elem.querySelector("#selectProfile"); selectProfile && (selectProfile.addEventListener("change", function() { onProfileChange(elem, this.value) }), dialogOptions.ProfileOptions.length && selectProfile.dispatchEvent(new CustomEvent("change", { bubbles: !0 }))); var selectQuality = elem.querySelector("#selectQuality"); selectQuality && (selectQuality.addEventListener("change", function() { onQualityChange(elem, this.value) }), selectQuality.dispatchEvent(new CustomEvent("change", { bubbles: !0 }))), setTimeout(function() { focusManager.autoFocus(elem) }, 100) } function showWifiMessage() { require(["dialog", "appRouter"], function(dialog, appRouter) { var options = { title: globalize.translate("sharedcomponents#HeaderWaitingForWifi"), text: globalize.translate("sharedcomponents#WifiRequiredToDownload") }, items = []; items.push({ name: options.confirmText || globalize.translate("sharedcomponents#ButtonOk"), id: "ok", type: "submit" }), items.push({ name: options.cancelText || globalize.translate("sharedcomponents#HeaderDownloadSettings"), id: "downloadsettings", type: "cancel" }), options.buttons = items, dialog(options).then(function(result) { return "ok" === result ? Promise.resolve() : "downloadsettings" === result ? (appRouter.show(appRouter.getRouteUrl("downloadsettings")), Promise.resolve()) : Promise.reject() }) }) } function validateNetwork() { switch (navigator.connection ? navigator.connection.type : null) { case "cellular": case "bluetooth": return showWifiMessage(), !1; default: return !0 } } function showSyncMenu(options) { return "download" === options.mode && appSettings.syncOnlyOnWifi() && !validateNetwork() ? Promise.reject() : registrationServices.validateFeature("sync").then(function() { return showSyncMenuInternal(options) }) } function enableAutoSync(options) { if ("download" !== options.mode) return !1; var firstItem = (options.items || [])[0] || {}; return "Audio" === firstItem.Type || ("MusicAlbum" === firstItem.Type || ("MusicArtist" === firstItem.Type || ("MusicGenre" === firstItem.Type || "Playlist" === firstItem.Type && "Audio" === firstItem.MediaType))) } function showSyncMenuInternal(options) { var apiClient = connectionManager.getApiClient(options.serverId), userId = apiClient.getCurrentUserId(); if (enableAutoSync(options)) return submitQuickSyncJob(apiClient, userId, apiClient.deviceId(), { items: options.items, Quality: "custom", Bitrate: appSettings.maxStaticMusicBitrate() }); var dialogOptionsFn = getTargetDialogOptionsFn(apiClient, { UserId: userId, ItemIds: (options.items || []).map(function(i) { return i.Id || i }).join(","), ParentId: options.ParentId, Category: options.Category, IncludeProviders: "convert" === options.mode ? "ConvertSyncProvider" : null, ExcludeProviders: "convert" === options.mode ? null : "ConvertSyncProvider" }); return dialogOptionsFn().then(function(dialogOptions) { currentDialogOptions = dialogOptions; var dlgElementOptions = { removeOnClose: !0, scrollY: !1, autoFocus: !1 }; layoutManager.tv ? dlgElementOptions.size = "fullscreen" : dlgElementOptions.size = "small"; var dlg = dialogHelper.createDialog(dlgElementOptions); dlg.classList.add("formDialog"); var html = ""; html += '
', html += '', html += '

'; var syncButtonLabel = "download" === options.mode ? globalize.translate("sharedcomponents#Download") : "convert" === options.mode ? globalize.translate("sharedcomponents#Convert") : globalize.translate("sharedcomponents#Sync"); html += syncButtonLabel, html += "

", appHost.supports("externallinks") && (html += 'info' + globalize.translate("sharedcomponents#Help") + ""), html += "
", html += '
', html += '
', html += '
', html += '
', html += '
', html += '", html += "
", html += "
", html += "
", html += "
", dlg.innerHTML = html; var submitted = !1; dlg.querySelector("form").addEventListener("submit", function(e) { return submitted = submitJob(dlg, apiClient, userId, options, this), e.preventDefault(), !1 }), dlg.querySelector(".btnCancel").addEventListener("click", function() { dialogHelper.close(dlg) }), layoutManager.tv && scrollHelper.centerFocus.on(dlg.querySelector(".formDialogContent"), !1); var promise = dialogHelper.open(dlg); return renderForm({ elem: dlg.querySelector(".formFields"), dialogOptions: dialogOptions, dialogOptionsFn: dialogOptionsFn, mode: options.mode }), promise.then(function() { return layoutManager.tv && scrollHelper.centerFocus.off(dlg.querySelector(".formDialogContent"), !1), submitted ? Promise.resolve() : Promise.reject() }) }) } function getTargetDialogOptionsFn(apiClient, query) { return function(targetId) { return query.TargetId = targetId, apiClient.getJSON(apiClient.getUrl("Sync/Options", query)) } } function setQualityFieldVisible(form, visible) { var fldQuality = form.querySelector(".fldQuality"), selectQuality = form.querySelector("#selectQuality"); visible ? (fldQuality && fldQuality.classList.remove("hide"), selectQuality && selectQuality.removeAttribute("required")) : (fldQuality && fldQuality.classList.add("hide"), selectQuality && selectQuality.removeAttribute("required")) } function onProfileChange(form, profileId) { var options = currentDialogOptions || {}, profileOptions = options.ProfileOptions || []; if (profileOptions.length) { var option = profileOptions.filter(function(o) { return o.Id === profileId })[0], qualityOptions = options.QualityOptions || []; option ? (form.querySelector(".profileDescription").innerHTML = option.Description || "", setQualityFieldVisible(form, qualityOptions.length > 0 && option.EnableQualityOptions && -1 !== options.Options.indexOf("Quality"))) : (form.querySelector(".profileDescription").innerHTML = "", setQualityFieldVisible(form, qualityOptions.length > 0 && -1 !== options.Options.indexOf("Quality"))) } } function onQualityChange(form, qualityId) { var options = currentDialogOptions || {}, option = (options.QualityOptions || []).filter(function(o) { return o.Id === qualityId })[0], qualityDescription = form.querySelector(".qualityDescription"); qualityDescription.innerHTML = option ? option.Description || "" : ""; var fldBitrate = form.querySelector(".fldBitrate"), txtBitrate = form.querySelector("#txtBitrate"); "custom" === qualityId ? (fldBitrate && fldBitrate.classList.remove("hide"), txtBitrate && txtBitrate.setAttribute("required", "required")) : (fldBitrate && fldBitrate.classList.add("hide"), txtBitrate && txtBitrate.removeAttribute("required")) } function renderTargetDialogOptions(form, options) { currentDialogOptions = options; var fldProfile = form.querySelector(".fldProfile"), selectProfile = form.querySelector("#selectProfile"); options.ProfileOptions.length && -1 !== options.Options.indexOf("Profile") ? (fldProfile && fldProfile.classList.remove("hide"), selectProfile && selectProfile.setAttribute("required", "required")) : (fldProfile && fldProfile.classList.add("hide"), selectProfile && selectProfile.removeAttribute("required")), setQualityFieldVisible(form, options.QualityOptions.length > 0), selectProfile && (selectProfile.innerHTML = options.ProfileOptions.map(function(o) { var selectedAttribute = o.IsDefault ? ' selected="selected"' : ""; return '" }).join(""), selectProfile.dispatchEvent(new CustomEvent("change", { bubbles: !0 }))); var selectQuality = form.querySelector("#selectQuality"); if (selectQuality) { selectQuality.innerHTML = options.QualityOptions.map(function(o) { var selectedAttribute = o.IsDefault ? ' selected="selected"' : ""; return '" }).join(""); var lastQuality = appSettings.get("sync-lastquality"); lastQuality && options.QualityOptions.filter(function(i) { return i.Id === lastQuality }).length && (selectQuality.value = lastQuality), selectQuality.dispatchEvent(new CustomEvent("change", { bubbles: !0 })) } } function loadQualityOptions(form, targetId, dialogOptionsFn) { return dialogOptionsFn(targetId).then(function(options) { return renderTargetDialogOptions(form, options) }) } var currentDialogOptions; return { showMenu: showSyncMenu, renderForm: renderForm, setJobValues: setJobValues } });