From cfa2e054dfebe26e768a6abb0e3b7cc2c44c0be0 Mon Sep 17 00:00:00 2001 From: Arzumify Date: Mon, 20 May 2024 20:24:43 +0100 Subject: [PATCH] Mobile revamp and overhaulg --- app/index.html | 14 +- index.html | 8 +- static/css/style.css | 81 +- static/js/main.js | 166 +- static/js/main.js.save | 695 ++++++++ static/svg/arrow-back.svg | 1 + static/svg/close.svg | 1 + static/svg/download.svg | 2 +- static/svg/grid.svg | 3535 ------------------------------------- static/svg/list.svg | 2 +- static/svg/markdown.svg | 1 + static/svg/upload.svg | 1 + 12 files changed, 887 insertions(+), 3620 deletions(-) create mode 100644 static/js/main.js.save create mode 100644 static/svg/arrow-back.svg create mode 100644 static/svg/close.svg delete mode 100644 static/svg/grid.svg create mode 100644 static/svg/markdown.svg create mode 100644 static/svg/upload.svg diff --git a/app/index.html b/app/index.html index e9e8b5f..0bb6ad2 100644 --- a/app/index.html +++ b/app/index.html @@ -15,13 +15,14 @@
+

+ -
@@ -42,7 +43,6 @@

Your account

-

Storage


@@ -51,6 +51,7 @@

Account managment

+
@@ -62,6 +63,13 @@
+ -
+
diff --git a/index.html b/index.html index 6b5d1dc..10c3ead 100644 --- a/index.html +++ b/index.html @@ -13,18 +13,14 @@ - Click here

Burgernotes

A simple note-taking service!


