diff --git a/static/js/main.js b/static/js/main.js index 8c31370..f5c4934 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -628,7 +628,27 @@ function importNotes(plaintextNotes) { let encryptedContent = CryptoJS.AES.encrypt(originalContent, password).toString(); plaintextNotes[i]["content"] = encryptedContent; } - return JSON.stringify(plaintextNotes); + fetch(remote + "/api/importnotes", { + method: "POST", + body: JSON.stringify({ + "secretKey": localStorage.getItem("DONOTSHARE-secretkey"), + "notes": JSON.stringify(plaintextNotes) + }), + headers: { + "Content-Type": "application/json; charset=UTF-8" + } + }) + .then((response) => { + async function doStuff() { + if (response.status === 500) { + displayError("Something went wrong! Perhaps your note file was invalid?") + } else { + displayError("Notes uploaded!") + updateNotes() + } + } + doStuff() + }) } function firstNewVersion() { @@ -670,9 +690,7 @@ importFile.addEventListener('change', function(e) { "load", () => { let decrypted = JSON.parse(fileread.result) - console.log(decrypted) - let encrypted = importNotes(decrypted) - console.log(encrypted) + importNotes(decrypted) }, false, ); diff --git a/static/js/main.js.save b/static/js/main.js.save deleted file mode 100644 index 1e68bf0..0000000 --- a/static/js/main.js.save +++ /dev/null @@ -1,695 +0,0 @@ -if (localStorage.getItem("DONOTSHARE-secretkey") === null) { - window.location.replace("/login") - document.body.innerHTML = "Redirecting..." - throw new Error(); -} -if (localStorage.getItem("DONOTSHARE-password") === null) { - window.location.replace("/login") - document.body.innerHTML = "Redirecting..." - throw new Error(); -} - -if (localStorage.getItem("CACHE-username") !== null) { - document.getElementById("usernameBox").innerText = localStorage.getItem("CACHE-username") -} - -let remote = localStorage.getItem("homeserverURL") -if (remote == null) { - localStorage.setItem("homeserverURL", "https://notes.hectabit.org") - remote = "https://notes.hectabit.org" -} - -function formatBytes(a, b = 2) { if (!+a) return "0 Bytes"; const c = 0 > b ? 0 : b, d = Math.floor(Math.log(a) / Math.log(1000)); return `${parseFloat((a / Math.pow(1000, d)).toFixed(c))} ${["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"][d]}` } - -let secretkey = localStorage.getItem("DONOTSHARE-secretkey") -let password = localStorage.getItem("DONOTSHARE-password") -let currentFontSize = 16 -let markdowntoggle = false - -let burgerButton = document.getElementById("burgerButton") -let backButton = document.getElementById("backButton") -let usernameBox = document.getElementById("usernameBox") -let optionsCoverDiv = document.getElementById("optionsCoverDiv") -let optionsDiv = document.getElementById("optionsDiv") -let errorDiv = document.getElementById("errorDiv") -let errorMessageThing = document.getElementById("errorMessageThing") -let closeErrorButton = document.getElementById("closeErrorButton") -let cancelErrorButton = document.getElementById("cancelErrorButton") -let errorInput = document.getElementById("errorInput") -let exitThing = document.getElementById("exitThing") -let exitSessionsThing = document.getElementById("exitSessionsThing") -let sessionManagerButton = document.getElementById("sessionManagerButton") -let importNotesButton = document.getElementById("importNotesButton") -let sessionManagerDiv = document.getElementById("sessionManagerDiv") -let importNotesDiv = document.getElementById("importDiv") -let sessionDiv = document.getElementById("sessionDiv") -let deleteMyAccountButton = document.getElementById("deleteMyAccountButton") -let storageThing = document.getElementById("storageThing") -let storageProgressThing = document.getElementById("storageProgressThing") -let usernameThing = document.getElementById("usernameThing") -let logOutButton = document.getElementById("logOutButton") -let notesBar = document.getElementById("notesBar") -let notesDiv = document.getElementById("notesDiv") -let newNote = document.getElementById("newNote") -let noteBox = document.getElementById("noteBox") -let noteBoxDiv = document.getElementById("noteBoxDiv") -let loadingStuff = document.getElementById("loadingStuff") -let exportNotesButton = document.getElementById("exportNotesButton") -let markdown = document.getElementById('markdown'); -let textSizeBox = document.getElementById('textSizeBox'); -let textPlusBox = document.getElementById('textPlusBox'); -let textMinusBox = document.getElementById('textMinusBox'); -let wordCountBox = document.getElementById('wordCountBox'); -let removeBox = document.getElementById("removeBox") -let importFile = document.getElementById("importFile") - -let selectedNote = 0 -let timer -let waitTime = 400 -let indiv = false - -if (/Android|iPhone|iPod/i.test(navigator.userAgent)) { - noteBoxDiv.style.width = "0px"; - notesBar.style.width = "calc(100% + 7.5px)" - noteBoxDiv.readOnly = true - noteBox.style.fontSize = "18px" - noteBoxDiv.classList.add("hidden") - - let touchstartX, touchstartY, touchendX, touchendY - - notesBar.addEventListener("touchstart", function (event) { - touchstartX = event.changedTouches[0].screenX; - touchstartY = event.changedTouches[0].screenY; - }, false); - - notesBar.addEventListener("touchend", function (event) { - touchendX = event.changedTouches[0].screenX; - touchendY = event.changedTouches[0].screenY; - handleGesture(); - }, false); - - noteBox.addEventListener("touchstart", function (event) { - touchstartX = event.changedTouches[0].screenX; - touchstartY = event.changedTouches[0].screenY; - }, false); - - noteBox.addEventListener("touchend", function (event) { - touchendX = event.changedTouches[0].screenX; - touchendY = event.changedTouches[0].screenY; - handleGesture(); - }, false); -} - -function handleGesture() { - if (indiv) { - indiv = false - notesBar.style.width = "calc(100% + 7.5px)"; - noteBoxDiv.style.width = "0px" - if (selectedNote !== 0) { - noteBoxDiv.readOnly = true - } - notesDiv.classList.remove("hidden") - noteBoxDiv.classList.add("hidden") - burgerButton.classList.remove("hidden") - backButton.classList.add("hidden") - newNote.classList.remove("hidden") - } else { - indiv = true - noteBoxDiv.style.width = "100%"; - notesBar.style.width = "0px" - if (selectedNote !== 0) { - noteBoxDiv.readOnly = false - } - notesDiv.classList.add("hidden") - noteBoxDiv.classList.remove("hidden") - burgerButton.classList.add("hidden") - backButton.classList.remove("hidden") - newNote.classList.add("hidden") - } -} - -noteBox.value = "" -noteBox.readOnly = true - -let noteCount = 0 - -function displayError(message) { - errorDiv.classList.remove("hidden") - optionsCoverDiv.classList.remove("hidden") - - errorMessageThing.innerHTML = message -} - -closeErrorButton.addEventListener("click", () => { - errorDiv.classList.add("hidden") - optionsCoverDiv.classList.add("hidden") -}); -closeErrorButton.addEventListener("click", () => { - errorDiv.classList.add("hidden") - optionsCoverDiv.classList.add("hidden") - errorInput.classList.add("hidden") - cancelErrorButton.classList.add("hidden") -}); - -function updateFont() { - currentFontSize = localStorage.getItem("SETTING-fontsize") - noteBox.style.fontSize = currentFontSize + "px" - textSizeBox.innerText = currentFontSize + "px" - if (markdowntoggle) { - markdown.srcdoc = "" + marked.parse(noteBox.value) + ""; - } -} - -async function waitforedit() { - while(true) { - await fetch(remote + "/api/waitforedit", { - method: "POST", - body: JSON.stringify({ - "secretKey": localStorage.getItem("DONOTSHARE-secretkey") - }), - headers: { - "Content-Type": "application/json; charset=UTF-8" - } - }) - .then(async (response) => { - async function doStuff() { - const data = await response.json(); - // Access the "note" field from the response - const note = data["note"]; - if (note === selectedNote) { - selectNote(selectedNote) - } - } - doStuff() - }); - } -} - -if (localStorage.getItem("SETTING-fontsize") === null) { - localStorage.setItem("SETTING-fontsize", "16") - updateFont() -} else { - updateFont() -} - -textPlusBox.addEventListener("click", () => { - localStorage.setItem("SETTING-fontsize", String(Number(localStorage.getItem("SETTING-fontsize")) + Number(1))) - updateFont() -}); -textMinusBox.addEventListener("click", () => { - localStorage.setItem("SETTING-fontsize", String(Number(localStorage.getItem("SETTING-fontsize")) - Number(1))) - updateFont() -}); - - -function truncateString(str, num) { - if (str.length > num) { - return str.slice(0, num) + ".."; - } else { - return str; - } -} - - -function updateUserInfo() { - fetch(remote + "/api/userinfo", { - method: "POST", - body: JSON.stringify({ - secretKey: secretkey - }), - headers: { - "Content-Type": "application/json; charset=UTF-8" - } - }) - .catch(() => { - noteBox.readOnly = true - noteBox.value = "" - noteBox.placeholder = "Failed to connect to the server.\nPlease check your internet connection." - }) - .then((response) => { - async function doStuff() { - if (response.status === 500) { - displayError("Something went wrong! Signing you out..") - closeErrorButton.classList.add("hidden") - usernameBox.innerText = "" - setTimeout(function () { - window.location.replace("/logout") - }, 2500); - } else { - let responseData = await response.json() - usernameBox.innerText = responseData["username"] - usernameThing.innerText = "Username: " + responseData["username"] - storageThing.innerText = "You've used " + formatBytes(responseData["storageused"]) + " out of " + formatBytes(responseData["storagemax"]) - storageProgressThing.value = responseData["storageused"] - storageProgressThing.max = responseData["storagemax"] - noteCount = responseData["notecount"] - localStorage.setItem("CACHE-username", responseData["username"]) - } - } - doStuff() - }); -} -usernameBox.addEventListener("click", () => { - optionsCoverDiv.classList.remove("hidden") - optionsDiv.classList.remove("hidden") - updateUserInfo() -}); -logOutButton.addEventListener("click", () => { - window.location.replace("/logout") -}); -exitThing.addEventListener("click", () => { - optionsDiv.classList.add("hidden") - optionsCoverDiv.classList.add("hidden") -}); -deleteMyAccountButton.addEventListener("click", () => { - if (confirm("Are you REALLY sure that you want to delete your account? There's no going back!") === true) { - fetch(remote + "/api/deleteaccount", { - method: "POST", - body: JSON.stringify({ - secretKey: secretkey - }), - headers: { - "Content-Type": "application/json; charset=UTF-8" - } - }) - .then((response) => { - if (response.status === 200) { - window.location.href = "/logout" - } else { - displayError("Failed to delete account (HTTP error code " + response.status + ")") - } - }) - } -}); -importNotesButton.addEventListener("click", () => { - optionsDiv.classList.add("hidden") - importNotesDiv.classList.remove("hidden") -}); -sessionManagerButton.addEventListener("click", () => { - optionsDiv.classList.add("hidden") - sessionManagerDiv.classList.remove("hidden") - - fetch(remote + "/api/sessions/list", { - method: "POST", - body: JSON.stringify({ - secretKey: secretkey - }), - headers: { - "Content-Type": "application/json; charset=UTF-8" - } - }) - .then((response) => { - async function doStuff() { - let responseData = await response.json() - document.querySelectorAll(".burgerSession").forEach((el) => el.remove()); - let ua; - for (let i in responseData) { - let sessionElement = document.createElement("div") - let sessionText = document.createElement("p") - let sessionImage = document.createElement("img") - let sessionRemoveButton = document.createElement("button") - sessionText.classList.add("w300") - if (responseData[i]["thisSession"] === true) { - sessionText.innerText = "(current) " + responseData[i]["device"] - } else { - sessionText.innerText = responseData[i]["device"] - } - sessionText.title = responseData[i]["device"] - sessionRemoveButton.innerText = "x" - - sessionImage.src = "/static/svg/device_other.svg" - - ua = responseData[i]["device"] - - if (ua.includes("NT") || ua.includes("Linux")) { - sessionImage.src = "/static/svg/device_computer.svg" - } - if (ua.includes("iPhone" || ua.includes("Android") || ua.includes("iPod"))) { - sessionImage.src = "/static/svg/device_smartphone.svg" - } - - sessionRemoveButton.addEventListener("click", () => { - fetch(remote + "/api/sessions/remove", { - method: "POST", - body: JSON.stringify({ - secretKey: secretkey, - sessionId: responseData[i]["id"] - }), - headers: { - "Content-Type": "application/json; charset=UTF-8" - } - }) - .then(() => { - if (responseData[i]["thisSession"] === true) { - window.location.replace("/logout") - } - }); - sessionElement.remove() - }); - - sessionElement.append(sessionImage) - sessionElement.append(sessionText) - sessionElement.append(sessionRemoveButton) - - sessionElement.classList.add("burgerSession") - - sessionDiv.append(sessionElement) - } - } - doStuff() - }); -}); -exitImportThing.addEventListener("click", () => { - optionsDiv.classList.remove("hidden") - importNotesDiv.classList.add("hidden") -}); -exitSessionsThing.addEventListener("click", () => { - optionsDiv.classList.remove("hidden") - sessionManagerDiv.classList.add("hidden") -}); - -updateUserInfo() - -function updateWordCount() { - let wordCount = noteBox.value.split(" ").length - if (wordCount === 1) { - wordCount = 0 - } - wordCountBox.innerText = wordCount + " words" -} - -function renderMarkDown() { - if (markdowntoggle) { - markdown.srcdoc = "" + marked.parse(noteBox.value) + "" - } -} - -function selectNote(nameithink) { - document.querySelectorAll(".noteButton").forEach((el) => el.classList.remove("selected")); - let thingArray = Array.from(document.querySelectorAll(".noteButton")).find(el => String(nameithink) === String(el.id)); - thingArray.classList.add("selected") - - fetch(remote + "/api/readnote", { - method: "POST", - body: JSON.stringify({ - secretKey: secretkey, - noteId: nameithink, - }), - headers: { - "Content-Type": "application/json; charset=UTF-8" - } - }) - .catch(() => { - noteBox.readOnly = true - noteBox.value = "" - noteBox.placeholder = "" - displayError("Something went wrong... Please try again later!") - }) - .then((response) => { - selectedNote = nameithink - if (/Android|iPhone|iPod/i.test(navigator.userAgent)) { - handleGesture() - } - noteBox.readOnly = false - noteBox.placeholder = "Type something!" - - async function doStuff() { - let responseData = await response.json() - - let bytes = CryptoJS.AES.decrypt(responseData["content"], password); - noteBox.value = bytes.toString(CryptoJS.enc.Utf8) - updateWordCount() - renderMarkDown() - - noteBox.addEventListener("input", () => { - updateWordCount() - renderMarkDown() - clearTimeout(timer); - timer = setTimeout(() => { - let encryptedTitle = "New note" - if (noteBox.value.substring(0, noteBox.value.indexOf("\n")) !== "") { - let firstTitle = noteBox.value.substring(0, noteBox.value.indexOf("\n")); - - document.getElementById(nameithink).innerText = firstTitle - encryptedTitle = CryptoJS.AES.encrypt(firstTitle, password).toString(); - } - let encryptedText = CryptoJS.AES.encrypt(noteBox.value, password).toString(); - - if (selectedNote === nameithink) { - fetch(remote + "/api/editnote", { - method: "POST", - body: JSON.stringify({ - secretKey: secretkey, - noteId: nameithink, - content: encryptedText, - title: encryptedTitle - }), - headers: { - "Content-Type": "application/json; charset=UTF-8" - } - }) - .then((response) => { - if (response.status === 418) { - displayError("You've ran out of storage... Changes will not be saved until you free up storage!") - } - }) - .catch(() => { - displayError("Failed to save changes, please try again later...") - }) - } - }, waitTime); - }); - } - doStuff() - }); -} - -function updateNotes() { - fetch(remote + "/api/listnotes", { - method: "POST", - body: JSON.stringify({ - secretKey: secretkey - }), - headers: { - "Content-Type": "application/json; charset=UTF-8" - } - }) - .then((response) => { - async function doStuff() { - document.querySelectorAll(".noteButton").forEach((el) => el.remove()); - noteBox.readOnly = true - selectedNote = 0 - noteBox.placeholder = "" - noteBox.value = "" - clearTimeout(timer) - updateWordCount() - renderMarkDown() - - let responseData = await response.json() - for (let i in responseData) { - let noteButton = document.createElement("button"); - noteButton.classList.add("noteButton") - notesDiv.append(noteButton) - - let bytes = CryptoJS.AES.decrypt(responseData[i]["title"], password); - let originalTitle = bytes.toString(CryptoJS.enc.Utf8); - - noteButton.id = responseData[i]["id"] - noteButton.innerText = truncateString(originalTitle, 15) - - noteButton.addEventListener("click", (event) => { - if (event.ctrlKey) { - fetch(remote + "/api/removenote", { - method: "POST", - body: JSON.stringify({ - secretKey: secretkey, - noteId: responseData[i]["id"] - }), - headers: { - "Content-Type": "application/json; charset=UTF-8" - } - }) - .then(() => { - updateNotes() - }) - .catch(() => { - displayError("Something went wrong! Please try again later...") - }) - } else { - selectNote(responseData[i]["id"]) - } - }); - } - document.querySelectorAll(".loadingStuff").forEach((el) => el.remove()); - } - doStuff() - }); -} - -updateNotes() - -newNote.addEventListener("click", () => { - let noteName = "New note" - let encryptedName = CryptoJS.AES.encrypt(noteName, password).toString(CryptoJS.enc.Utf8); - fetch(remote + "/api/newnote", { - method: "POST", - body: JSON.stringify({ - secretKey: secretkey, - noteName: encryptedName, - }), - headers: { - "Content-Type": "application/json; charset=UTF-8" - } - }) - .catch(() => { - displayError("Failed to create new note, please try again later...") - }) - .then((response) => { - if (response.status !== 200) { - updateNotes() - displayError("Failed to create new note (HTTP error code " + response.status + ")") - } else { - updateNotes() - } - }); -}); -function downloadObjectAsJson(exportObj, exportName) { - let dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(exportObj)); - let downloadAnchorNode = document.createElement("a"); - downloadAnchorNode.setAttribute("href", dataStr); - downloadAnchorNode.setAttribute("download", exportName + ".json"); - document.body.appendChild(downloadAnchorNode); - downloadAnchorNode.click(); - downloadAnchorNode.remove(); -} - -function exportNotes() { - fetch(remote + "/api/exportnotes", { - method: "POST", - body: JSON.stringify({ - secretKey: secretkey - }), - headers: { - "Content-Type": "application/json; charset=UTF-8" - } - }) - .then((response) => { - async function doStuff() { - let responseData = await response.json() - for (let i in responseData) { - exportNotes.innerText = "Decrypting " + i + "/" + noteCount - - let bytes = CryptoJS.AES.decrypt(responseData[i]["title"], password); - responseData[i]["title"] = bytes.toString(CryptoJS.enc.Utf8) - - let bytesd = CryptoJS.AES.decrypt(responseData[i]["content"], password); - responseData[i]["content"] = bytesd.toString(CryptoJS.enc.Utf8) - } - let jsonString = JSON.parse(JSON.stringify(responseData)) - downloadObjectAsJson(jsonString, "data") - optionsDiv.classList.add("hidden") - displayError("Exported notes!") - } - doStuff() - }) -} - -function importNotes(plaintextNotes) { - for (let i in plaintextNotes) { - let originalTitle = plaintextNotes[i]["title"]; - let encryptedTitle = CryptoJS.AES.encrypt(originalTitle, password).toString(); - plaintextNotes[i]["title"] = encryptedTitle; - - let originalContent = plaintextNotes[i]["content"]; - let encryptedContent = CryptoJS.AES.encrypt(originalContent, password).toString(); - plaintextNotes[i]["content"] = encryptedContent; - } - return JSON.stringify(plaintextNotes); -} - -function isFirstTimeVisitor() { - if (localStorage.getItem("FIRSTVISIT") === null) { - localStorage.setItem("FIRSTVISIT", "1") - return true; - } else { - return false; - } -} - -function firstNewVersion() { - if (localStorage.getItem("NEWVERSION") === "1.2") { - return false; - } else { - localStorage.setItem("NEWVERSION", "1.2") - return true; - } -} - -function toggleMarkdown() { - if (markdown.style.display === 'none') { - markdown.style.display = 'inherit'; - markdowntoggle = true - renderMarkDown() - } else { - markdown.style.display = 'none'; - markdowntoggle = false - markdown.srcdoc = "" - } -} - -exportNotesButton.addEventListener("click", () => { - exportNotes() -}); - -importFile.addEventListener('change', function(e) { - let fileread = new FileReader() - fileread.addEventListener( - "load", - () => { - let decrypted = JSON.parse(fileread.result) - console.log(decrypted) - let encrypted = importNotes(decrypted) - console.log(encrypted) - }, - false, - ); - - fileread.readAsText(importFile.files[0]) -}) - -removeBox.addEventListener("click", () => { - if (selectedNote === 0) { - displayError("You need to select a note first!") - } else { - fetch(remote + "/api/removenote", { - method: "POST", - body: JSON.stringify({ - secretKey: secretkey, - noteId: selectedNote - }), - headers: { - "Content-Type": "application/json; charset=UTF-8" - } - }) - .then(() => { - updateNotes() - }) - .catch(() => { - displayError("Something went wrong! Please try again later...") - }) - } -}); - -document.addEventListener("DOMContentLoaded", function() { - markdown.srcdoc = "" + marked.parse(noteBox.value) + "" -}); - -if (isFirstTimeVisitor() && /Android|iPhone|iPod/i.test(navigator.userAgent)) { - displayError("To use Burgernotes:\n Swipe Right on a note to open it\n Swipe left in the text boxes to return to notes\n Click on a note to highlight it") -} - -if (firstNewVersion()) { - displayError("What's new in Burgernotes 1.2-1?\nNotes now support live editing\nFixed various bugs and issues in the client") -} - -//waitforedit()