Move home page into svelte and remove some old junk
This commit is contained in:
@@ -1,99 +0,0 @@
|
||||
|
||||
let modal_global_index = 100
|
||||
|
||||
// Modal creates a new modal window and shows it. The width and height are will
|
||||
// be adjusted to the screen size. Content should be added to the `body`
|
||||
// property
|
||||
function Modal(parent, closeCallback, title, width, height) {
|
||||
this.parent = parent
|
||||
this.closeCallback = closeCallback
|
||||
this.title = title
|
||||
this.width = width
|
||||
this.height = height
|
||||
this.visible = false
|
||||
|
||||
this.background = document.createElement("div")
|
||||
this.background.classList = "modal_background"
|
||||
this.background.addEventListener("click", e => { this.close() })
|
||||
|
||||
this.window = document.createElement("div")
|
||||
this.window.classList = "modal_window"
|
||||
this.window.style.width = this.width
|
||||
this.window.style.height = this.height
|
||||
this.window.addEventListener("click", e => { e.stopPropagation() })
|
||||
|
||||
this.header = document.createElement("div")
|
||||
this.header.classList = "modal_header"
|
||||
|
||||
this.titleDiv = document.createElement("div")
|
||||
this.titleDiv.classList = "modal_title"
|
||||
this.titleDiv.innerText = this.title
|
||||
|
||||
this.btnClose = document.createElement("button")
|
||||
this.btnClose.classList = "modal_btn_close button_red round"
|
||||
this.btnClose.innerHTML = '<i class="icon">close</i>'
|
||||
this.btnClose.addEventListener("click", e => { this.close() })
|
||||
|
||||
this.body = document.createElement("div")
|
||||
this.body.classList = "modal_body"
|
||||
|
||||
// And add all the elements to eachother.
|
||||
this.header.append(this.titleDiv)
|
||||
this.header.append(this.btnClose)
|
||||
this.window.append(this.header)
|
||||
this.window.append(this.body)
|
||||
this.background.append(this.window)
|
||||
}
|
||||
|
||||
Modal.prototype.setTitle = function (title) {
|
||||
this.title = title
|
||||
this.titleDiv.innerText = title
|
||||
}
|
||||
|
||||
Modal.prototype.setBody = function (element) {
|
||||
this.body.innerHTML = ""
|
||||
this.body.append(element)
|
||||
}
|
||||
|
||||
Modal.prototype.cloneTemplate = function (templateID) {
|
||||
this.setBody(document.getElementById(templateID).content.cloneNode(true))
|
||||
}
|
||||
|
||||
Modal.prototype.open = function () {
|
||||
if (this.visible) { return }
|
||||
this.visible = true
|
||||
|
||||
console.debug("Showing modal " + this.title)
|
||||
|
||||
// Each time a modal is shown it gets a z-index which is one higher of the
|
||||
// previous one. This makes sure they are always shown and closed in order
|
||||
this.background.style.zIndex = modal_global_index
|
||||
modal_global_index++
|
||||
|
||||
this.parent.prepend(this.background)
|
||||
|
||||
// If an element is created and shown in the same frame it won't render the
|
||||
// transition. So here we wait for a few frames to make it visible
|
||||
this.background.style.display = ""
|
||||
setTimeout(() => { this.background.style.opacity = 1 }, 40)
|
||||
|
||||
// This is a workaround for a chrome bug which makes it so hidden
|
||||
// windows can't be scrolled after they are shown
|
||||
this.body.focus()
|
||||
}
|
||||
|
||||
Modal.prototype.close = function () {
|
||||
if (!this.visible) { return }
|
||||
this.visible = false
|
||||
|
||||
if (this.closeCallback) {
|
||||
this.closeCallback()
|
||||
}
|
||||
|
||||
// First we make it invisible with a transition. When we remove it so the
|
||||
// user can click through it
|
||||
this.background.style.opacity = 0
|
||||
|
||||
// Wait for the animation to finish and remove the window
|
||||
setTimeout(() => { this.parent.removeChild(this.background) }, 400)
|
||||
}
|
@@ -1,166 +0,0 @@
|
||||
function UploadManager(uploadEndpoint, uploadsFinished) {
|
||||
this.uploadEndpoint = uploadEndpoint;
|
||||
|
||||
// Callback function for when the queue is empty
|
||||
this.uploadsFinished = uploadsFinished;
|
||||
|
||||
// Counts the total number of upload jobs
|
||||
this.jobCounter = 0;
|
||||
|
||||
// Queue of files to be uploaded. Format:
|
||||
// {
|
||||
// jobID: number,
|
||||
// file: Blob,
|
||||
// name: string,
|
||||
// onProgress: function,
|
||||
// onFinished: function,
|
||||
// onFailure: function,
|
||||
// tries: number
|
||||
// }
|
||||
this.uploadQueue = [];
|
||||
|
||||
// Here we put successful jobs. The array should be sorted by job ID.
|
||||
// Format:
|
||||
// { jobID: number, fileID: string, fileName: string }
|
||||
this.uploadLog = [];
|
||||
|
||||
// Max number of uploading threads at once
|
||||
this.maxWorkers = 3;
|
||||
|
||||
// Threads which are currently uploading
|
||||
this.activeWorkers = 0;
|
||||
|
||||
// Total number of jobs accepted
|
||||
this.jobCounter = 0;
|
||||
}
|
||||
|
||||
UploadManager.prototype.finishedUploads = function () {
|
||||
this.uploadLog.sort((a, b) => {
|
||||
return a.jobID - b.jobID;
|
||||
})
|
||||
return this.uploadLog;
|
||||
}
|
||||
|
||||
UploadManager.prototype.addFile = function (
|
||||
file, // Blob
|
||||
name, // string
|
||||
onProgress, // func (progress: number)
|
||||
onFinished, // func (id: string)
|
||||
onFailure // func (errorID: string, errorMessage: string)
|
||||
) {
|
||||
this.uploadQueue.push({
|
||||
jobID: this.jobCounter,
|
||||
file: file,
|
||||
name: name,
|
||||
onProgress: onProgress,
|
||||
onFinished: onFinished,
|
||||
onFailure: onFailure,
|
||||
tries: 0
|
||||
});
|
||||
|
||||
// Increment the job counter
|
||||
this.jobCounter++
|
||||
|
||||
if (this.activeWorkers < this.maxWorkers) {
|
||||
// Run the upload function
|
||||
this.startUpload();
|
||||
}
|
||||
}
|
||||
|
||||
UploadManager.prototype.startUpload = function () {
|
||||
if (this.uploadQueue.length === 0) {
|
||||
return; // Nothing to upload
|
||||
}
|
||||
|
||||
if (this.activeWorkers < this.maxWorkers) {
|
||||
this.activeWorkers++;
|
||||
this.uploadThread();
|
||||
}
|
||||
}
|
||||
|
||||
UploadManager.prototype.finishUpload = function () {
|
||||
this.activeWorkers--;
|
||||
|
||||
if (
|
||||
this.uploadQueue.length === 0 &&
|
||||
this.activeWorkers === 0 &&
|
||||
typeof (this.uploadsFinished) === "function"
|
||||
) {
|
||||
this.uploadsFinished();
|
||||
return;
|
||||
}
|
||||
|
||||
// Run the upload function for the next file
|
||||
this.startUpload();
|
||||
}
|
||||
|
||||
UploadManager.prototype.uploadThread = function () {
|
||||
let job = this.uploadQueue.shift(); // Get the first element of the array
|
||||
console.debug("Starting upload of " + job.name);
|
||||
|
||||
let form = new FormData();
|
||||
form.append('file', job.file, job.name);
|
||||
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", this.uploadEndpoint, true);
|
||||
xhr.timeout = 21600000; // 6 hours, to account for slow connections
|
||||
|
||||
// Report progress updates back to the caller
|
||||
xhr.upload.addEventListener("progress", evt => {
|
||||
if (evt.lengthComputable && typeof (job.onProgress) === "function") {
|
||||
job.onProgress(evt.loaded / evt.total);
|
||||
}
|
||||
});
|
||||
|
||||
xhr.onreadystatechange = () => {
|
||||
// readystate 4 means the upload is done
|
||||
if (xhr.readyState !== 4) { return; }
|
||||
|
||||
if (xhr.status >= 100 && xhr.status < 400) {
|
||||
// Request is a success
|
||||
let resp = JSON.parse(xhr.response);
|
||||
addUploadHistory(resp.id)
|
||||
|
||||
// Log the successful job
|
||||
this.uploadLog.push({
|
||||
jobID: job.jobID,
|
||||
fileID: resp.id,
|
||||
fileName: job.name
|
||||
});
|
||||
|
||||
if (typeof (job.onFinished) === "function") {
|
||||
job.onFinished(resp.id);
|
||||
}
|
||||
|
||||
// Finish the upload job
|
||||
this.finishUpload();
|
||||
} else if (xhr.status >= 400) {
|
||||
// Request failed
|
||||
console.log("Upload error. status: " + xhr.status + " response: " + xhr.response);
|
||||
let resp = JSON.parse(xhr.response);
|
||||
if (resp.value == "file_too_large" || job.tries === 3) { // Upload failed
|
||||
job.onFailure(resp.value, resp.message);
|
||||
} else { // Try again
|
||||
job.tries++;
|
||||
this.uploadQueue.push(job);
|
||||
}
|
||||
|
||||
// Sleep the upload thread for 5 seconds
|
||||
window.setTimeout(() => { this.finishUpload(); }, 5000);
|
||||
} else {
|
||||
// Request did not arrive
|
||||
if (job.tries === 3) { // Upload failed
|
||||
if (typeof (job.onFailure) === "function") {
|
||||
job.onFailure(xhr.responseText, xhr.responseText);
|
||||
}
|
||||
} else { // Try again
|
||||
job.tries++;
|
||||
this.uploadQueue.push(job);
|
||||
}
|
||||
|
||||
// Sleep the upload thread for 5 seconds
|
||||
window.setTimeout(() => { this.finishUpload(); }, 5000);
|
||||
}
|
||||
};
|
||||
xhr.send(form);
|
||||
}
|
@@ -1,104 +0,0 @@
|
||||
function addUploadHistory(fileID) {
|
||||
// Make sure the user is not logged in, for privacy. This keeps the
|
||||
// files uploaded while logged in and anonymously uploaded files
|
||||
// separated
|
||||
if (document.cookie.includes("pd_auth_key")) { return; }
|
||||
|
||||
let uploads = localStorage.getItem("uploaded_files");
|
||||
if (uploads === null) { uploads = ""; }
|
||||
|
||||
// Check if there are not too many values stored
|
||||
if (uploads.length > 3600) {
|
||||
// 3600 characters is enough to store 400 file IDs. If we exceed that
|
||||
// number we'll drop the last two items
|
||||
uploads = uploads.substring(
|
||||
uploads.indexOf(",") + 1
|
||||
).substring(
|
||||
uploads.indexOf(",") + 1
|
||||
);
|
||||
}
|
||||
|
||||
// Save the new ID
|
||||
localStorage.setItem("uploaded_files", fileID + "," + uploads);
|
||||
}
|
||||
|
||||
function printDate(date, hours, minutes, seconds) {
|
||||
let dateStr = date.getFullYear()
|
||||
+ "-" + ("00" + (date.getMonth() + 1)).slice(-2)
|
||||
+ "-" + ("00" + date.getDate()).slice(-2)
|
||||
|
||||
if (hours) { dateStr += " " + ("00" + date.getHours()).slice(-2) }
|
||||
if (minutes) { dateStr += ":" + ("00" + date.getMinutes()).slice(-2) }
|
||||
if (seconds) { dateStr += ":" + ("00" + date.getMinutes()).slice(-2) }
|
||||
return dateStr
|
||||
}
|
||||
|
||||
function copyText(text) {
|
||||
// Create a textarea to copy the text from
|
||||
let ta = document.createElement("textarea");
|
||||
ta.setAttribute("readonly", "readonly")
|
||||
ta.style.position = "absolute";
|
||||
ta.style.left = "-9999px";
|
||||
ta.value = text; // Put the text in the textarea
|
||||
|
||||
// Add the textarea to the DOM so it can be seleted by the user
|
||||
document.body.appendChild(ta);
|
||||
ta.select() // Select the contents of the textarea
|
||||
let success = document.execCommand("copy"); // Copy the selected text
|
||||
document.body.removeChild(ta); // Remove the textarea
|
||||
return success;
|
||||
}
|
||||
|
||||
function domainURL() {
|
||||
let url = window.location.protocol + "//" + window.location.hostname;
|
||||
if (window.location.port != "") {
|
||||
url = url + ":" + window.location.port;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
function formatNumber(amt, precision) {
|
||||
if (precision < 3) { precision = 3; }
|
||||
if (amt >= 1e6) {
|
||||
return (amt / 1e6).toPrecision(precision) + "M";
|
||||
} else if (amt >= 1e3) {
|
||||
return (amt / 1e3).toPrecision(precision) + "k";
|
||||
}
|
||||
return amt
|
||||
}
|
||||
|
||||
function formatThousands(x) {
|
||||
// Inject a space every three digits
|
||||
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " ");
|
||||
}
|
||||
|
||||
function formatDataVolume(amt, precision) {
|
||||
if (precision < 3) { precision = 3; }
|
||||
if (amt >= 1e18) {
|
||||
return (amt / 1e18).toPrecision(precision) + " EB";
|
||||
} else if (amt >= 1e15) {
|
||||
return (amt / 1e15).toPrecision(precision) + " PB";
|
||||
} else if (amt >= 1e12) {
|
||||
return (amt / 1e12).toPrecision(precision) + " TB";
|
||||
} else if (amt >= 1e9) {
|
||||
return (amt / 1e9).toPrecision(precision) + " GB";
|
||||
} else if (amt >= 1e6) {
|
||||
return (amt / 1e6).toPrecision(precision) + " MB";
|
||||
} else if (amt >= 1e3) {
|
||||
return (amt / 1e3).toPrecision(precision) + " kB";
|
||||
}
|
||||
return Math.floor(amt) + " B"
|
||||
}
|
||||
|
||||
const second = 1000
|
||||
const minute = second * 60
|
||||
const hour = minute * 60
|
||||
const day = hour * 24
|
||||
|
||||
function formatDuration(ms) {
|
||||
let res = ""
|
||||
if (ms >= day) { res += Math.floor(ms / day) + "d " }
|
||||
if (ms >= hour) { res += Math.floor((ms % day) / hour) + "h " }
|
||||
if (ms >= minute) { res += Math.floor((ms % hour) / minute) + "m " }
|
||||
return res + ((ms % minute) / second).toFixed(3) + "s"
|
||||
}
|
@@ -1,16 +1,16 @@
|
||||
function renderFileButton(apiURL, id, title, subtitle) {
|
||||
let btn = document.createElement("a")
|
||||
btn.classList = "file_button"
|
||||
btn.href = "/u/"+id
|
||||
btn.target = "_blank"
|
||||
let thumbnail = document.createElement("img")
|
||||
thumbnail.src = apiURL+"/file/"+id+"/thumbnail?width=80&height=80"
|
||||
thumbnail.alt = title
|
||||
let titleSpan = document.createElement("span")
|
||||
titleSpan.classList = "file_button_title"
|
||||
titleSpan.innerText = title
|
||||
let br = document.createElement("br")
|
||||
let subtitleSpan = document.createElement("span")
|
||||
let btn = document.createElement("a")
|
||||
btn.classList = "file_button"
|
||||
btn.href = "/u/" + id
|
||||
btn.target = "_blank"
|
||||
let thumbnail = document.createElement("img")
|
||||
thumbnail.src = apiURL + "/file/" + id + "/thumbnail?width=80&height=80"
|
||||
thumbnail.alt = title
|
||||
let titleSpan = document.createElement("span")
|
||||
titleSpan.classList = "file_button_title"
|
||||
titleSpan.innerText = title
|
||||
let br = document.createElement("br")
|
||||
let subtitleSpan = document.createElement("span")
|
||||
subtitleSpan.classList = "file_button_subtitle"
|
||||
subtitleSpan.innerText = subtitle
|
||||
|
||||
@@ -26,6 +26,17 @@ function getCookie(name) {
|
||||
return result ? result[1] : null
|
||||
}
|
||||
|
||||
function printDate(date, hours, minutes, seconds) {
|
||||
let dateStr = date.getFullYear()
|
||||
+ "-" + ("00" + (date.getMonth() + 1)).slice(-2)
|
||||
+ "-" + ("00" + date.getDate()).slice(-2)
|
||||
|
||||
if (hours) { dateStr += " " + ("00" + date.getHours()).slice(-2) }
|
||||
if (minutes) { dateStr += ":" + ("00" + date.getMinutes()).slice(-2) }
|
||||
if (seconds) { dateStr += ":" + ("00" + date.getMinutes()).slice(-2) }
|
||||
return dateStr
|
||||
}
|
||||
|
||||
// Get the uploads from localstorage
|
||||
let uploadsStr = localStorage.getItem("uploaded_files")
|
||||
if (uploadsStr === null) { uploadsStr = "" }
|
||||
@@ -51,7 +62,7 @@ function getHistoryItem() {
|
||||
if (item === undefined || item === "") { return }
|
||||
|
||||
fetch(
|
||||
apiEndpoint+"/file/"+item+"/info"
|
||||
apiEndpoint + "/file/" + item + "/info"
|
||||
).then(resp => {
|
||||
if (!resp.ok) {
|
||||
return Promise.reject()
|
||||
@@ -68,7 +79,7 @@ function getHistoryItem() {
|
||||
)
|
||||
getHistoryItem()
|
||||
}).catch(err => {
|
||||
console.log("Fetch failed: "+err)
|
||||
console.log("Fetch failed: " + err)
|
||||
getHistoryItem()
|
||||
})
|
||||
}
|
||||
|
@@ -1,64 +0,0 @@
|
||||
.modal_background {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
opacity: 0;
|
||||
transition: opacity .4s;
|
||||
}
|
||||
|
||||
.modal_window {
|
||||
position: absolute;
|
||||
z-index: inherit;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: var(--layer_2_color);
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
top: 20%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -20%);
|
||||
padding: 0;
|
||||
text-align: left;
|
||||
/* box-shadow: var(--shadow_color) 0px 0px 50px; */
|
||||
border-radius: 20px 20px 8px 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.modal_header {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
background: var(--layer_1_color);
|
||||
color: var(--layer_1_text_color);
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.modal_title {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.2em;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.modal_btn_close {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.modal_body {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
}
|
Reference in New Issue
Block a user