Open in your browser - - Download for iOS (TrollApps Repo) - Download for iOS (AltStore) - Download for iOS (TrollStore) - + Download for iOS (IPA) + Download for iOS (WebClip) diff --git a/static/css/style.css b/static/css/style.css index 3947ec5..acd41c4 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -151,6 +151,7 @@ body { border-color: var(--border-color); border-width: 0px; border-bottom-width: 1px; + display: flex; } .bottomBar { @@ -166,6 +167,8 @@ body { border-width: 0px; border-top-width: 1px; display: flex; + text-wrap: nowrap; + overflow-x: scroll; } .bottomBar button { @@ -178,6 +181,16 @@ body { padding-right: 7.5px; } +.bottomBar .markdownButton { + filter: invert(var(--invertdm)); + padding-left: 17.5px; + padding-right: 17.5px; + background-image: url("../../static/svg/markdown.svg"); + background-position: center; + background-repeat: no-repeat; + background-size: 55%; +} + .bottomBar .removeButton { filter: invert(var(--invertdm)); padding-left: 17.5px; @@ -238,14 +251,19 @@ body { } .topBar .logo { - padding-left: 12px; + margin-left: 12px; + background-color: transparent; + border: none; + color: var(--text-color); + white-space: break-spaces; + display: flex; } .topBar .usernameBox { text-align: right; - position: absolute; + margin-left: auto; + margin-right: 16px; cursor: pointer; - right: 12px; } .notesBar { @@ -297,14 +315,14 @@ body { radial-gradient(38px circle at 19px 19px, #eee 50%, transparent 51%), linear-gradient(var(--contrast), var(--contrast)); background-repeat: no-repeat; - background-size: 315px 250px, 315px 180px, 100px 100px, 225px 30px; - background-position: -315px 0, 0 0, 0px 190px, 50px 195px; + background-size: 200% 200%, 100% 200%, 50% 50%, 140% 12%; + background-position: -200% 0, 0 0, 0 76%, 16% 78%; animation: loading 1.5s infinite; } @keyframes loading { to { - background-position: 315px 0, 0 0, 0 190px, 50px 195px; + background-position: 200% 0, 0 0, 0 76%, 16% 78%; } } @@ -333,31 +351,38 @@ body { } .noteBox { - resize: none; position: fixed; right: 0; - top: 55px; - padding: 4px; + top: 50px; border: none; font-size: 16px; color: var(--text-color); background-color: var(--editor); - width: calc(100% - 180px - 7px - 6px); - height: calc(100% - 50px - 6px - 8px - 30px); + width: calc(100% - 180px); + height: calc(100% - 50px - 30px); font-family: "Inter", sans-serif; display: flex; + flex-direction: row; + z-index: -1; +} + +.noteBox.mobile { + flex-direction: column-reverse; } .noteBoxText { + resize: none; background-color: var(--editor); color: var(--text-color); border: none; width: 100%; + height: 100%; font-family: "Inter", sans-serif; } iframe#markdown { width: 100%; + height: 100%; border: none; border-left: solid var(--bar) 1px; } @@ -384,26 +409,26 @@ iframe#markdown { padding: 10px; color: var(--text-color); border-radius: 8px; - min-width: 300px; + width: 300px; z-index: 3; - + display: flex; + flex-direction: column; + max-width: 90%; + max-height: 90%; + overflow-y: scroll; } .optionsDiv button { width: 100%; padding: 10px; - padding-bottom: 13px; - margin-right: 5px; margin-bottom: 7px; - padding-left: 15px; - padding-right: 15px; color: var(--theme-text-color); border: none; text-decoration: none; background-color: var(--theme-color); border-radius: 8px; cursor: pointer; - + font-size: 15px; } .optionsDiv .normalButton { @@ -481,7 +506,10 @@ iframe#markdown { height: 18px; padding-right: 5px; filter: invert(var(--invert)); - transform: translateY(3.25px); + position: absolute; + left: 20px; + scale: 1.3; + transform: translateY(1px); } .optionsDiv .section { @@ -504,19 +532,23 @@ iframe#markdown { margin-bottom: 5px; padding: 10px; height: 35px; + display: flex; + overflow-y: scroll; } .sessionDiv div p { display: inline; - position: absolute; - transform: translateY(-7.5px); + transform: translateY(-20px); + overflow-wrap: anywhere; + margin-left: 10px; } .sessionDiv div button { - position: absolute; + position: static; border-radius: 99px; - right: 15px; - width: 40px; + max-width: 40px; + min-width: 40px; + margin-left: auto; height: 40px; font-size: 16px; transform: translateY(-2px); @@ -526,6 +558,7 @@ iframe#markdown { display: inline; filter: none; height: 100%; + position: static; } /* Sign up/log in div */ diff --git a/static/js/main.js b/static/js/main.js index d8f285d..8c31370 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -26,6 +26,8 @@ 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") @@ -37,7 +39,9 @@ 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") @@ -48,6 +52,7 @@ 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'); @@ -56,17 +61,22 @@ 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 +let mobile = false if (/Android|iPhone|iPod/i.test(navigator.userAgent)) { - noteBox.style.width = "10px"; - notesBar.style.width = "calc(100% - 10px)" - noteBox.readOnly = true + mobile = true + noteBoxDiv.classList.add("mobile"); + noteBoxDiv.style.width = "0px"; + notesBar.style.width = "calc(100% + 7.5px)" + noteBoxDiv.readOnly = true noteBox.style.fontSize = "18px" - noteBox.classList.add("hidden") + noteBoxDiv.classList.add("hidden") let touchstartX, touchstartY, touchendX, touchendY @@ -78,7 +88,9 @@ if (/Android|iPhone|iPod/i.test(navigator.userAgent)) { notesBar.addEventListener("touchend", function (event) { touchendX = event.changedTouches[0].screenX; touchendY = event.changedTouches[0].screenY; - handleGesture(); + if (touchendX < touchstartX - 75) { + handleGesture(); + } }, false); noteBox.addEventListener("touchstart", function (event) { @@ -89,31 +101,54 @@ if (/Android|iPhone|iPod/i.test(navigator.userAgent)) { noteBox.addEventListener("touchend", function (event) { touchendX = event.changedTouches[0].screenX; touchendY = event.changedTouches[0].screenY; - handleGesture(); + if (touchendX > touchstartX + 75) { + handleGesture(); + } else if (touchendX < touchstartX - 75) { + enableMarkdown(); + } }, false); - function handleGesture() { - if (touchendX > touchstartX + 75) { - notesBar.style.width = "calc(100% - 10px)"; - noteBox.style.width = "10px" - if (selectedNote !== 0) { - noteBox.readOnly = true - } - notesDiv.classList.remove("hidden") - noteBox.classList.add("hidden") - newNote.classList.remove("hidden") - } + markdown.addEventListener("touchstart", function (event) { + touchstartX = event.changedTouches[0].screenX; + touchstartY = event.changedTouches[0].screenY; + }, false); - if (touchendX < touchstartX - 75) { - noteBox.style.width = "calc(100% - 30px)"; - notesBar.style.width = "10px" - if (selectedNote !== 0) { - noteBox.readOnly = false - } - notesDiv.classList.add("hidden") - noteBox.classList.remove("hidden") - newNote.classList.add("hidden") + markdown.addEventListener("touchend", function (event) { + touchendX = event.changedTouches[0].screenX; + touchendY = event.changedTouches[0].screenY; + if (touchendX > touchstartX + 75) { + disableMarkdown(); + } else if (touchendX < touchstartX - 75) { + disableMarkdown(); } + }, 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") } } @@ -145,7 +180,7 @@ function updateFont() { noteBox.style.fontSize = currentFontSize + "px" textSizeBox.innerText = currentFontSize + "px" if (markdowntoggle) { - markdown.srcdoc = "" + marked.parse(noteBox.value) + ""; + markdown.srcdoc = "" + marked.parse(noteBox.value) + ""; } } @@ -270,6 +305,10 @@ deleteMyAccountButton.addEventListener("click", () => { }) } }); +importNotesButton.addEventListener("click", () => { + optionsDiv.classList.add("hidden") + importNotesDiv.classList.remove("hidden") +}); sessionManagerButton.addEventListener("click", () => { optionsDiv.classList.add("hidden") sessionManagerDiv.classList.remove("hidden") @@ -344,6 +383,10 @@ sessionManagerButton.addEventListener("click", () => { doStuff() }); }); +exitImportThing.addEventListener("click", () => { + optionsDiv.classList.remove("hidden") + importNotesDiv.classList.add("hidden") +}); exitSessionsThing.addEventListener("click", () => { optionsDiv.classList.remove("hidden") sessionManagerDiv.classList.add("hidden") @@ -361,7 +404,7 @@ function updateWordCount() { function renderMarkDown() { if (markdowntoggle) { - markdown.srcdoc = "" + marked.parse(noteBox.value) + "" + markdown.srcdoc = "" + marked.parse(noteBox.value) + "" } } @@ -388,6 +431,9 @@ function selectNote(nameithink) { }) .then((response) => { selectedNote = nameithink + if (mobile) { + handleGesture() + } noteBox.readOnly = false noteBox.placeholder = "Type something!" @@ -564,24 +610,25 @@ function exportNotes() { responseData[i]["content"] = bytesd.toString(CryptoJS.enc.Utf8) } let jsonString = JSON.parse(JSON.stringify(responseData)) - - exportNotesButton.innerText = "Export notes" downloadObjectAsJson(jsonString, "data") optionsDiv.classList.add("hidden") displayError("Exported notes!") - } doStuff() }) } -function isFirstTimeVisitor() { - if (localStorage.getItem("FIRSTVISIT") === null) { - localStorage.setItem("FIRSTVISIT", "1") - return true; - } else { - return false; +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 firstNewVersion() { @@ -595,21 +642,44 @@ function firstNewVersion() { function toggleMarkdown() { if (markdown.style.display === 'none') { - markdown.style.display = 'inherit'; - markdowntoggle = true - renderMarkDown() + enableMarkdown() } else { - markdown.style.display = 'none'; - markdowntoggle = false - markdown.srcdoc = "" + disableMarkdown() } } +function enableMarkdown() { + markdown.style.display = 'inherit'; + markdowntoggle = true + renderMarkDown() +} + +function disableMarkdown() { + markdown.style.display = 'none'; + markdowntoggle = false + markdown.srcdoc = "" +} + exportNotesButton.addEventListener("click", () => { - exportNotesButton.innerText = "Downloading..." 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!") @@ -634,15 +704,11 @@ removeBox.addEventListener("click", () => { }); document.addEventListener("DOMContentLoaded", function() { - markdown.srcdoc = "" + marked.parse(noteBox.value) + "" + 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() +//waitforedit() diff --git a/static/js/main.js.save b/static/js/main.js.save new file mode 100644 index 0000000..1e68bf0 --- /dev/null +++ b/static/js/main.js.save @@ -0,0 +1,695 @@ +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() diff --git a/static/svg/arrow-back.svg b/static/svg/arrow-back.svg new file mode 100644 index 0000000..fb227fa --- /dev/null +++ b/static/svg/arrow-back.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/svg/close.svg b/static/svg/close.svg new file mode 100644 index 0000000..707309a --- /dev/null +++ b/static/svg/close.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/svg/download.svg b/static/svg/download.svg index eb90940..72054d2 100644 --- a/static/svg/download.svg +++ b/static/svg/download.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/static/svg/grid.svg b/static/svg/grid.svg deleted file mode 100644 index fc91a30..0000000 --- a/static/svg/grid.svg +++ /dev/null @@ -1,3535 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/svg/list.svg b/static/svg/list.svg index 339b1f5..9a07b29 100644 --- a/static/svg/list.svg +++ b/static/svg/list.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/static/svg/markdown.svg b/static/svg/markdown.svg new file mode 100644 index 0000000..5090f00 --- /dev/null +++ b/static/svg/markdown.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/svg/upload.svg b/static/svg/upload.svg new file mode 100644 index 0000000..251fd99 --- /dev/null +++ b/static/svg/upload.svg @@ -0,0 +1 @@ + \ No newline at end of file