diff --git a/main b/main index a04dfa1..421c33b 100644 --- a/main +++ b/main @@ -438,6 +438,19 @@ def apisessionsremove(): else: return {}, 422 + +@app.route("/api/submitfeedback", methods=("GET", "POST")) +def apisubmitfeedback(): + if request.method == "POST": + data = request.get_json() + secretKey = data["secretKey"] + feedback = data["feedback"] + + print("feedback: " + feedback) + + return {}, 200 + + @app.route("/listusers/", methods=("GET", "POST")) def listusers(secretkey): if secretkey == SECRET_KEY: diff --git a/static/css/style.css b/static/css/style.css index e6451f6..b9dcb3e 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -13,7 +13,8 @@ --note-button-text-color: #ffffff; --unselected-note-button-text-color: #000000; --option-background: #ffffff; - --invert: 100% + --invert: 100%; + --bottomBarHover: #e4e4e4; } /* dark mode */ @@ -32,48 +33,68 @@ --note-button-text-color: #ffffff; --unselected-note-button-text-color: #ffffff; --option-background: #202124; - --invert: 100% + --invert: 100%; + --bottomBarHover: #e4e4e4; } + .startDiv p { color: white !important; } + .topBar p { color: white !important; } + .newNote { color: white !important; } + .newNote img { filter: invert(100%) } + #errorDiv p { color: white !important; } + .optionsCoverDiv p { color: white !important; } + .burgerSession img { filter: invert(100%) !important } - .feature h3, p { + + .feature h3, + p { color: black !important; } + .links a { color: white !important; } + .inoutdiv p { color: white !important; } + .inoutdiv a { color: #969696 !important; } + .inoutdiv input { color: white; background-color: #202124; } } -p, h1, h2, h3, h4, h5, h6 { +p, +h1, +h2, +h3, +h4, +h5, +h6 { color: var(--text-color); } @@ -97,6 +118,48 @@ body { border-bottom-width: 1px; } +.bottomBar { + position: fixed; + width: 100%; + height: 29px; + bottom: 0; + + background-color: var(--bar); + + border: solid; + border-color: var(--border-color); + border-width: 0px; + border-top-width: 1px; +} + +.bottomBar button { + background-color: rgba(0, 0, 0, 0); + color: var(--text-color); + height: 100%; + border: none; + font-size: 14px; + padding-left: 7.5px; + padding-right: 7.5px; +} + +.bottomBar .removeButton { + padding-left: 17.5px; + padding-right: 17.5px; + transform: translateY(-5px); + background-image: url("/static/svg/delete.svg"); + background-position: center; + background-repeat: no-repeat; + background-size: 55%; +} + +.bottomBar button:hover { + background-color: var(--bottomBarHover); +} + +.bottomBar .right { + float: right; +} + .burgerDropdown { position: fixed; z-index: 2; @@ -140,7 +203,6 @@ body { .topBar .logo { padding-left: 12px; - cursor: pointer; } .topBar .usernameBox { @@ -153,8 +215,8 @@ body { .notesBar { position: fixed; width: 180px; - bottom: 0; - height: calc(100% - 50px - 1px); + top: 50px; + height: calc(100% - 50px - 30px - 1px); background-color: var(--bar); @@ -189,6 +251,7 @@ body { font-size: 15px; text-align: left; + cursor: pointer; } .notesBar .loadingStuff { @@ -227,6 +290,7 @@ body { font-size: 16px; margin-bottom: 5px; + cursor: pointer; } .notesBar .newNote img { @@ -239,14 +303,14 @@ body { resize: none; position: fixed; right: 0; - bottom: 0; + top: 55px; padding: 4px; 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); + height: calc(100% - 50px - 6px - 8px - 30px); font-family: "Inter", sans-serif; } @@ -288,6 +352,7 @@ body { text-decoration: none; background-color: var(--theme-color); border-radius: 8px; + cursor: pointer; } .optionsDiv .normalButton { @@ -311,6 +376,7 @@ body { border-width: 1px; border-radius: 8px; } + .optionsDiv .mfacheckbox { display: inline; margin: 0; @@ -320,6 +386,7 @@ body { height: 17px; width: 17px; } + .optionsDiv input:focus { outline: 0; border-color: var(--theme-color); diff --git a/static/js/main.js b/static/js/main.js index 4d92753..d021ae5 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -131,9 +131,10 @@ closeErrorButton.addEventListener("click", (event) => { optionsCoverDiv.classList.add("hidden") }); -function displayPrompt(message, callback) { +function displayPrompt(message, placeholdertext, callback) { errorMessageThing.innerText = message errorInput.value = "" + errorInput.placeholder = placeholdertext closeErrorButton.addEventListener("click", (event) => { if (callback) { @@ -175,6 +176,29 @@ closeErrorButton.addEventListener("click", (event) => { cancelErrorButton.classList.add("hidden") }); +function updateFont() { + let currentFontSize = localStorage.getItem("SETTING-fontsize") + noteBox.style.fontSize = currentFontSize + "px" + textSizeBox.innerText = currentFontSize + "px" +} + +if (localStorage.getItem("SETTING-fontsize") === null) { + localStorage.setItem("SETTING-fontsize", "16") + updateFont() +} else { + updateFont() +} + +textPlusBox.addEventListener("click", (event) => { + localStorage.setItem("SETTING-fontsize", String(Number(localStorage.getItem("SETTING-fontsize")) + Number(1))) + updateFont() +}); +textMinusBox.addEventListener("click", (event) => { + localStorage.setItem("SETTING-fontsize", String(Number(localStorage.getItem("SETTING-fontsize")) - Number(1))) + updateFont() +}); + + function updateUserInfo() { fetch("/api/userinfo", { method: "POST", @@ -238,7 +262,7 @@ deleteMyAccountButton.addEventListener("click", (event) => { if (response.status == 200) { window.location.href = "/api/logout" } else { - displayError("failed to delete account (" + String(response.status) + ")") + displayError("failed to delete account (HTTP error code " + response.status + ")") } }) } @@ -336,6 +360,14 @@ exitMfaThing.addEventListener("click", (event) => { updateUserInfo() +function updateWordCount() { + let wordCount = noteBox.value.split(" ").length + if (wordCount == 1) { + wordCount = 0 + } + wordCountBox.innerText = wordCount + " words" +} + function selectNote(nameithink) { document.querySelectorAll(".noteButton").forEach((el) => el.classList.remove("selected")); let thingArray = Array.from(document.querySelectorAll(".noteButton")).find(el => el.id == nameithink); @@ -370,8 +402,10 @@ function selectNote(nameithink) { let originalText = bytes.toString(CryptoJS.enc.Utf8); noteBox.value = originalText + updateWordCount() noteBox.addEventListener("input", (event) => { + updateWordCount() clearTimeout(timer); timer = setTimeout(() => { let encryptedText = CryptoJS.AES.encrypt(noteBox.value, password).toString(); @@ -424,6 +458,7 @@ function updateNotes() { noteBox.placeholder = "" noteBox.value = "" clearTimeout(timer) + updateWordCount() let responseData = await response.json() for (let i in responseData) { @@ -470,7 +505,7 @@ function updateNotes() { updateNotes() newNote.addEventListener("click", (event) => { - let noteName = displayPrompt("note name? :3", burgerFunction) + let noteName = displayPrompt("note name? :3", "e.g. shopping list", burgerFunction) function burgerFunction(noteName) { if (noteName != null) { let encryptedName = CryptoJS.AES.encrypt(noteName, password).toString(); @@ -487,11 +522,10 @@ newNote.addEventListener("click", (event) => { .catch((error) => { displayError("failed to create new note, please try again later") }) - .then((response) => response) .then((response) => { if (response.status !== 200) { updateNotes() - displayError("something went wrong while creating note") + displayError("failed to create new note (HTTP error code " + response.status + ")") } else { updateNotes() } @@ -552,4 +586,56 @@ function exportNotes() { exportNotesButton.addEventListener("click", (event) => { exportNotesButton.innerText = "downloading.." exportNotes() +}); + +sendFeedbackButton.addEventListener("click", (event) => { + let noteName = displayPrompt("Feedback:", "Write your feedback here. Don't include personal info.", burgerFunction) + function burgerFunction(feedbackText) { + if (feedbackText != null) { + fetch("/api/submitfeedback", { + method: "POST", + body: JSON.stringify({ + secretKey: secretkey, + feedback: feedbackText + }), + headers: { + "Content-type": "application/json; charset=UTF-8" + } + }) + .catch((error) => { + displayError("failed to submit feedback, please try again later") + }) + .then((response) => { + if (response.status == 200) { + displayError("Thank you for submitting feedback!") + } else { + displayError("failed to submit feedback (HTTP error code " + response.status + ")") + } + }); + }; + } +}); + +removeBox.addEventListener("click", (event) => { + if (selectedNote == 0) { + displayError("you need to select a note first!") + } else { + fetch("/api/removenote", { + method: "POST", + body: JSON.stringify({ + secretKey: secretkey, + noteId: selectedNote + }), + headers: { + "Content-type": "application/json; charset=UTF-8" + } + }) + .then((response) => response) + .then((response) => { + updateNotes() + }) + .catch((error) => { + displayError("something went wrong! please try again later") + }) + } }); \ No newline at end of file diff --git a/static/mainimg.png b/static/mainimg.png deleted file mode 100644 index c576833..0000000 Binary files a/static/mainimg.png and /dev/null differ diff --git a/static/svg/delete.svg b/static/svg/delete.svg new file mode 100644 index 0000000..560d174 --- /dev/null +++ b/static/svg/delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/app.html b/templates/app.html index 0bfd451..168711f 100644 --- a/templates/app.html +++ b/templates/app.html @@ -18,6 +18,15 @@

+
+ + + + + + +
+
@@ -70,7 +79,7 @@