diff --git a/src/script.js b/src/script.js index 56095ca..1926eb5 100755 --- a/src/script.js +++ b/src/script.js @@ -21,6 +21,9 @@ const okBadge = document.getElementById('ok') const sadBadge = document.getElementById('sad') const pageTitle = document.head.querySelector('title') const pageH1 = document.body.querySelector('h1') +const editor = document.getElementById('text-editor') +const crossIcon = document.getElementById('quitAll') +const toast = document.getElementById('toast') // helpers let allA @@ -63,19 +66,28 @@ function browseTo (href, flickerDone, skipHistory) { } window.onClickLink = e => { + storeLastArrowSrc(e.target.href) + + // follow dirs if (e.target.innerText.endsWith('/')) { - storeLastArrowSrc(e.target.href) browseTo(e.target.href) return false - } else if (picsOn(true, e.target.href)) { - return false } - return true + + // try dynamic, otherwise just click item + restoreCursorPos() + if (picsOn(true) || picsNav(true) || padOn(true)) { + return false + } else { + return true + } } const refresh = () => browseTo(location.href, true) -const prevPage = (url, skipHistory) => picsOff() || browseTo(url, false, skipHistory) +const softPrev = () => history.replaceState({}, '', decodeURI(location.href.split('/').slice(0, -1).join('/') + '/')) + +const prevPage = (url, skipHistory) => window.quitAll() || browseTo(url, false, skipHistory) window.onpopstate = () => prevPage(location.href, true) @@ -188,7 +200,7 @@ upGrid.ondragleave = e => { } document.ondragenter = e => { - if (isPicMode()) { return } + if (isEditorMode() || isPicMode()) { return } cancelDefault(e) resetBackgroundLinks() @@ -233,6 +245,89 @@ document.ondrop = e => { return false } +// pad +function saveText (cbok, cberr) { + const formData = new FormData() + formData.append(fileEdited, editor.innerText) + fetch(location.origin + '/post', { + method: 'POST', + credentials: 'include', + body: formData, + headers: new Headers({ "gossa-path": encodeURIComponent(decodeURI(location.pathname)) }) + }).then(() => { + toast.style.display = "none" + cbok && cbok() + }).catch(() => { + toast.style.display = "block" + cberr && cberr() + }) +} + +const isEditorMode = () => editor.style.display === "block" +const textTypes = ['.txt', '.rtf', '.md', '.log'] +const isTextFile = src => src && textTypes.find(type => src.toLocaleLowerCase().includes(type)) +let fileEdited + +window.padOff = function () { + if (!isEditorMode()) { return } + + saveText(() => { + clearInterval(window.padTimer) + window.onbeforeunload = null + editor.style.display = crossIcon.style.display = "none" + softPrev() + refresh() + }, () => { + alert('cant save!\r\nleave window open to resume saving\r\nwhen connection back up') + }) + + return true +} + +async function padOn (ifTxtSelected) { + const a = getASelected() + if (ifTxtSelected && !isTextFile(a.innerText)) { + return + } + + if (isTextFile(a.innerText)) { + try { + fileEdited = a.innerText + const f = await fetch(a.href, { + credentials: 'include', + headers: new Headers({ + 'pragma': 'no-cache', + 'cache-control': 'no-cache' + }) + }) + editor.innerText = await f.text() + } catch (error) { + return alert('cant read file') + } + } else { + fileEdited = prompt('new filename', '') + if (!fileEdited) { return } + fileEdited = isTextFile(fileEdited) ? fileEdited : fileEdited + '.txt' + editor.innerText = '' + saveText() + storeLastArrowSrc(location.href + fileEdited) + } + + console.log('editing file', fileEdited) + editor.style.display = crossIcon.style.display = "block" + editor.focus() + history.replaceState({}, '', encodeURI(fileEdited)) + window.onbeforeunload = warningMsg + window.padTimer = setInterval(saveText, 5000) + return true +} + +window.padOn = padOn +window.padOff = padOff + +// quit pictures or editor +window.quitAll = () => picsOff() || padOff() + // Mkdir icon window.mkdirBtn = function () { const folder = prompt('new folder name', '') @@ -341,8 +436,8 @@ function setImage () { history.replaceState({}, '', encodeURI(src.split('/').pop())) } -function picsOn (ifImgSelected, href) { - href = href || getASelected().href +function picsOn (ifImgSelected) { + const href = getASelected().href if (isPicMode() || (ifImgSelected && !isPic(href))) { return false @@ -353,20 +448,19 @@ function picsOn (ifImgSelected, href) { } setImage() + crossIcon.style.display = "block" pics.style.display = 'flex' return true } +window.picsOn = picsOn function picsOff (skip) { if (!isPicMode()) { return } - - history.replaceState({}, '', encodeURI(location.href.split('/').slice(0, -1).join('/') + '/')) - pics.style.display = 'none' + softPrev() + pics.style.display = crossIcon.style.display = 'none' return true } -window.picsToggle = () => isPicMode() ? picsOff() : picsOn() - function picsNav (down) { if (!isPicMode()) { return false } @@ -419,6 +513,11 @@ function setCursorToClosestTyped () { } document.body.addEventListener('keydown', e => { + if (isEditorMode()) { + if (e.code === 'Escape') { padOff() } + return + } + switch (e.code) { case 'Tab': case 'ArrowDown': @@ -429,13 +528,16 @@ document.body.addEventListener('keydown', e => { case 'Enter': case 'ArrowRight': - return prevent(e) || picsOn(true) || picsNav(true) || getASelected().click() + return prevent(e) || getASelected().click() case 'ArrowLeft': return prevent(e) || picsNav(false) || prevPage(location.href + '../') case 'Escape': return prevent(e) || resetBackgroundLinks() || picsOff() + + case 'Delete': + return prevent(e) || isPicMode() || window.rm(e) } // Ctrl keys diff --git a/src/style.css b/src/style.css index 56e87ca..39a4bdd 100644 --- a/src/style.css +++ b/src/style.css @@ -119,11 +119,20 @@ h1 { margin-left: 5px; } +#toast { + top: 7px; + position: absolute; + right: 70px; + font-style: italic; + width: intrinsic; + width: -moz-max-content; + width: -webkit-max-content; +} -#picsToggleCinema { +#quitAll { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAoElEQVRYhe2Wuw3AIAxEbZRRMwFlJiBLMCBDcClCCwq2gRRc7/cO8RFEOzt/DAAPIABwBixXWL5nKOBN1JQo8lhYQTooKqFmaAAWCxCDzOQSoLm8BzxM/kUwXN4STZM3SsyTV0qo5HMaW2bpFiw9hEuv4dKHqAdsXkICNCuhAalLWKxCxcDEL9lRmU1EdBPRxcxZWoCZM4Cz8JKUs7MzNA81r4TL7qAyXAAAAABJRU5ErkJggg=="); position: fixed; - left: 20px; + right: 20px; top: 20px; width: 2em; height: 2em; @@ -179,6 +188,26 @@ h1 { background-color: rgba(123, 123, 123, 0.2) } + +#text-editor { + height: 100%; + background-color: #2d3436; + position: fixed; + left: 0px; + right: 0px; + top: 0px; + bottom: 0px; + z-index: 100; + overflow-y: auto; + word-wrap: anywhere; + padding: 20px; + padding-bottom: 0px; + border-bottom: 10px; + width: -moz-available; + width: -webkit-fill-available; +} + + #pics { user-select: none; -webkit-tap-highlight-color: transparent; @@ -238,6 +267,10 @@ h1 { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAElBMVEUAAAAAAAAAgACAgID////AwMAbJqpVAAAAAXRSTlMAQObYZgAAAAFiS0dEBI9o2VEAAAAHdElNRQfiBhoANRyRjMyLAAAArElEQVQoz22R0Q3EIAiGNbfAeU4gad+9sMGFLtC4/yyngBaa+tCELz+fFkJ4PimltyljAoCSrvoDfBbRGkC74qyh3AIauQIacaCajo1+ANmARqcHRP2T61LsdIgkWoUFrICCC7Bigo1OUUzQK1GslkaiGIDfsZMoICvokcODXRTjpXpvU0W9/T5WP7GhcDNF9EPN3GH2ooEQvrI51EAIL+y7zbgCg/Cx68eZ/wNuLjeFQzbY1AAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxOC0wNi0yNlQwMDo1MzoyOC0wNDowMGvaoe4AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTgtMDYtMjZUMDA6NTM6MjgtMDQ6MDAahxlSAAAAAElFTkSuQmCC"); } +.icon-large-pad { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAGFBMVEUAAAAAAACAgID////AwMAAAL8AAP///wCsLlssAAAAAXRSTlMAQObYZgAAAAFiS0dEAxEMTPIAAAAHdElNRQfiBhoAOCQMIApYAAAAvUlEQVQoz22Ryw7CIBREqYl7xlb3Pj7APpQ1iaZbXcjaxBTXhCi/bx+2XBomd8PJDDcMjCUc43DWab8rpunIIi/TcbYyCkovKdltBpbPGVAtuHjJqz6GDvUOI1d9DiPqpcMt6tsEkXyjwy04NWEkhWooEMD6wUnEGuBOHidEBXACrKsNuuf/A7Wr3AekD2trB1JQe4MzUvqIK4BMeofIV0OFIzBpOYG+qmxoLNJ6DNCSow528I6s//4EXu3xB1FNX4O6vHKSAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE4LTA2LTI2VDAwOjU2OjM2LTA0OjAwEWYRaQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxOC0wNi0yNlQwMDo1NjozNi0wNDowMGA7qdUAAAAASUVORK5CYII="); +} + .icon-large-upload { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAXVBMVEUAAAAzzDPM/8z///8z/2YzmQAzZgAzZv8Amf8AAAAzzP+ZzP8AgADM//8z//8AMwAzzGaZmQD4+Pj//5kAZgD/zGYzmTP/zJmAgAAzMwDMZjPMmTP//wBmMwDwyqYv7S31AAAAAXRSTlMAQObYZgAAAAFiS0dEAxEMTPIAAAAHdElNRQfiBhoAOCALTc5BAAAB3klEQVRIx5WUCZKDIBBFAQXEbTTRQbPM/Y85TQMKClm+piplvcdv0YSQINSFfBQAWcHKsqSUc/EBbmnAgedCyje8Xxxxw782LI+zCPORVSWlesPj4qKqETdC3nA8R76uasBr+cJoCmHGdzwadSsxaaPpCiHcPJ6naLQqw3d9J2jEix/AW540msIYZnMMX/et5xnPCNjQC+SrvoUvlh8GzlWW73tcH+YRdk+tIFRqoq6jwPf+Diph5mcjJiEAThkNeQb4MF6uJmej6ShjrJymnR+GjU8YDfLwJk2Wr9DY+LNBi4DHSMHGOcjo418k5Es+TY6vxO94SUU5oUQDXg1QpDlEOBFEu3MOjJKCsfioUNBe0fNqBcfTZaMWdYkKXMUmIF8uAbSo0zx7A+GH9SPDwNqegWD4Oc6yx1dsAuHw61ku2ShsCRoImY4T6fCYlZ0oEMjEl8NG7rd6nVd9bAAjbrCOb1i1PgkkELR7VnpveCV4OLiH1W9dpiGaR5sGH5IQjvPgJKn/Disc9ke755UXzjQ23NTdJRb0NZ5ne16Pp8+HDSEYCPbFvMb0cfuTu3QwcoKOnpf+umFPRpjzSQpkzYe8z/OuPqC+E+5hbhAVXUmsGebx93eLLjzf1L1i/gHK3l4JVuA9nAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxOC0wNi0yNlQwMDo1NjozMi0wNDowMOUpNXoAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTgtMDYtMjZUMDA6NTY6MzItMDQ6MDCUdI3GAAAAAElFTkSuQmCC"); margin-bottom: 3px; diff --git a/src/template.go b/src/template.go index 9336464..de92730 100644 --- a/src/template.go +++ b/src/template.go @@ -18,6 +18,8 @@
+ +