Files
NIA Sanitized Release Publisher 7141326ea0 Sanitized public release v1.0.3
Source-Tag: v1.0.3
Manifest-SHA256: b7b09bf48f9e092ed8ad82f99c0319d6c3837d0a1549bd0cc4a374276c0f3896
2026-07-20 22:35:36 +00:00

143 lines
5.0 KiB
JavaScript

"use strict";
(function() {
var pendingRegistration = null;
var busy = false;
var $ = function(id) { return document.getElementById(id); };
function formatSize(value) {
var units = ["B", "KiB", "MiB", "GiB"];
var size = Number(value);
var index = 0;
while (size >= 1024 && index < units.length - 1) { size /= 1024; index++; }
return size.toFixed(index ? 1 : 0) + " " + units[index];
}
function setStatus(message, error) {
$("status").textContent = message;
$("status").classList.toggle("error", Boolean(error));
}
async function api(path, options) {
var response = await fetch(path, Object.assign({cache: "no-store"}, options || {}));
var value;
try { value = await response.json(); } catch (_) { value = null; }
if (!response.ok) throw new Error("Management request failed.");
return value;
}
async function copyUrl(url) {
await navigator.clipboard.writeText(url);
setStatus("Share URL copied.", false);
}
function actionButton(label, handler, className) {
var button = document.createElement("button");
button.type = "button";
button.textContent = label;
if (className) button.className = className;
button.addEventListener("click", handler);
return button;
}
function render(rows) {
var body = $("drops");
body.textContent = "";
$("empty").classList.toggle("hidden", rows.length !== 0);
rows.forEach(function(row) {
var tr = document.createElement("tr");
[row.name, row.type || "application/octet-stream", formatSize(row.size),
new Date(row.expiresAt * 1000).toLocaleString()].forEach(function(value) {
var td = document.createElement("td");
td.textContent = value;
tr.appendChild(td);
});
var actions = document.createElement("td");
actions.className = "actions";
actions.appendChild(actionButton("Copy", function() { copyUrl(row.readUrl).catch(function() {
setStatus("Unable to copy the share URL.", true);
}); }));
actions.appendChild(actionButton("Open", function() {
window.open(row.readUrl, "_blank", "noopener,noreferrer");
}));
actions.appendChild(actionButton("Delete", async function() {
if (!window.confirm("Permanently delete " + row.name + "?")) return;
try {
await api("/manage/api/v1/drops/" + row.id, {method: "DELETE"});
await load();
setStatus("Drop deleted.", false);
} catch (_) { setStatus("Delete failed.", true); }
}, "danger"));
tr.appendChild(actions);
body.appendChild(tr);
});
}
async function load() {
var value = await api("/manage/api/v1/list", {
method: "POST", headers: {"Content-Type": "application/json"}, body: "{}"
});
render(Array.isArray(value.drops) ? value.drops : []);
}
async function register(result) {
await api("/manage/api/v1/register", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({readUrl: result.readUrl, deleteCapability: result.deleteCapability})
});
pendingRegistration = null;
$("retry").classList.add("hidden");
await load();
}
$("upload-form").addEventListener("submit", async function(event) {
event.preventDefault();
if (busy) return;
var file = $("file").files[0];
if (!file) return setStatus("Select a file.", true);
busy = true;
$("upload").disabled = true;
$("progress").style.width = "0";
setStatus("Encrypting and uploading...", false);
try {
var result = await NeoDropCrypto.upload(file, {
base: location.origin,
profile: Number($("profile").value),
onProgress: function(value) { $("progress").style.width = Math.round(value * 100) + "%"; }
});
pendingRegistration = result;
setStatus("Upload complete. Registering encrypted catalog entry...", false);
try {
await register(result);
$("upload-form").reset();
setStatus("Encrypted drop uploaded and registered.", false);
} catch (_) {
$("retry").classList.remove("hidden");
setStatus("Upload succeeded, but catalog registration must be retried in this tab.", true);
}
} catch (error) {
if (error.name !== "AbortError") setStatus(error.message || "Encrypted upload failed.", true);
} finally {
busy = false;
$("upload").disabled = false;
}
});
$("retry").addEventListener("click", async function() {
if (!pendingRegistration || busy) return;
busy = true;
try {
await register(pendingRegistration);
setStatus("Catalog registration completed.", false);
} catch (_) { setStatus("Catalog registration failed; retry from this tab.", true); }
finally { busy = false; }
});
$("refresh").addEventListener("click", function() {
load().then(function() { setStatus("Managed drops refreshed.", false); })
.catch(function() { setStatus("Unable to load managed drops.", true); });
});
load().catch(function() { setStatus("Unable to load managed drops.", true); });
}());