omegaupload/web/src/main.ts

325 lines
10 KiB
TypeScript
Raw Normal View History

2021-10-31 14:01:27 -07:00
// OmegaUpload Web Frontend
// Copyright (C) 2021 Edward Shen
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
2021-10-24 02:25:42 -07:00
// Exported to main.rs
function loadFromDb(mimeType: string, name?: string, language?: string) {
console.log("[js] Got name:", name);
console.log("[js] Got language:", language);
console.log("[js] Got mime type:", mimeType);
2021-10-24 02:25:42 -07:00
const dbReq = window.indexedDB.open("omegaupload", 1);
dbReq.onsuccess = (evt) => {
const db = (evt.target as IDBRequest).result;
const obj_store = db
2021-10-24 11:40:19 -07:00
.transaction("decrypted data")
.objectStore("decrypted data");
const fetchReq = obj_store.get(window.location.pathname);
2021-10-24 11:40:19 -07:00
fetchReq.onsuccess = (evt) => {
2021-10-24 02:25:42 -07:00
const data = (evt.target as IDBRequest).result;
switch (data.type) {
case "string":
createStringPasteUi(data, mimeType, name, language);
2021-10-24 02:25:42 -07:00
break;
case "blob":
createBlobPasteUi(data, name);
2021-10-24 02:25:42 -07:00
break;
case "image":
createImagePasteUi(data, name);
2021-10-24 02:25:42 -07:00
break;
2021-10-24 11:40:19 -07:00
case "audio":
createAudioPasteUi(data, name);
2021-10-24 11:40:19 -07:00
break;
case "video":
createVideoPasteUi(data, name);
2021-10-24 11:40:19 -07:00
break;
2021-10-26 18:19:14 -07:00
case "archive":
createArchivePasteUi(data, name);
2021-10-26 18:19:14 -07:00
break;
2021-10-24 02:25:42 -07:00
default:
2021-10-25 02:42:20 -07:00
renderMessage("Something went wrong. Try clearing local data.");
2021-10-24 02:25:42 -07:00
break;
}
2021-10-24 11:40:19 -07:00
// IDB was only used as a temporary medium;
window.onbeforeunload = (e) => {
// See https://link.eddie.sh/NrIIq on why .commit is necessary.
const transaction = db.transaction("decrypted data", "readwrite");
transaction
.objectStore("decrypted data")
.delete(window.location.pathname);
transaction.commit();
transaction.oncomplete = () => {
console.log("Item deleted from cache");
}
};
2021-10-24 02:25:42 -07:00
};
2021-10-24 11:40:19 -07:00
fetchReq.onerror = (evt) => {
2021-10-24 02:25:42 -07:00
console.log("err");
console.log(evt);
};
};
}
function createStringPasteUi(data, mimeType: string, name?: string, lang?: string) {
const bodyEle = document.getElementsByTagName("body")[0];
2021-10-24 02:25:42 -07:00
bodyEle.textContent = '';
const mainEle = document.createElement("main");
const preEle = document.createElement("pre");
2021-10-24 02:25:42 -07:00
preEle.classList.add("paste");
const headerEle = document.createElement("p");
2021-10-24 02:25:42 -07:00
headerEle.classList.add("unselectable");
2021-10-27 01:49:06 -07:00
headerEle.classList.add("centered");
2021-10-24 02:25:42 -07:00
headerEle.textContent = data.expiration;
preEle.appendChild(headerEle);
const downloadEle = document.createElement("a");
downloadEle.href = getObjectUrl([data.data], mimeType);
downloadEle.download = name;
2022-01-11 22:19:15 -08:00
downloadEle.classList.add("hljs-meta");
downloadEle.classList.add("centered");
downloadEle.textContent = "Download file.";
preEle.appendChild(downloadEle);
2021-10-24 02:25:42 -07:00
preEle.appendChild(document.createElement("hr"));
const codeEle = document.createElement("code");
2021-10-24 02:25:42 -07:00
codeEle.textContent = data.data;
preEle.appendChild(codeEle);
mainEle.appendChild(preEle);
bodyEle.appendChild(mainEle);
let languages = undefined;
if (!hljs.getLanguage(lang)) {
console.warn(`[js] User provided language (${lang}) is not known.`);
} else {
languages = [lang];
}
// If a language wasn't provided, see if we can use the file extension to give
// us a better hint for hljs
if (!languages) {
if (name) {
console.log("[js] Trying to infer from file name...");
const periodIndex = name.indexOf(".");
if (periodIndex === -1) {
console.warn("[js] Did not find file extension.")
} else {
let extension = name.slice(periodIndex + 1);
console.info(`[js] Found extension ${extension}.`);
if (!hljs.getLanguage(extension)) {
console.warn(`[js] Extension was not recognized by hljs. Giving up.`);
} else {
console.info("[js] Successfully inferred language from file extension.");
languages = [extension];
}
}
} else {
console.log("[js] No file name hint provided.");
}
} else {
console.info(`[js] Selecting user provided language ${languages[0]} for highlighting.`);
}
// If we still haven't set languages here, then we're leaving it up to the
if (!languages) {
console.log("[js] Deferring to hljs inference for syntax highlighting.");
} else {
hljs.configure({ languages });
}
2021-10-24 02:25:42 -07:00
hljs.highlightAll();
hljs.initLineNumbersOnLoad();
}
function createBlobPasteUi(data, name?: string) {
const bodyEle = document.getElementsByTagName("body")[0];
2021-10-24 02:25:42 -07:00
bodyEle.textContent = '';
const mainEle = document.createElement("main");
2021-10-24 02:25:42 -07:00
mainEle.classList.add("hljs");
mainEle.classList.add("centered");
mainEle.classList.add("fullscreen");
const divEle = document.createElement("div");
2021-10-24 02:25:42 -07:00
divEle.classList.add("centered");
const expirationEle = document.createElement("p");
2021-10-24 02:25:42 -07:00
expirationEle.textContent = data.expiration;
divEle.appendChild(expirationEle);
const downloadEle = document.createElement("a");
downloadEle.href = getObjectUrl(data.data, name);
downloadEle.download = name;
2021-10-24 02:25:42 -07:00
downloadEle.classList.add("hljs-meta");
downloadEle.textContent = "Download binary file.";
divEle.appendChild(downloadEle);
mainEle.appendChild(divEle);
const displayAnywayEle = document.createElement("p");
2021-10-24 02:25:42 -07:00
displayAnywayEle.classList.add("display-anyways");
displayAnywayEle.classList.add("hljs-comment");
displayAnywayEle.textContent = "Display anyways?";
displayAnywayEle.onclick = () => {
data.data.text().then(text => {
data.data = text;
2022-01-11 22:19:15 -08:00
createStringPasteUi(data, "application/octet-stream");
2021-10-24 02:25:42 -07:00
})
};
mainEle.appendChild(displayAnywayEle);
bodyEle.appendChild(mainEle);
}
function createImagePasteUi({ expiration, data, file_size }, name?: string) {
createMultiMediaPasteUi("img", expiration, data, name, (downloadEle, imgEle) => {
imgEle.onload = () => {
const width = imgEle.naturalWidth || imgEle.width;
const height = imgEle.naturalHeight || imgEle.height;
2021-10-27 02:27:44 -07:00
downloadEle.textContent = "Download " + file_size + " \u2014 " + width + " by " + height;
}
});
2021-10-24 11:40:19 -07:00
}
function createAudioPasteUi({ expiration, data }, name?: string) {
createMultiMediaPasteUi("audio", expiration, data, name, "Download");
2021-10-24 11:40:19 -07:00
}
function createVideoPasteUi({ expiration, data }, name?: string) {
createMultiMediaPasteUi("video", expiration, data, name, "Download");
2021-10-24 11:40:19 -07:00
}
function createArchivePasteUi({ expiration, data, entries }, name?: string) {
const bodyEle = document.getElementsByTagName("body")[0];
2021-10-26 18:19:14 -07:00
bodyEle.textContent = '';
const mainEle = document.createElement("main");
2021-10-26 18:19:14 -07:00
const sectionEle = document.createElement("section");
2021-10-27 01:49:06 -07:00
sectionEle.classList.add("paste");
2021-10-26 18:19:14 -07:00
const expirationEle = document.createElement("p");
2021-10-26 18:19:14 -07:00
expirationEle.textContent = expiration;
2021-10-27 01:49:06 -07:00
expirationEle.classList.add("centered");
sectionEle.appendChild(expirationEle);
const downloadEle = document.createElement("a");
downloadEle.href = getObjectUrl(data);
downloadEle.download = name;
2021-10-27 01:49:06 -07:00
downloadEle.textContent = "Download";
downloadEle.classList.add("hljs-meta");
downloadEle.classList.add("centered");
sectionEle.appendChild(downloadEle);
sectionEle.appendChild(document.createElement("hr"));
2021-10-26 18:19:14 -07:00
const mediaEle = document.createElement("table");
2021-10-27 01:49:06 -07:00
mediaEle.classList.add("archive-table");
2021-10-26 18:19:14 -07:00
const tr = mediaEle.insertRow();
2021-10-27 01:49:06 -07:00
tr.classList.add("hljs-title");
2021-10-26 18:19:14 -07:00
const tdName = tr.insertCell();
2021-10-27 01:49:06 -07:00
tdName.textContent = "Name";
2021-10-26 18:19:14 -07:00
const tdSize = tr.insertCell();
2021-10-27 01:49:06 -07:00
tdSize.classList.add("align-right");
tdSize.textContent = "File Size";
// Because it's a stable sort, we can first sort by name (to get all folder
// items grouped together) and then sort by if there's a / or not.
entries.sort((a, b) => {
return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
});
2021-10-27 02:23:28 -07:00
// This doesn't get sub directories and their folders, but hey it's close
// enough
2021-10-27 01:49:06 -07:00
entries.sort((a, b) => {
return b.name.includes("/") - a.name.includes("/");
});
for (const { name, file_size } of entries) {
2021-10-26 18:19:14 -07:00
const tr = mediaEle.insertRow();
const tdName = tr.insertCell();
2021-10-27 01:49:06 -07:00
tdName.textContent = name;
2021-10-26 18:19:14 -07:00
const tdSize = tr.insertCell();
2021-10-27 01:49:06 -07:00
tdSize.textContent = file_size;
tdSize.classList.add("align-right");
tdSize.classList.add("hljs-number");
2021-10-26 18:19:14 -07:00
}
2021-10-27 01:49:06 -07:00
sectionEle.appendChild(mediaEle);
mainEle.appendChild(sectionEle);
2021-10-26 18:19:14 -07:00
bodyEle.appendChild(mainEle);
}
function createMultiMediaPasteUi(tag, expiration, data, name?: string, on_create?) {
const bodyEle = document.getElementsByTagName("body")[0];
2021-10-24 11:40:19 -07:00
bodyEle.textContent = '';
const mainEle = document.createElement("main");
2021-10-24 11:40:19 -07:00
mainEle.classList.add("hljs");
mainEle.classList.add("centered");
mainEle.classList.add("fullscreen");
const downloadLink = getObjectUrl(data, name);
2021-10-24 11:40:19 -07:00
const expirationEle = document.createElement("p");
2021-10-24 11:40:19 -07:00
expirationEle.textContent = expiration;
mainEle.appendChild(expirationEle);
const mediaEle = document.createElement(tag);
mediaEle.src = downloadLink;
mediaEle.controls = true;
mainEle.appendChild(mediaEle);
2021-10-24 11:40:19 -07:00
2021-10-27 01:49:06 -07:00
const downloadEle = document.createElement("a");
2021-10-24 11:40:19 -07:00
downloadEle.href = downloadLink;
downloadEle.download = name;
2021-10-24 11:40:19 -07:00
downloadEle.classList.add("hljs-meta");
mainEle.appendChild(downloadEle);
bodyEle.appendChild(mainEle);
if (on_create instanceof Function) {
on_create(downloadEle, mediaEle);
} else {
downloadEle.textContent = on_create;
}
2021-10-24 11:40:19 -07:00
}
2021-10-25 02:42:20 -07:00
function renderMessage(message) {
const body = document.getElementsByTagName("body")[0];
2021-10-24 02:25:42 -07:00
body.textContent = '';
const mainEle = document.createElement("main");
2021-10-24 02:25:42 -07:00
mainEle.classList.add("hljs");
mainEle.classList.add("centered");
mainEle.classList.add("fullscreen");
mainEle.textContent = message;
2021-10-25 02:42:20 -07:00
body.appendChild(mainEle);
2021-10-24 02:25:42 -07:00
}
function getObjectUrl(data, mimeType?: string) {
return URL.createObjectURL(new Blob(data, {
type: mimeType,
}));
}
2021-10-26 18:19:14 -07:00
window.addEventListener("hashchange", () => location.reload());