diff --git a/src/Jellyfin.Plugin.Multilang/Configuration/configPage.html b/src/Jellyfin.Plugin.Multilang/Configuration/configPage.html index 4ab242b..f7a6c25 100644 --- a/src/Jellyfin.Plugin.Multilang/Configuration/configPage.html +++ b/src/Jellyfin.Plugin.Multilang/Configuration/configPage.html @@ -515,12 +515,7 @@ } } - function prop(obj, pascal, camel, fallback) { - if (!obj) return fallback; - if (obj[pascal] !== undefined) return obj[pascal]; - if (obj[camel] !== undefined) return obj[camel]; - return fallback; - } + var prop = M.prop; function formatUnixTime(value) { value = Number(value || 0); @@ -629,13 +624,7 @@ } } - function formatBytes(bytes) { - bytes = Number(bytes || 0); - if (bytes < 1024) return bytes + " B"; - if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KiB"; - if (bytes < 1024 * 1024 * 1024) return (bytes / 1024 / 1024).toFixed(1) + " MiB"; - return (bytes / 1024 / 1024 / 1024).toFixed(1) + " GiB"; - } + var formatBytes = M.formatBytes; async function loadExportInfo() { try { @@ -652,14 +641,6 @@ } } - function showModal(id) { - document.getElementById(id).hidden = false; - } - - function hideModals() { - Array.prototype.slice.call(document.querySelectorAll(".ml-modal")).forEach(function (modal) { modal.hidden = true; }); - } - function syncAssetCheckboxes() { document.getElementById("ml-export-assets").disabled = !document.getElementById("ml-export-db").checked; if (document.getElementById("ml-export-assets").disabled) document.getElementById("ml-export-assets").checked = false; @@ -689,15 +670,8 @@ }); if (!response.ok) throw new Error("HTTP " + response.status); var blob = await response.blob(); - var url = URL.createObjectURL(blob); - var a = document.createElement("a"); - a.href = url; - a.download = "multilang-export.zip"; - document.body.appendChild(a); - a.click(); - a.remove(); - URL.revokeObjectURL(url); - hideModals(); + M.downloadBlob(blob, "multilang-export.zip"); + M.hideModals(); M.setStatus(status, "Export created."); } @@ -719,7 +693,7 @@ }); if (!response.ok) throw new Error("HTTP " + response.status); var result = await response.json(); - hideModals(); + M.hideModals(); await load(); M.setStatus(status, "Import complete. Users: " + (result.UserSettingsImported ?? result.userSettingsImported ?? 0) + ", translations: " + (result.TranslationsImported ?? result.translationsImported ?? 0) + "."); } @@ -731,7 +705,7 @@ } M.setStatus(status, "Cleaning up..."); await M.post("/Multilang/CleanupAll", { Confirm: true }); - hideModals(); + M.hideModals(); await load(); M.setStatus(status, "Multilang data cleaned up."); } @@ -893,16 +867,16 @@ document.getElementById("ml-cache-refresh").addEventListener("click", loadCacheDiagnostics); document.getElementById("ml-cache-clear").addEventListener("click", clearCacheEntries); document.getElementById("ml-refresh-activity-refresh").addEventListener("click", loadRefreshDiagnostics); - document.getElementById("ml-export-open").addEventListener("click", function () { loadExportInfo(); syncAssetCheckboxes(); showModal("ml-export-modal"); }); - document.getElementById("ml-import-open").addEventListener("click", function () { loadExportInfo(); syncAssetCheckboxes(); showModal("ml-import-modal"); }); - document.getElementById("ml-cleanup-open").addEventListener("click", function () { document.getElementById("ml-cleanup-confirm").checked = false; showModal("ml-cleanup-modal"); }); + document.getElementById("ml-export-open").addEventListener("click", function () { loadExportInfo(); syncAssetCheckboxes(); M.showModal("ml-export-modal"); }); + document.getElementById("ml-import-open").addEventListener("click", function () { loadExportInfo(); syncAssetCheckboxes(); M.showModal("ml-import-modal"); }); + document.getElementById("ml-cleanup-open").addEventListener("click", function () { document.getElementById("ml-cleanup-confirm").checked = false; M.showModal("ml-cleanup-modal"); }); document.getElementById("ml-export-db").addEventListener("change", syncAssetCheckboxes); document.getElementById("ml-import-db").addEventListener("change", syncAssetCheckboxes); document.getElementById("ml-export-run").addEventListener("click", function () { downloadExport().catch(function (err) { M.setStatus(status, String(err), true); }); }); document.getElementById("ml-import-run").addEventListener("click", function () { runImport().catch(function (err) { M.setStatus(status, String(err), true); }); }); document.getElementById("ml-cleanup-run").addEventListener("click", function () { runCleanupAll().catch(function (err) { M.setStatus(status, String(err), true); }); }); Array.prototype.slice.call(document.querySelectorAll("[data-modal-close]")).forEach(function (button) { - button.addEventListener("click", hideModals); + button.addEventListener("click", function () { M.hideModals(); }); }); document.getElementById("ml-log-enabled").addEventListener("change", function () { if (!this.checked) document.getElementById("ml-log-verbose").checked = false; diff --git a/src/Jellyfin.Plugin.Multilang/Configuration/debugPage.html b/src/Jellyfin.Plugin.Multilang/Configuration/debugPage.html index 2887f14..66a915c 100644 --- a/src/Jellyfin.Plugin.Multilang/Configuration/debugPage.html +++ b/src/Jellyfin.Plugin.Multilang/Configuration/debugPage.html @@ -37,6 +37,7 @@ var mode = document.getElementById("ml-debug-mode"); var meta = document.getElementById("ml-debug-meta"); var lastJson = ""; + var prop = M.prop; function itemId() { var match = location.pathname.match(/\/Multilang\/DebugUi\/([^/?#]+)/i); @@ -63,13 +64,6 @@ ].join("\n"); } - function prop(obj, pascal, camel, fallback) { - if (!obj) return fallback; - if (obj[pascal] !== undefined) return obj[pascal]; - if (obj[camel] !== undefined) return obj[camel]; - return fallback; - } - function make(tag, className, text) { var el = document.createElement(tag); if (className) el.className = className; diff --git a/src/Jellyfin.Plugin.Multilang/Configuration/shared.js b/src/Jellyfin.Plugin.Multilang/Configuration/shared.js index fd079e0..84b5f9c 100644 --- a/src/Jellyfin.Plugin.Multilang/Configuration/shared.js +++ b/src/Jellyfin.Plugin.Multilang/Configuration/shared.js @@ -61,6 +61,40 @@ el.style.color = error ? "#ff9b9b" : ""; } + function prop(obj, pascal, camel, fallback) { + if (!obj) return fallback; + if (obj[pascal] !== undefined) return obj[pascal]; + if (obj[camel] !== undefined) return obj[camel]; + return fallback; + } + + function formatBytes(bytes) { + bytes = Number(bytes || 0); + if (bytes < 1024) return bytes + " B"; + if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KiB"; + if (bytes < 1024 * 1024 * 1024) return (bytes / 1024 / 1024).toFixed(1) + " MiB"; + return (bytes / 1024 / 1024 / 1024).toFixed(1) + " GiB"; + } + + function showModal(id) { + document.getElementById(id).hidden = false; + } + + function hideModals(selector) { + [...document.querySelectorAll(selector || ".ml-modal")].forEach((modal) => { modal.hidden = true; }); + } + + function downloadBlob(blob, name) { + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = name; + document.body.appendChild(a); + a.click(); + a.remove(); + URL.revokeObjectURL(url); + } + function chip(label) { const el = document.createElement("span"); el.className = "ml-chip"; @@ -105,6 +139,11 @@ authHeaders, splitList, setStatus, + prop, + formatBytes, + showModal, + hideModals, + downloadBlob, chip, bucketValues, renderBucket, diff --git a/src/Jellyfin.Plugin.Multilang/Configuration/userRulesPage.html b/src/Jellyfin.Plugin.Multilang/Configuration/userRulesPage.html index d3a20c2..aba9def 100644 --- a/src/Jellyfin.Plugin.Multilang/Configuration/userRulesPage.html +++ b/src/Jellyfin.Plugin.Multilang/Configuration/userRulesPage.html @@ -1164,14 +1164,7 @@ }); if (!response.ok) throw new Error("HTTP " + response.status); var blob = await response.blob(); - var url = URL.createObjectURL(blob); - var a = document.createElement("a"); - a.href = url; - a.download = "multilang-user-settings.zip"; - document.body.appendChild(a); - a.click(); - a.remove(); - URL.revokeObjectURL(url); + M.downloadBlob(blob, "multilang-user-settings.zip"); M.setStatus(status, "Export created."); } diff --git a/src/Jellyfin.Plugin.Multilang/Services/Backup/MultilangBackupService.cs b/src/Jellyfin.Plugin.Multilang/Services/Backup/MultilangBackupService.cs index 160a6b1..8a6ed50 100644 --- a/src/Jellyfin.Plugin.Multilang/Services/Backup/MultilangBackupService.cs +++ b/src/Jellyfin.Plugin.Multilang/Services/Backup/MultilangBackupService.cs @@ -6,7 +6,6 @@ using Jellyfin.Plugin.Multilang.Configuration; using Jellyfin.Plugin.Multilang.Data; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; -using Microsoft.Extensions.Logging; namespace Jellyfin.Plugin.Multilang.Services.Backup; @@ -21,18 +20,15 @@ public sealed class MultilangBackupService private readonly TranslationStore _store; private readonly ILibraryManager _libraryManager; private readonly IUserManager _userManager; - private readonly ILogger _logger; public MultilangBackupService( TranslationStore store, ILibraryManager libraryManager, - IUserManager userManager, - ILogger logger) + IUserManager userManager) { _store = store; _libraryManager = libraryManager; _userManager = userManager; - _logger = logger; } public BackupStorageInfo GetStorageInfo()