Sanitized public release v1.0.3
Source-Tag: v1.0.3 Manifest-SHA256: b7b09bf48f9e092ed8ad82f99c0319d6c3837d0a1549bd0cc4a374276c0f3896
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
"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); });
|
||||
}());
|
||||
Reference in New Issue
Block a user