mirror of https://github.com/raftario/filite.git
253 lines
7.8 KiB
JavaScript
253 lines
7.8 KiB
JavaScript
const tabs = {
|
|
files: [
|
|
document.querySelector("#files-tab"),
|
|
document.querySelector("#files-form"),
|
|
],
|
|
links: [
|
|
document.querySelector("#links-tab"),
|
|
document.querySelector("#links-form"),
|
|
],
|
|
texts: [
|
|
document.querySelector("#texts-tab"),
|
|
document.querySelector("#texts-form"),
|
|
],
|
|
};
|
|
|
|
const inputs = {
|
|
files: [
|
|
document.querySelector("#files-url"),
|
|
document.querySelector("#files-file"),
|
|
document.querySelector("#files-submit"),
|
|
],
|
|
links: [
|
|
document.querySelector("#links-url"),
|
|
document.querySelector("#links-forward"),
|
|
document.querySelector("#links-submit"),
|
|
],
|
|
texts: [
|
|
document.querySelector("#texts-url"),
|
|
document.querySelector("#texts-contents"),
|
|
document.querySelector("#texts-submit"),
|
|
],
|
|
};
|
|
|
|
const used = {
|
|
files: [],
|
|
links: [],
|
|
texts: [],
|
|
};
|
|
|
|
let baseUrl = `${location.protocol}//${location.host}${location.pathname}`;
|
|
if (!baseUrl.endsWith("/")) {
|
|
baseUrl += "/";
|
|
}
|
|
|
|
const fetchUsed = () => {
|
|
fetch(`${baseUrl}f`)
|
|
.then((response) => response.json())
|
|
.then((json) => (used.files = json));
|
|
fetch(`${baseUrl}l`)
|
|
.then((response) => response.json())
|
|
.then((json) => (used.links = json));
|
|
fetch(`${baseUrl}t`)
|
|
.then((response) => response.json())
|
|
.then((json) => (used.texts = json));
|
|
};
|
|
fetchUsed();
|
|
|
|
const randomUrl = () => {
|
|
return Math.floor(Math.random() * 2147483647).toString(36);
|
|
};
|
|
|
|
const updateClipboard = (data) => {
|
|
navigator.permissions
|
|
.query({ name: "clipboard-write" })
|
|
.then((result) => {
|
|
if (result.state === "denied") {
|
|
throw new Error();
|
|
}
|
|
})
|
|
.then(() => navigator.clipboard.writeText(data))
|
|
.then(() => alert("URL copied to clipboard"))
|
|
.catch(() => alert(data));
|
|
};
|
|
|
|
for (const group in tabs) {
|
|
tabs[group][0].onclick = () => {
|
|
const active = document.querySelectorAll(".active");
|
|
for (const el of active) {
|
|
el.classList.remove("active");
|
|
}
|
|
for (const el of tabs[group]) {
|
|
el.classList.add("active");
|
|
}
|
|
};
|
|
}
|
|
|
|
for (const group in inputs) {
|
|
const submitButton = inputs[group][inputs[group].length - 1];
|
|
|
|
const urlInput = inputs[group][0];
|
|
urlInput.addEventListener("input", (e) => {
|
|
if (urlInput.value[urlInput.value.length - 1] === " ") {
|
|
urlInput.value = randomUrl();
|
|
checkValidity();
|
|
e.preventDefault();
|
|
return;
|
|
}
|
|
|
|
urlInput.value = urlInput.value
|
|
.replace(/[^0-9A-Za-z]/g, "")
|
|
.toLowerCase();
|
|
if (parseInt(urlInput.value, 36) > 2147483647) {
|
|
urlInput.setCustomValidity(
|
|
"Base 36 integer below or equal to zik0zj"
|
|
);
|
|
} else {
|
|
urlInput.setCustomValidity("");
|
|
}
|
|
});
|
|
|
|
const checkValidity = () => {
|
|
if (used[group].some((x) => x.id === parseInt(urlInput.value, 36))) {
|
|
urlInput.classList.add("conflict");
|
|
} else {
|
|
urlInput.classList.remove("conflict");
|
|
}
|
|
submitButton.disabled = inputs[group].some(
|
|
(input) => input.validity != undefined && !input.validity.valid
|
|
);
|
|
};
|
|
|
|
for (const input of inputs[group].filter(
|
|
(input) =>
|
|
input instanceof HTMLInputElement ||
|
|
input instanceof HTMLTextAreaElement
|
|
)) {
|
|
input.addEventListener("input", () => checkValidity());
|
|
input.addEventListener("change", () => checkValidity());
|
|
}
|
|
|
|
const clearInputs = () => {
|
|
for (const input of inputs[group].filter(
|
|
(input) =>
|
|
input instanceof HTMLInputElement ||
|
|
input instanceof HTMLTextAreaElement
|
|
)) {
|
|
input.value = "";
|
|
}
|
|
submitButton.disabled = true;
|
|
};
|
|
|
|
if (group === "files") {
|
|
const filesFileInput = inputs.files[1];
|
|
const filesBrowseButton = document.querySelector("#files-browse");
|
|
const filesValueInput = document.querySelector("#files-value");
|
|
filesFileInput.addEventListener("change", () => {
|
|
filesValueInput.value = filesFileInput.files[0].name || "";
|
|
});
|
|
filesBrowseButton.onclick = () => {
|
|
filesFileInput.click();
|
|
};
|
|
filesValueInput.onfocus = (e) => {
|
|
e.preventDefault();
|
|
filesValueInput.blur();
|
|
return false;
|
|
};
|
|
|
|
submitButton.addEventListener("click", () => {
|
|
const file = filesFileInput.files[0];
|
|
|
|
if (!file) {
|
|
alert(new Error("No file selected"));
|
|
return;
|
|
}
|
|
|
|
let fileReader = new FileReader();
|
|
fileReader.onload = () => {
|
|
const id = urlInput.value;
|
|
const url = `${baseUrl}f/${id}`;
|
|
|
|
const base64 = btoa(fileReader.result);
|
|
const filename = file.name;
|
|
let status;
|
|
fetch(url, {
|
|
method: "PUT",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ base64, filename }),
|
|
})
|
|
.then((response) => {
|
|
status = response.status;
|
|
return response.text();
|
|
})
|
|
.then((text) => {
|
|
if (status !== 201) {
|
|
throw new Error(text);
|
|
} else {
|
|
updateClipboard(url);
|
|
clearInputs();
|
|
filesValueInput.value = "";
|
|
fetchUsed();
|
|
}
|
|
})
|
|
.catch((error) => alert(error));
|
|
};
|
|
fileReader.readAsBinaryString(file);
|
|
});
|
|
} else if (group === "links") {
|
|
submitButton.addEventListener("click", () => {
|
|
const id = urlInput.value;
|
|
const forward = inputs.links[1].value;
|
|
|
|
const url = `${baseUrl}l/${id}`;
|
|
let status;
|
|
fetch(url, {
|
|
method: "PUT",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ forward }),
|
|
})
|
|
.then((response) => {
|
|
status = response.status;
|
|
return response.text();
|
|
})
|
|
.then((text) => {
|
|
if (status !== 201) {
|
|
throw new Error(text);
|
|
} else {
|
|
updateClipboard(url);
|
|
clearInputs();
|
|
fetchUsed();
|
|
}
|
|
})
|
|
.catch((error) => alert(error));
|
|
});
|
|
} else if (group === "texts") {
|
|
submitButton.addEventListener("click", () => {
|
|
const id = urlInput.value;
|
|
const contents = inputs.texts[1].value;
|
|
|
|
const url = `${baseUrl}t/${id}`;
|
|
let status;
|
|
fetch(url, {
|
|
method: "PUT",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ contents, highlight: true }),
|
|
})
|
|
.then((response) => {
|
|
status = response.status;
|
|
return response.text();
|
|
})
|
|
.then((text) => {
|
|
if (status !== 201) {
|
|
throw new Error(text);
|
|
} else {
|
|
updateClipboard(url);
|
|
clearInputs();
|
|
fetchUsed();
|
|
}
|
|
})
|
|
.catch((error) => alert(error));
|
|
});
|
|
}
|
|
}
|