From 8b6cd9c0582ac3657b903cb5b526ab44cdae8bca Mon Sep 17 00:00:00 2001 From: fvanroie Date: Sat, 20 Apr 2024 22:30:33 +0200 Subject: [PATCH 01/55] Allow larger btnmap --- src/hasp/hasp_attribute.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hasp/hasp_attribute.cpp b/src/hasp/hasp_attribute.cpp index a3fd9f29..b8b42eca 100644 --- a/src/hasp/hasp_attribute.cpp +++ b/src/hasp/hasp_attribute.cpp @@ -98,7 +98,7 @@ const char** my_map_create(const char* payload) { // Reserve memory for JsonDocument // StaticJsonDocument<1024> map_doc; - size_t maxsize = (128u * ((strlen(payload) / 128) + 1)) + 256; + size_t maxsize = (128u * ((strlen(payload) / 128) + 1)) + 1024; DynamicJsonDocument map_doc(maxsize); DeserializationError jsonError = deserializeJson(map_doc, payload); From 660a8bb512d50d218334f8efe72636381e0b56ae Mon Sep 17 00:00:00 2001 From: fvanroie Date: Mon, 13 May 2024 13:44:00 +0200 Subject: [PATCH 02/55] Update ace.js to 1.33.2 --- data/edit.htm | 2 +- data/script.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/edit.htm b/data/edit.htm index 4143e51c..a644194a 100644 --- a/data/edit.htm +++ b/data/edit.htm @@ -1 +1 @@ -openHASP File Editor
L:
  • New File
  • Upload Files
  • Edit
  • Preview
  • Download
  • Delete
\ No newline at end of file +openHASP File Editor
L:
  • New File
  • Upload Files
  • Edit
  • Preview
  • Download
  • Delete
\ No newline at end of file diff --git a/data/script.js b/data/script.js index 5e9dc496..2578aad1 100644 --- a/data/script.js +++ b/data/script.js @@ -1 +1 @@ -var ctx_el;function _(e){return document.getElementById(e)}function hidectx(){_("ctx").style.display="none",ctx_el&&ctx_el.classList.remove("selitem"),ctx_el=void 0}function doesFontExist(e){var t=document.createElement("canvas"),n=t.getContext("2d"),o="abcdefghijklmnopqrstuvwxyz0123456789";n.font="72px monospace";var a=n.measureText(o).width;return n.font="72px '"+e+"', monospace",t=null,n.measureText(o).width!=a}function createEditor(e,t,n,o,a){function i(e){let t=/(?:\.([^.]+))?$/.exec(e)[1];if(void 0!==typeof t)switch(t){case"htm":case"html":return"html";case"js":return"javascript";case"cmd":case"json":case"jsonl":return"json";case"css":case"svg":case"xml":return t}return"plain_text"}void 0===n&&(n=i(t)),void 0===a&&(a="text/"+n);["basePath","modePath","themePath"].forEach((e=>{ace.config.set(e,"https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.8")}));var c=ace.edit(e,{useWorker:!1,wrap:!0,indentedSoftWrap:!1,showPrintMargin:!1,highlightGutterLine:!0,useSoftTabs:!0,tabSize:2});c.setFontSize(parseFloat(getComputedStyle(document.documentElement).fontSize)),c.setReadOnly(!0),c.getSession().setUndoManager(new ace.UndoManager),void 0===o&&(o=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"monokai":"textmate");var s=_("save"),l=_("undo"),r=_("redo"),d=_("cut"),m=_("copy"),u=_("paste"),p=_("font"),f=_("fontsize"),g="none"!==_(e).display;f.value=parseFloat(c.getFontSize()).toFixed(1),p.onchange=function(){c.setOption("fontFamily","'"+p.value+"',monospace")},f.onchange=function(){var e=parseFloat(f.value);!isNaN(e)&&e>=9&&e<=40&&c.setFontSize(e),f.value=parseFloat(c.getFontSize()).toFixed(1)};function h(){let e=!g||c.session.getSelection().isEmpty();d.disabled=e,m.disabled=e}function y(){let e=c.session.getUndoManager();s.disabled=!g||e.isClean(),l.disabled=!g||!e.hasUndo(),r.disabled=!g||!e.hasRedo()}function v(){if(void 0===t)return;const e=function(e){var t=e.getValue();try{var n=JSON.parse(t);return JSON.stringify(n)}catch(e){return t+""}}(c),n=new FormData;n.append("data",new Blob([e],{type:a}),t),fetch("/edit",{method:"POST",body:n}).then((e=>e.ok?e.text().then((e=>{console.log("Save OK /edit "+e)})):e.text().then((e=>{throw console.log("Save FAIL /edit"),new Error(e)})))).then((e=>{console.log(e),generateToast({message:"Saved "+t,background:"#ddd",color:"#000"})})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{y()}))}function x(){var e=c.getCopyText();if(window.clipboardData&&window.clipboardData.setData)return window.clipboardData.setData("Text",e);if(document.queryCommandSupported&&document.queryCommandSupported("copy")){c.focus();try{return document.execCommand("copy")}catch(t){return console.warn("Copy to clipboard failed.",t),prompt("Copy to clipboard: Ctrl+C, Enter",e)}}}function w(e){_("name").innerHTML=e;fetch(e).then((t=>t.ok?(console.log("OK "+e),t.text()):t.text().then((e=>{throw console.log("ERROR "+url),new Error(e)})))).then((e=>{try{var t=JSON.parse(e);c.setValue(JSON.stringify(t,null,4)),console.log("parse json OK")}catch(t){c.setValue(e),console.log("parse json FAIL")}null!==_("editor")&&(_("editor").style.display="block"),null!==_("preview")&&(_("preview").style.display="none"),g=!0,c.setReadOnly(!1),c.focus(),y()})).catch((e=>{console.log(e),alert(e),c.setReadOnly(!0)})).finally((()=>{c.resize(!0),c.scrollToLine(1,!0,!0,(function(){})),c.gotoLine(1,0,!0),c.clearSelection(),c.session.getUndoManager().reset()}))}return["Courier New","Monaco","Lucida Console","Monospace","ui-monospace","Roboto Mono","Inconsolata","IBM Plex Mono","Space Mono","PT Mono","Ubuntu Mono","Nanum Gothic Coding","Cousine","Fira Mono","Share Tech Mono","Courier Prime","Anonymous Pro","Cutive Mono","Overpass Mono","Fira Code","VT323","DM Mono","Oxygen Mono","Nova Mono","B612 Mono","Spline Sans Mono","Noto Sans Mono","Major Mono Display","Azeret Mono","Red Hat Mono","Syne Mono","Xanh Mono"].sort().forEach((function(e,t){if(doesFontExist(e)){var n=document.createElement("option");n.text=e,p.add(n)}})),null!==s&&null!==l&&null!==r&&c.on("input",y),c.session.selection.on("changeCursor",h),s.onclick=v,l.onclick=e=>{c.undo()&&c.focus()},r.onclick=e=>{c.redo()&&c.focus()},d.onclick=e=>{x()&&c.execCommand("cut")},m.onclick=e=>{x()&&c.execCommand("copy")},u.onclick=function(){try{navigator.clipboard.readText().then((e=>{c.execCommand("paste",e)})).catch((e=>{u.disabled=!0}))}catch{u.disabled=!0}},c.loadUrl=(e,o)=>{n=i(t=e+o),a="text/"+n,"plain"!==n&&c.getSession().setMode("ace/mode/"+n),w(e+o)},c.hide=()=>{g=!1,y(),h(),_("editor").style.display="none"},"plain"!==n&&c.getSession().setMode("ace/mode/"+n),c.setTheme("ace/theme/"+o),c.$blockScrolling=1/0,c.commands.addCommand({name:"save",bindKey:{win:"Ctrl-S",mac:"Command-S"},exec:v,readOnly:!1}),c.commands.addCommand({name:"undo",bindKey:{win:"Ctrl-Z",mac:"Command-Z"},exec:function(){c.undo()}}),c.commands.addCommand({name:"redo",bindKey:{win:"Ctrl-Y",mac:"Command-Y"},exec:function(){c.redo()}}),void 0!==t&&w(t),c.resize(),c}function uploadFileAsync(e,t,n,o,a,i){fetchData("/edit","POST",e).then((e=>{generateToast({message:"Upload "+n+"/"+o+" "+t+" done.",background:"#ddd",color:"#000"}),n==o&&listFiles(a,i)}))}function doUpload(e,t){const n=_("upload"),o=n.files.length;if(0!==o)for(let a=0;a=0}function isText(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"txt":case"cmd":case"json":case"jsonl":case"htm":case"html":case"js":case"c":case"cpp":case"css":case"svg":case"xml":return!0}return!1}function isImage(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"bmp":case"png":case"jpg":case"gif":case"svg":return!0}return!1}function isAudio(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"wav":case"mp3":case"aac":case"m4a":case"wma":return!0}return!1}function icon(e){if(isFolder(e))return"dir";if(isImage(e))return"image";if(isAudio(e))return"audio";var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"cmd":case"css":case"json":case"jsonl":case"ttf":return t;case"zip":case"gz":return"zip";case"html":case"htm":return"html"}return"file"}function preview(e,t){if(isImage(e)){let n=t+e.name;const o=_("preview");o.innerHTML='',o.style.display="block",ace.edit("editor").hide(),_("name").innerHTML=n}}function edit(e,t){isText(e)&&(ace.edit("editor").loadUrl(t,e.name),_("preview").style.display="none")}function url(e,t){console.log("click "+t+e.name),isImage(e)?preview(e,t):isText(e)&&edit(e,t)}async function fetchData(e,t,n,o){await fetch(e,{method:t,body:n}).then((n=>n.ok?(console.log(t+" OK "+e),n.text()):n.text().then((n=>{throw console.log(t+" FAIL "+e),new Error(n)})))).then((e=>{o&&o.remove(),console.log(e)})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{}))}function download(e,t){console.log("download "+t+e.name),document.getElementById("download-frame").src=t+e.name+"?download=true"}function remove(e,t,n){let o=t+e.name;isFolder(e)&&(o+="/"),console.log("remove "+o);const a=new FormData;a.append("path",o),fetchData("/edit","DELETE",a,n)}function create(e,t,n){var o=window.prompt("Create File in "+e,"");if(null==o||""==o||o.includes("/"))return;const a=new FormData;a.append("path",e+o),fetchData("/edit","PUT",a),fetch("/api/files/").then((e=>e.json())).then((o=>{t&&t.remove(),listFiles(n,e),console.log(o)}))}function upload(e,t){_("upload").onchange=()=>{doUpload(e,t)},_("upload").click()}function ctx(e,t,n,o){e.preventDefault(),ctx_el=o;let a,i=isFolder(t),c=_("ctx");c.style.display="block",a=c.getElementsByTagName("li")[0],a.onclick=i?function(){hidectx(),create(n+t.name+"/",o.children.item(1),o)}:function(){hidectx(),create(n,o.parentNode,o.parentNode.parentNode)},a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[1],i&&(a.onclick=function(){hidectx(),upload(o,n+t.name+"/")}),a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[2],a.onclick=function(){edit(t,n),hidectx()},a.style.display=isText(t)?"block":"none",a=c.getElementsByTagName("li")[3],a.onclick=function(){preview(t,n),hidectx()},a.style.display=isImage(t)?"block":"none",a=c.getElementsByTagName("li")[4],a.onclick=function(){download(t,n),hidectx()},a.style.display=i?"none":"block",a=c.getElementsByTagName("li")[5],a.onclick=function(){remove(t,n,o),hidectx()},a.style.display=n?"block":"none";var s=document.body.scrollTop?document.body.scrollTop:document.documentElement.scrollTop,l=document.body.scrollLeft?document.body.scrollLeft:document.documentElement.scrollLeft,r=e.clientX+l+10,d=e.clientY+s-20,m=(c.offsetWidth,c.offsetHeight),u=document.documentElement.clientHeight;d+m>u&&(d=u-m-20),c.style.left=r+"px",c.style.top=d+"px",o&&o.classList.add("selitem")}function drag(e,t,n){let o=n+t.name;isFolder(t)&&(o+="/"),e.dataTransfer.setData("text",o),console.log("drag start "+o)}function drop(e,t){let n=e.dataTransfer.getData("text");n.startsWith(t)||(e.preventDefault(),console.log("Move "+n+" to "+t))}function listFiles(e,t){return console.log("listFiles"),fetch("/api/files/?dir="+t).then((e=>e.json())).then((n=>{if(0==n.length)return!1;let o=e.getElementsByTagName("div")[0];o&&(o.onclick=n=>{i.remove(),o.onclick=()=>{listFiles(e,t)},n.stopPropagation()});let a=e.getElementsByTagName("ul");for(let e=0;e{drag(event,e,t)},a.appendChild(s),s.innerHTML=''+o+"",isFolder(e)){let n=t+e.name+"/";s.classList.add("bold"),s.onclick=function(e){listFiles(a,n)},s.ondragover=e=>{e.preventDefault()},s.ondrop=e=>{drop(e,n)}}else(isText(e)||isImage(e)||isAudio(e))&&(s.onclick=function(n){url(e,t)});s.oncontextmenu=n=>{ctx(n,e,t,a)}}return e.scrollIntoView(),!0}))}function generateToast({message:e,background:t="#00214d",color:n="#fffffe",length:o="7000ms"}){_("toast").insertAdjacentHTML("afterbegin",`

\n ${e}\n

`);const a=_("toast").firstElementChild;a.addEventListener("animationend",(()=>a.remove()))}document.addEventListener("blur",(function(){hidectx()})),document.addEventListener("DOMContentLoaded",(function(){createEditor("editor",void 0,void 0,void 0);listFiles(_("tree"),"/"),_("tree").getElementsByTagName("div")[0].oncontextmenu=e=>{ctx(e,{name:"",children:[]},"",_("tree"))},_("load").onclick=function(e){const t=new FormData;t.append("load",""),fetchData("/edit","PUT",t)},_("init").onclick=function(e){const t=new FormData;t.append("init",""),fetchData("/edit","PUT",t)},_("home").onclick=function(e){window.location.href="/"},_("page").onchange=function(e){const t=new FormData;t.append("page",_("page").value),fetchData("/edit","PUT",t)}})),document.addEventListener("DOMContentLoaded",(function(){const e=document.getElementById("dragMe"),t=e.previousElementSibling,n=e.nextElementSibling;let o=0,a=0,i=0;const c=function(a){const c=a.clientX-o,s=(a.clientY,100*(i+c)/e.parentNode.getBoundingClientRect().width);t.style.width=`${s}%`,t.style.right=t.style.width,e.style.cursor="col-resize",document.body.style.cursor="col-resize",t.style.userSelect="none",t.style.pointerEvents="none",n.style.userSelect="none",n.style.pointerEvents="none",ace.edit("editor").resize()},s=function(){e.style.removeProperty("cursor"),document.body.style.removeProperty("cursor"),t.style.removeProperty("user-select"),t.style.removeProperty("pointer-events"),n.style.removeProperty("user-select"),n.style.removeProperty("pointer-events"),document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",s)};e.addEventListener("mousedown",(function(e){o=e.clientX,a=e.clientY,i=t.getBoundingClientRect().width,document.addEventListener("mousemove",c),document.addEventListener("mouseup",s)})),e.addEventListener("dblclick",(()=>{var e=t.style.visibility="hidden"===t.style.visibility;t.style.visibility=e?"unset":"hidden",t.style.position=e?"unset":"absolute",ace.edit("editor").resize()}))})); \ No newline at end of file +var ctx_el;function _(e){return document.getElementById(e)}function hidectx(){_("ctx").style.display="none",ctx_el&&ctx_el.classList.remove("selitem"),ctx_el=void 0}function doesFontExist(e){var t=document.createElement("canvas"),n=t.getContext("2d"),o="abcdefghijklmnopqrstuvwxyz0123456789";n.font="72px monospace";var a=n.measureText(o).width;return n.font="72px '"+e+"', monospace",t=null,n.measureText(o).width!=a}function createEditor(e,t,n,o,a){function i(e){let t=/(?:\.([^.]+))?$/.exec(e)[1];if(void 0!==typeof t)switch(t){case"htm":case"html":return"html";case"js":return"javascript";case"cmd":case"json":case"jsonl":return"json";case"css":case"svg":case"xml":return t}return"plain_text"}void 0===n&&(n=i(t)),void 0===a&&(a="text/"+n);["basePath","modePath","themePath"].forEach((e=>{ace.config.set(e,"https://cdnjs.cloudflare.com/ajax/libs/ace/1.33.2")}));var c=ace.edit(e,{useWorker:!1,wrap:!0,indentedSoftWrap:!1,showPrintMargin:!1,highlightGutterLine:!0,useSoftTabs:!0,tabSize:2});c.setFontSize(parseFloat(getComputedStyle(document.documentElement).fontSize)),c.setReadOnly(!0),c.getSession().setUndoManager(new ace.UndoManager),void 0===o&&(o=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"monokai":"textmate");var s=_("save"),l=_("undo"),r=_("redo"),d=_("cut"),m=_("copy"),u=_("paste"),p=_("font"),f=_("fontsize"),g="none"!==_(e).display;f.value=parseFloat(c.getFontSize()).toFixed(1),p.onchange=function(){c.setOption("fontFamily","'"+p.value+"',monospace")},f.onchange=function(){var e=parseFloat(f.value);!isNaN(e)&&e>=9&&e<=40&&c.setFontSize(e),f.value=parseFloat(c.getFontSize()).toFixed(1)};function h(){let e=!g||c.session.getSelection().isEmpty();d.disabled=e,m.disabled=e}function y(){let e=c.session.getUndoManager();s.disabled=!g||e.isClean(),l.disabled=!g||!e.hasUndo(),r.disabled=!g||!e.hasRedo()}function v(){if(void 0===t)return;const e=function(e){var t=e.getValue();try{var n=JSON.parse(t);return JSON.stringify(n)}catch(e){return t+""}}(c),n=new FormData;n.append("data",new Blob([e],{type:a}),t),fetch("/edit",{method:"POST",body:n}).then((e=>e.ok?e.text().then((e=>{console.log("Save OK /edit "+e)})):e.text().then((e=>{throw console.log("Save FAIL /edit"),new Error(e)})))).then((e=>{console.log(e),generateToast({message:"Saved "+t,background:"#ddd",color:"#000"})})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{y()}))}function x(){var e=c.getCopyText();if(window.clipboardData&&window.clipboardData.setData)return window.clipboardData.setData("Text",e);if(document.queryCommandSupported&&document.queryCommandSupported("copy")){c.focus();try{return document.execCommand("copy")}catch(t){return console.warn("Copy to clipboard failed.",t),prompt("Copy to clipboard: Ctrl+C, Enter",e)}}}function w(e){_("name").innerHTML=e;fetch(e).then((t=>t.ok?(console.log("OK "+e),t.text()):t.text().then((e=>{throw console.log("ERROR "+url),new Error(e)})))).then((e=>{try{var t=JSON.parse(e);c.setValue(JSON.stringify(t,null,4)),console.log("parse json OK")}catch(t){c.setValue(e),console.log("parse json FAIL")}null!==_("editor")&&(_("editor").style.display="block"),null!==_("preview")&&(_("preview").style.display="none"),g=!0,c.setReadOnly(!1),c.focus(),y()})).catch((e=>{console.log(e),alert(e),c.setReadOnly(!0)})).finally((()=>{c.resize(!0),c.scrollToLine(1,!0,!0,(function(){})),c.gotoLine(1,0,!0),c.clearSelection(),c.session.getUndoManager().reset()}))}return["Courier New","Monaco","Lucida Console","Monospace","ui-monospace","Roboto Mono","Inconsolata","IBM Plex Mono","Space Mono","PT Mono","Ubuntu Mono","Nanum Gothic Coding","Cousine","Fira Mono","Share Tech Mono","Courier Prime","Anonymous Pro","Cutive Mono","Overpass Mono","Fira Code","VT323","DM Mono","Oxygen Mono","Nova Mono","B612 Mono","Spline Sans Mono","Noto Sans Mono","Major Mono Display","Azeret Mono","Red Hat Mono","Syne Mono","Xanh Mono"].sort().forEach((function(e,t){if(doesFontExist(e)){var n=document.createElement("option");n.text=e,p.add(n)}})),null!==s&&null!==l&&null!==r&&c.on("input",y),c.session.selection.on("changeCursor",h),s.onclick=v,l.onclick=e=>{c.undo()&&c.focus()},r.onclick=e=>{c.redo()&&c.focus()},d.onclick=e=>{x()&&c.execCommand("cut")},m.onclick=e=>{x()&&c.execCommand("copy")},u.onclick=function(){try{navigator.clipboard.readText().then((e=>{c.execCommand("paste",e)})).catch((e=>{u.disabled=!0}))}catch{u.disabled=!0}},c.loadUrl=(e,o)=>{n=i(t=e+o),a="text/"+n,"plain"!==n&&c.getSession().setMode("ace/mode/"+n),w(e+o)},c.hide=()=>{g=!1,y(),h(),_("editor").style.display="none"},"plain"!==n&&c.getSession().setMode("ace/mode/"+n),c.setTheme("ace/theme/"+o),c.$blockScrolling=1/0,c.commands.addCommand({name:"save",bindKey:{win:"Ctrl-S",mac:"Command-S"},exec:v,readOnly:!1}),c.commands.addCommand({name:"undo",bindKey:{win:"Ctrl-Z",mac:"Command-Z"},exec:function(){c.undo()}}),c.commands.addCommand({name:"redo",bindKey:{win:"Ctrl-Y",mac:"Command-Y"},exec:function(){c.redo()}}),void 0!==t&&w(t),c.resize(),c}function uploadFileAsync(e,t,n,o,a,i){fetchData("/edit","POST",e).then((e=>{generateToast({message:"Upload "+n+"/"+o+" "+t+" done.",background:"#ddd",color:"#000"}),n==o&&listFiles(a,i)}))}function doUpload(e,t){const n=_("upload"),o=n.files.length;if(0!==o)for(let a=0;a=0}function isText(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"txt":case"cmd":case"json":case"jsonl":case"htm":case"html":case"js":case"c":case"cpp":case"css":case"svg":case"xml":return!0}return!1}function isImage(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"bmp":case"png":case"jpg":case"gif":case"svg":return!0}return!1}function isAudio(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"wav":case"mp3":case"aac":case"m4a":case"wma":return!0}return!1}function icon(e){if(isFolder(e))return"dir";if(isImage(e))return"image";if(isAudio(e))return"audio";var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"cmd":case"css":case"json":case"jsonl":case"ttf":return t;case"zip":case"gz":return"zip";case"html":case"htm":return"html"}return"file"}function preview(e,t){if(isImage(e)){let n=t+e.name;const o=_("preview");o.innerHTML='',o.style.display="block",ace.edit("editor").hide(),_("name").innerHTML=n}}function edit(e,t){isText(e)&&(ace.edit("editor").loadUrl(t,e.name),_("preview").style.display="none")}function url(e,t){console.log("click "+t+e.name),isImage(e)?preview(e,t):isText(e)&&edit(e,t)}async function fetchData(e,t,n,o){await fetch(e,{method:t,body:n}).then((n=>n.ok?(console.log(t+" OK "+e),n.text()):n.text().then((n=>{throw console.log(t+" FAIL "+e),new Error(n)})))).then((e=>{o&&o.remove(),console.log(e)})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{}))}function download(e,t){console.log("download "+t+e.name),document.getElementById("download-frame").src=t+e.name+"?download=true"}function remove(e,t,n){let o=t+e.name;isFolder(e)&&(o+="/"),console.log("remove "+o);const a=new FormData;a.append("path",o),fetchData("/edit","DELETE",a,n)}function create(e,t,n){var o=window.prompt("Create File in "+e,"");if(null==o||""==o||o.includes("/"))return;const a=new FormData;a.append("path",e+o),fetchData("/edit","PUT",a),fetch("/api/files/").then((e=>e.json())).then((o=>{t&&t.remove(),listFiles(n,e),console.log(o)}))}function upload(e,t){_("upload").onchange=()=>{doUpload(e,t)},_("upload").click()}function ctx(e,t,n,o){e.preventDefault(),ctx_el=o;let a,i=isFolder(t),c=_("ctx");c.style.display="block",a=c.getElementsByTagName("li")[0],a.onclick=i?function(){hidectx(),create(n+t.name+"/",o.children.item(1),o)}:function(){hidectx(),create(n,o.parentNode,o.parentNode.parentNode)},a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[1],i&&(a.onclick=function(){hidectx(),upload(o,n+t.name+"/")}),a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[2],a.onclick=function(){edit(t,n),hidectx()},a.style.display=isText(t)?"block":"none",a=c.getElementsByTagName("li")[3],a.onclick=function(){preview(t,n),hidectx()},a.style.display=isImage(t)?"block":"none",a=c.getElementsByTagName("li")[4],a.onclick=function(){download(t,n),hidectx()},a.style.display=i?"none":"block",a=c.getElementsByTagName("li")[5],a.onclick=function(){remove(t,n,o),hidectx()},a.style.display=n?"block":"none";var s=document.body.scrollTop?document.body.scrollTop:document.documentElement.scrollTop,l=document.body.scrollLeft?document.body.scrollLeft:document.documentElement.scrollLeft,r=e.clientX+l+10,d=e.clientY+s-20,m=(c.offsetWidth,c.offsetHeight),u=document.documentElement.clientHeight;d+m>u&&(d=u-m-20),c.style.left=r+"px",c.style.top=d+"px",o&&o.classList.add("selitem")}function drag(e,t,n){let o=n+t.name;isFolder(t)&&(o+="/"),e.dataTransfer.setData("text",o),console.log("drag start "+o)}function drop(e,t){let n=e.dataTransfer.getData("text");n.startsWith(t)||(e.preventDefault(),console.log("Move "+n+" to "+t))}function listFiles(e,t){return console.log("listFiles"),fetch("/api/files/?dir="+t).then((e=>e.json())).then((n=>{if(0==n.length)return!1;let o=e.getElementsByTagName("div")[0];o&&(o.onclick=n=>{i.remove(),o.onclick=()=>{listFiles(e,t)},n.stopPropagation()});let a=e.getElementsByTagName("ul");for(let e=0;e{drag(event,e,t)},a.appendChild(s),s.innerHTML=''+o+"",isFolder(e)){let n=t+e.name+"/";s.classList.add("bold"),s.onclick=function(e){listFiles(a,n)},s.ondragover=e=>{e.preventDefault()},s.ondrop=e=>{drop(e,n)}}else(isText(e)||isImage(e)||isAudio(e))&&(s.onclick=function(n){url(e,t)});s.oncontextmenu=n=>{ctx(n,e,t,a)}}return e.scrollIntoView(),!0}))}function generateToast({message:e,background:t="#00214d",color:n="#fffffe",length:o="7000ms"}){_("toast").insertAdjacentHTML("afterbegin",`

\n ${e}\n

`);const a=_("toast").firstElementChild;a.addEventListener("animationend",(()=>a.remove()))}document.addEventListener("blur",(function(){hidectx()})),document.addEventListener("DOMContentLoaded",(function(){createEditor("editor",void 0,void 0,void 0);listFiles(_("tree"),"/"),_("tree").getElementsByTagName("div")[0].oncontextmenu=e=>{ctx(e,{name:"",children:[]},"",_("tree"))},_("load").onclick=function(e){const t=new FormData;t.append("load",""),fetchData("/edit","PUT",t)},_("init").onclick=function(e){const t=new FormData;t.append("init",""),fetchData("/edit","PUT",t)},_("home").onclick=function(e){window.location.href="/"},_("page").onchange=function(e){const t=new FormData;t.append("page",_("page").value),fetchData("/edit","PUT",t)}})),document.addEventListener("DOMContentLoaded",(function(){const e=document.getElementById("dragMe"),t=e.previousElementSibling,n=e.nextElementSibling;let o=0,a=0,i=0;const c=function(a){const c=a.clientX-o,s=(a.clientY,100*(i+c)/e.parentNode.getBoundingClientRect().width);t.style.width=`${s}%`,t.style.right=t.style.width,e.style.cursor="col-resize",document.body.style.cursor="col-resize",t.style.userSelect="none",t.style.pointerEvents="none",n.style.userSelect="none",n.style.pointerEvents="none",ace.edit("editor").resize()},s=function(){e.style.removeProperty("cursor"),document.body.style.removeProperty("cursor"),t.style.removeProperty("user-select"),t.style.removeProperty("pointer-events"),n.style.removeProperty("user-select"),n.style.removeProperty("pointer-events"),document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",s)};e.addEventListener("mousedown",(function(e){o=e.clientX,a=e.clientY,i=t.getBoundingClientRect().width,document.addEventListener("mousemove",c),document.addEventListener("mouseup",s)})),e.addEventListener("dblclick",(()=>{var e=t.style.visibility="hidden"===t.style.visibility;t.style.visibility=e?"unset":"hidden",t.style.position=e?"unset":"absolute",ace.edit("editor").resize()}))})); \ No newline at end of file From 180cc84ea2abbb9686775b277d6d57be5929436e Mon Sep 17 00:00:00 2001 From: FreeBear Date: Fri, 17 May 2024 00:09:34 +0100 Subject: [PATCH 03/55] Minor spelling mistake corrected --- src/hasp_filesystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hasp_filesystem.cpp b/src/hasp_filesystem.cpp index ac39a344..1f9f4953 100644 --- a/src/hasp_filesystem.cpp +++ b/src/hasp_filesystem.cpp @@ -180,7 +180,7 @@ void filesystemList() #else if(!HASP_FS.begin(true)) { // default vfs path: /littlefs #endif - LOG_ERROR(TAG_FILE, F("Flash file system not mouted.")); + LOG_ERROR(TAG_FILE, F("Flash file system not mounted.")); } else { LOG_VERBOSE(TAG_FILE, F("Listing files on the internal flash:")); From 182c8c670b640502f5efbfe973ed4affbd41d65c Mon Sep 17 00:00:00 2001 From: K Date: Sat, 18 May 2024 19:32:04 -0400 Subject: [PATCH 04/55] Add support for Guition JC4827W543 --- platformio.ini | 2 +- src/drv/tft/tft_driver_arduinogfx.cpp | 8 +++ src/hasp_gui.cpp | 2 +- user_setups/esp32s3/guition-jc4827w543.ini | 60 ++++++++++++++++++++++ 4 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 user_setups/esp32s3/guition-jc4827w543.ini diff --git a/platformio.ini b/platformio.ini index 444439fc..a003dc93 100644 --- a/platformio.ini +++ b/platformio.ini @@ -112,7 +112,7 @@ lib_deps = [arduinogfx] lib_deps = - moononournation/GFX Library for Arduino@1.4.0 ; Update needs modification of custom PCA class + moononournation/GFX Library for Arduino@1.4.7 ; Update needs modification of custom PCA class ;git+https://github.com/moononournation/Arduino_GFX.git [tft_espi] diff --git a/src/drv/tft/tft_driver_arduinogfx.cpp b/src/drv/tft/tft_driver_arduinogfx.cpp index c946120a..601d841f 100644 --- a/src/drv/tft/tft_driver_arduinogfx.cpp +++ b/src/drv/tft/tft_driver_arduinogfx.cpp @@ -85,6 +85,10 @@ void ArduinoGfx::init(int w, int h) /* More display class: https://github.com/moononournation/Arduino_GFX/wiki/Display-Class */ tft = new Arduino_RGB_Display(w, h, rgbpanel, 0 /* rotation */, TFT_AUTO_FLUSH, bus, TFT_RST, st7701_type1_init_operations, sizeof(st7701_type1_init_operations)); +#elif(TFT_WIDTH == 480) && (TFT_HEIGHT == 272) && defined(NV3041A_DRIVER) + Arduino_DataBus* bus = new Arduino_ESP32QSPI(TFT_CS, TFT_SCK, TFT_D0, TFT_D1, TFT_D2, TFT_D3); + Arduino_GFX* g = new Arduino_NV3041A(bus, TFT_RST, TFT_ROTATION, TFT_IPS); + tft = g; #elif 1 /* Reset is not implemented in the panel */ if(TFT_RST != GFX_NOT_DEFINED) { @@ -299,6 +303,8 @@ const char* ArduinoGfx::get_tft_model() return "R61529"; #elif defined(RM68140_DRIVER) return "RM68140"; +#elif defined(NV3041A_DRIVER) + return "NV3041A"; #else return "Other"; #endif @@ -336,6 +342,8 @@ uint32_t ArduinoGfx::get_tft_driver() return 0x61529; #elif defined(RM68140_DRIVER) return 0x68140; +#elif defined(NV3041A_DRIVER) + return 0x3041A; #else return 0x0; #endif diff --git a/src/hasp_gui.cpp b/src/hasp_gui.cpp index 13caf317..ebb7870a 100644 --- a/src/hasp_gui.cpp +++ b/src/hasp_gui.cpp @@ -341,7 +341,7 @@ void guiSetup() #endif gui_hide_pointer(false); if(mouse_indev != NULL) { - lv_indev_set_cursor(mouse_indev, cursor); /*Connect the image object to the driver*/ + lv_indev_set_cursor(mouse_indev, cursor); /*Connect the image object to the driver*/ } #if HASP_TARGET_ARDUINO diff --git a/user_setups/esp32s3/guition-jc4827w543.ini b/user_setups/esp32s3/guition-jc4827w543.ini new file mode 100644 index 00000000..ae5f15e7 --- /dev/null +++ b/user_setups/esp32s3/guition-jc4827w543.ini @@ -0,0 +1,60 @@ +;***************************************************; +; Guition ESP32-S3 TFT 4.3" ; +; - Custom esp32-s3 board ; +; - nv3041a 480x272 ; +; - gt911 touch controller ; +;***************************************************; + +[guition-esp32-s3-tft] +extends = arduino_esp32s3_v2 +board = esp32-s3-devkitc-1 +board_build.arduino.memory_type = qio_opi + +build_flags = + ${arduino_esp32s3_v2.build_flags} + ${esp32s3.ps_ram} + ;-D HASP_MODEL="Guition 4.3\"" + +;region -- ArduinoGFX build options ------------------------ + -D HASP_USE_ARDUINOGFX + -D NV3041A_DRIVER + -D BACKLIGHT_FREQUENCY=50 + ;endregion + +lib_deps = + ${arduino_esp32s3_v2.lib_deps} + ${arduinogfx.lib_deps} + ${goodix.lib_deps} + + +[guition-tft-common-pins] +build_flags = + -D TFT_BCKL=1 + -D TFT_CS=45 + -D TFT_SCK=47 + -D TFT_D0=21 + -D TFT_D1=48 + -D TFT_D2=40 + -D TFT_D3=39 + -D TFT_RST=GFX_NOT_DEFINED + -D TFT_ROTATION=0 + -D TFT_IPS=true + -D TFT_WIDTH=480 + -D TFT_HEIGHT=272 + +[guition-jc4827w543] +extends = guition-esp32-s3-tft +debug_tool = esp-builtin +debug_build_flags = -Os # optimize for size +build_flags = + -D HASP_MODEL="Guition ESP32-S3 JC4827W543" + ${guition-esp32-s3-tft.build_flags} + ${guition-tft-common-pins.build_flags} + ; Touch Settings + -D TOUCH_DRIVER=0x0911 + -D TOUCH_SCL=4 + -D TOUCH_SDA=8 + -D TOUCH_IRQ=-1 + -D TOUCH_RST=38 + -D I2C_TOUCH_FREQUENCY=0 + -D I2C_TOUCH_ADDRESS=0x5D \ No newline at end of file From c70dfe6d424ef0c5b433a4446304f2cd0db7f278 Mon Sep 17 00:00:00 2001 From: FreeBear Date: Mon, 20 May 2024 15:03:19 +0100 Subject: [PATCH 05/55] Add list of TFT gpio pins so that they can not be selected for IO. --- src/drv/tft/tft_driver_arduinogfx.cpp | 98 +++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/src/drv/tft/tft_driver_arduinogfx.cpp b/src/drv/tft/tft_driver_arduinogfx.cpp index c946120a..e050059c 100644 --- a/src/drv/tft/tft_driver_arduinogfx.cpp +++ b/src/drv/tft/tft_driver_arduinogfx.cpp @@ -262,6 +262,104 @@ void IRAM_ATTR ArduinoGfx::flush_pixels(lv_disp_drv_t* disp, const lv_area_t* ar bool ArduinoGfx::is_driver_pin(uint8_t pin) { + if(false // start condition is always needed + +// Use individual checks instead of switch statement, as some case labels could be duplicated +#ifdef TFT_MOSI + || (pin == TFT_MOSI) +#endif +#ifdef TFT_MISO + || (pin == TFT_MISO) +#endif +#ifdef TFT_SCLK + || (pin == TFT_SCLK) +#endif +#ifdef TFT_CS + || (pin == TFT_CS) +#endif +#ifdef TFT_DC + || (pin == TFT_DC) +#endif +#ifdef TFT_DE + || (pin == TFT_DE) +#endif +#ifdef TFT_PCLK + || (pin == TFT_PCLK) +#endif +#ifdef TFT_VSYNC + || (pin == TFT_VSYNC) +#endif +#ifdef TFT_HSYNC + || (pin == TFT_HSYNC) +#endif +#ifdef TFT_BCKL + || (pin == TFT_BCKL) +#endif +#ifdef TFT_RST + || (pin == TFT_RST) +#endif +#ifdef TFT_BUSY + || (pin == TFT_BUSY) +#endif +#ifdef TFT_RD + || (pin == TFT_RD) +#endif +#ifdef TFT_R0 + || (pin == TFT_R0) +#endif +#ifdef TFT_R1 + || (pin == TFT_R1) +#endif +#ifdef TFT_R2 + || (pin == TFT_R2) +#endif +#ifdef TFT_R3 + || (pin == TFT_R3) +#endif +#ifdef TFT_R4 + || (pin == TFT_R4) +#endif +#ifdef TFT_G0 + || (pin == TFT_G0) +#endif +#ifdef TFT_G1 + || (pin == TFT_G1) +#endif +#ifdef TFT_G2 + || (pin == TFT_G2) +#endif +#ifdef TFT_G3 + || (pin == TFT_G3) +#endif +#ifdef TFT_G4 + || (pin == TFT_G4) +#endif +#ifdef TFT_B0 + || (pin == TFT_B0) +#endif +#ifdef TFT_B1 + || (pin == TFT_B1) +#endif +#ifdef TFT_B2 + || (pin == TFT_B2) +#endif +#ifdef TFT_B3 + || (pin == TFT_B3) +#endif +#ifdef TFT_B4 + || (pin == TFT_B4) +#endif + ) { + return true; + } + +#ifdef ARDUINO_ARCH_ESP8266 +#ifndef TFT_SPI_OVERLAP + if((pin >= 12) && (pin <= 14)) return true; // HSPI +#endif +#endif + + return false; return false; } From 7a3b8d0997fe8367ad27f755f4f07df0a4ea77b4 Mon Sep 17 00:00:00 2001 From: FreeBear Date: Mon, 20 May 2024 15:30:15 +0100 Subject: [PATCH 06/55] Add the touch gpio pins to the list so that they are hidden from IO selection. --- src/drv/tft/tft_driver_arduinogfx.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/drv/tft/tft_driver_arduinogfx.cpp b/src/drv/tft/tft_driver_arduinogfx.cpp index e050059c..00847ca3 100644 --- a/src/drv/tft/tft_driver_arduinogfx.cpp +++ b/src/drv/tft/tft_driver_arduinogfx.cpp @@ -348,6 +348,18 @@ bool ArduinoGfx::is_driver_pin(uint8_t pin) #endif #ifdef TFT_B4 || (pin == TFT_B4) +#endif +#ifdef TOUCH_SDA + || (pin == TOUCH_SDA) +#endif +#ifdef TOUCH_SCL + || (pin == TOUCH_SCL) +#endif +#ifdef TOUCH_RST + || (pin == TOUCH_RST) +#endif +#ifdef TOUCH_IRQ + || (pin == TOUCH_IRQ) #endif ) { return true; From 86d45119404b9c7cbca170b911a56c07690dca5c Mon Sep 17 00:00:00 2001 From: K Date: Mon, 20 May 2024 12:18:33 -0400 Subject: [PATCH 07/55] Fix backlight freq and suffix build target --- user_setups/esp32s3/guition-jc4827w543.ini | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/user_setups/esp32s3/guition-jc4827w543.ini b/user_setups/esp32s3/guition-jc4827w543.ini index ae5f15e7..689b764c 100644 --- a/user_setups/esp32s3/guition-jc4827w543.ini +++ b/user_setups/esp32s3/guition-jc4827w543.ini @@ -18,7 +18,6 @@ build_flags = ;region -- ArduinoGFX build options ------------------------ -D HASP_USE_ARDUINOGFX -D NV3041A_DRIVER - -D BACKLIGHT_FREQUENCY=50 ;endregion lib_deps = @@ -42,12 +41,12 @@ build_flags = -D TFT_WIDTH=480 -D TFT_HEIGHT=272 -[guition-jc4827w543] -extends = guition-esp32-s3-tft +[guition-jc4827w543c] +extends = guition-esp32-s3-tft, flash_4mb debug_tool = esp-builtin debug_build_flags = -Os # optimize for size build_flags = - -D HASP_MODEL="Guition ESP32-S3 JC4827W543" + -D HASP_MODEL="Guition ESP32-S3 JC4827W543C" ${guition-esp32-s3-tft.build_flags} ${guition-tft-common-pins.build_flags} ; Touch Settings @@ -57,4 +56,4 @@ build_flags = -D TOUCH_IRQ=-1 -D TOUCH_RST=38 -D I2C_TOUCH_FREQUENCY=0 - -D I2C_TOUCH_ADDRESS=0x5D \ No newline at end of file + -D I2C_TOUCH_ADDRESS=0x5D From ca6d521a0a5d22f4bbb1c6c4b6146dad03fa5584 Mon Sep 17 00:00:00 2001 From: FreeBear Date: Tue, 21 May 2024 13:14:58 +0100 Subject: [PATCH 08/55] Missing the FILE_SIZE_DIVIDER for gigabits - This results in the number being printed with the decimal point in the wrong place. --- src/hasp/hasp_parser.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hasp/hasp_parser.cpp b/src/hasp/hasp_parser.cpp index a44a9741..eee1175d 100644 --- a/src/hasp/hasp_parser.cpp +++ b/src/hasp/hasp_parser.cpp @@ -212,6 +212,7 @@ int Parser::format_bytes(size_t filesize, char* buf, size_t len) return snprintf_P(buf, len, PSTR("%d" D_DECIMAL_POINT "%02d " D_FILE_SIZE_MEGABYTES), filesize / 100, filesize % 100); + filesize = filesize / D_FILE_SIZE_DIVIDER; // multiply by 100 for 2 decimal place return snprintf_P(buf, len, PSTR("%d" D_DECIMAL_POINT "%02d " D_FILE_SIZE_GIGABYTES), filesize / 100, filesize % 100); } From 3433efbb49bdd1822202b70d4434a8ff5546bd4b Mon Sep 17 00:00:00 2001 From: fvanroie Date: Tue, 21 May 2024 15:50:57 +0200 Subject: [PATCH 09/55] Update sensecap-indicator-d1 --- user_setups/esp32s3/sensecap-indicator.ini | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/user_setups/esp32s3/sensecap-indicator.ini b/user_setups/esp32s3/sensecap-indicator.ini index ef64e18d..bc721aba 100644 --- a/user_setups/esp32s3/sensecap-indicator.ini +++ b/user_setups/esp32s3/sensecap-indicator.ini @@ -83,8 +83,7 @@ build_flags = lib_deps = ${arduino_esp32s3_v2.lib_deps} - ${arduinogfx.lib_deps} - ; ${ft6336.lib_deps} + moononournation/GFX Library for Arduino@1.4.0 ; Update needs modification of custom PCA class ; ${ft6336.lib_deps} ; git+https://github.com/RobTillaart/TCA9555.git From 909afcf2baf21ecd51f15f50b5135d729e5b56d1 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Tue, 21 May 2024 20:28:56 +0200 Subject: [PATCH 10/55] UPdate ace.js to 1.33.3 --- data/edit.htm | 2 +- data/script.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/edit.htm b/data/edit.htm index a644194a..3d0a9e5a 100644 --- a/data/edit.htm +++ b/data/edit.htm @@ -1 +1 @@ -openHASP File Editor
L:
  • New File
  • Upload Files
  • Edit
  • Preview
  • Download
  • Delete
\ No newline at end of file +openHASP File Editor
L:
  • New File
  • Upload Files
  • Edit
  • Preview
  • Download
  • Delete
\ No newline at end of file diff --git a/data/script.js b/data/script.js index 2578aad1..c129c1e6 100644 --- a/data/script.js +++ b/data/script.js @@ -1 +1 @@ -var ctx_el;function _(e){return document.getElementById(e)}function hidectx(){_("ctx").style.display="none",ctx_el&&ctx_el.classList.remove("selitem"),ctx_el=void 0}function doesFontExist(e){var t=document.createElement("canvas"),n=t.getContext("2d"),o="abcdefghijklmnopqrstuvwxyz0123456789";n.font="72px monospace";var a=n.measureText(o).width;return n.font="72px '"+e+"', monospace",t=null,n.measureText(o).width!=a}function createEditor(e,t,n,o,a){function i(e){let t=/(?:\.([^.]+))?$/.exec(e)[1];if(void 0!==typeof t)switch(t){case"htm":case"html":return"html";case"js":return"javascript";case"cmd":case"json":case"jsonl":return"json";case"css":case"svg":case"xml":return t}return"plain_text"}void 0===n&&(n=i(t)),void 0===a&&(a="text/"+n);["basePath","modePath","themePath"].forEach((e=>{ace.config.set(e,"https://cdnjs.cloudflare.com/ajax/libs/ace/1.33.2")}));var c=ace.edit(e,{useWorker:!1,wrap:!0,indentedSoftWrap:!1,showPrintMargin:!1,highlightGutterLine:!0,useSoftTabs:!0,tabSize:2});c.setFontSize(parseFloat(getComputedStyle(document.documentElement).fontSize)),c.setReadOnly(!0),c.getSession().setUndoManager(new ace.UndoManager),void 0===o&&(o=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"monokai":"textmate");var s=_("save"),l=_("undo"),r=_("redo"),d=_("cut"),m=_("copy"),u=_("paste"),p=_("font"),f=_("fontsize"),g="none"!==_(e).display;f.value=parseFloat(c.getFontSize()).toFixed(1),p.onchange=function(){c.setOption("fontFamily","'"+p.value+"',monospace")},f.onchange=function(){var e=parseFloat(f.value);!isNaN(e)&&e>=9&&e<=40&&c.setFontSize(e),f.value=parseFloat(c.getFontSize()).toFixed(1)};function h(){let e=!g||c.session.getSelection().isEmpty();d.disabled=e,m.disabled=e}function y(){let e=c.session.getUndoManager();s.disabled=!g||e.isClean(),l.disabled=!g||!e.hasUndo(),r.disabled=!g||!e.hasRedo()}function v(){if(void 0===t)return;const e=function(e){var t=e.getValue();try{var n=JSON.parse(t);return JSON.stringify(n)}catch(e){return t+""}}(c),n=new FormData;n.append("data",new Blob([e],{type:a}),t),fetch("/edit",{method:"POST",body:n}).then((e=>e.ok?e.text().then((e=>{console.log("Save OK /edit "+e)})):e.text().then((e=>{throw console.log("Save FAIL /edit"),new Error(e)})))).then((e=>{console.log(e),generateToast({message:"Saved "+t,background:"#ddd",color:"#000"})})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{y()}))}function x(){var e=c.getCopyText();if(window.clipboardData&&window.clipboardData.setData)return window.clipboardData.setData("Text",e);if(document.queryCommandSupported&&document.queryCommandSupported("copy")){c.focus();try{return document.execCommand("copy")}catch(t){return console.warn("Copy to clipboard failed.",t),prompt("Copy to clipboard: Ctrl+C, Enter",e)}}}function w(e){_("name").innerHTML=e;fetch(e).then((t=>t.ok?(console.log("OK "+e),t.text()):t.text().then((e=>{throw console.log("ERROR "+url),new Error(e)})))).then((e=>{try{var t=JSON.parse(e);c.setValue(JSON.stringify(t,null,4)),console.log("parse json OK")}catch(t){c.setValue(e),console.log("parse json FAIL")}null!==_("editor")&&(_("editor").style.display="block"),null!==_("preview")&&(_("preview").style.display="none"),g=!0,c.setReadOnly(!1),c.focus(),y()})).catch((e=>{console.log(e),alert(e),c.setReadOnly(!0)})).finally((()=>{c.resize(!0),c.scrollToLine(1,!0,!0,(function(){})),c.gotoLine(1,0,!0),c.clearSelection(),c.session.getUndoManager().reset()}))}return["Courier New","Monaco","Lucida Console","Monospace","ui-monospace","Roboto Mono","Inconsolata","IBM Plex Mono","Space Mono","PT Mono","Ubuntu Mono","Nanum Gothic Coding","Cousine","Fira Mono","Share Tech Mono","Courier Prime","Anonymous Pro","Cutive Mono","Overpass Mono","Fira Code","VT323","DM Mono","Oxygen Mono","Nova Mono","B612 Mono","Spline Sans Mono","Noto Sans Mono","Major Mono Display","Azeret Mono","Red Hat Mono","Syne Mono","Xanh Mono"].sort().forEach((function(e,t){if(doesFontExist(e)){var n=document.createElement("option");n.text=e,p.add(n)}})),null!==s&&null!==l&&null!==r&&c.on("input",y),c.session.selection.on("changeCursor",h),s.onclick=v,l.onclick=e=>{c.undo()&&c.focus()},r.onclick=e=>{c.redo()&&c.focus()},d.onclick=e=>{x()&&c.execCommand("cut")},m.onclick=e=>{x()&&c.execCommand("copy")},u.onclick=function(){try{navigator.clipboard.readText().then((e=>{c.execCommand("paste",e)})).catch((e=>{u.disabled=!0}))}catch{u.disabled=!0}},c.loadUrl=(e,o)=>{n=i(t=e+o),a="text/"+n,"plain"!==n&&c.getSession().setMode("ace/mode/"+n),w(e+o)},c.hide=()=>{g=!1,y(),h(),_("editor").style.display="none"},"plain"!==n&&c.getSession().setMode("ace/mode/"+n),c.setTheme("ace/theme/"+o),c.$blockScrolling=1/0,c.commands.addCommand({name:"save",bindKey:{win:"Ctrl-S",mac:"Command-S"},exec:v,readOnly:!1}),c.commands.addCommand({name:"undo",bindKey:{win:"Ctrl-Z",mac:"Command-Z"},exec:function(){c.undo()}}),c.commands.addCommand({name:"redo",bindKey:{win:"Ctrl-Y",mac:"Command-Y"},exec:function(){c.redo()}}),void 0!==t&&w(t),c.resize(),c}function uploadFileAsync(e,t,n,o,a,i){fetchData("/edit","POST",e).then((e=>{generateToast({message:"Upload "+n+"/"+o+" "+t+" done.",background:"#ddd",color:"#000"}),n==o&&listFiles(a,i)}))}function doUpload(e,t){const n=_("upload"),o=n.files.length;if(0!==o)for(let a=0;a=0}function isText(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"txt":case"cmd":case"json":case"jsonl":case"htm":case"html":case"js":case"c":case"cpp":case"css":case"svg":case"xml":return!0}return!1}function isImage(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"bmp":case"png":case"jpg":case"gif":case"svg":return!0}return!1}function isAudio(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"wav":case"mp3":case"aac":case"m4a":case"wma":return!0}return!1}function icon(e){if(isFolder(e))return"dir";if(isImage(e))return"image";if(isAudio(e))return"audio";var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"cmd":case"css":case"json":case"jsonl":case"ttf":return t;case"zip":case"gz":return"zip";case"html":case"htm":return"html"}return"file"}function preview(e,t){if(isImage(e)){let n=t+e.name;const o=_("preview");o.innerHTML='',o.style.display="block",ace.edit("editor").hide(),_("name").innerHTML=n}}function edit(e,t){isText(e)&&(ace.edit("editor").loadUrl(t,e.name),_("preview").style.display="none")}function url(e,t){console.log("click "+t+e.name),isImage(e)?preview(e,t):isText(e)&&edit(e,t)}async function fetchData(e,t,n,o){await fetch(e,{method:t,body:n}).then((n=>n.ok?(console.log(t+" OK "+e),n.text()):n.text().then((n=>{throw console.log(t+" FAIL "+e),new Error(n)})))).then((e=>{o&&o.remove(),console.log(e)})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{}))}function download(e,t){console.log("download "+t+e.name),document.getElementById("download-frame").src=t+e.name+"?download=true"}function remove(e,t,n){let o=t+e.name;isFolder(e)&&(o+="/"),console.log("remove "+o);const a=new FormData;a.append("path",o),fetchData("/edit","DELETE",a,n)}function create(e,t,n){var o=window.prompt("Create File in "+e,"");if(null==o||""==o||o.includes("/"))return;const a=new FormData;a.append("path",e+o),fetchData("/edit","PUT",a),fetch("/api/files/").then((e=>e.json())).then((o=>{t&&t.remove(),listFiles(n,e),console.log(o)}))}function upload(e,t){_("upload").onchange=()=>{doUpload(e,t)},_("upload").click()}function ctx(e,t,n,o){e.preventDefault(),ctx_el=o;let a,i=isFolder(t),c=_("ctx");c.style.display="block",a=c.getElementsByTagName("li")[0],a.onclick=i?function(){hidectx(),create(n+t.name+"/",o.children.item(1),o)}:function(){hidectx(),create(n,o.parentNode,o.parentNode.parentNode)},a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[1],i&&(a.onclick=function(){hidectx(),upload(o,n+t.name+"/")}),a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[2],a.onclick=function(){edit(t,n),hidectx()},a.style.display=isText(t)?"block":"none",a=c.getElementsByTagName("li")[3],a.onclick=function(){preview(t,n),hidectx()},a.style.display=isImage(t)?"block":"none",a=c.getElementsByTagName("li")[4],a.onclick=function(){download(t,n),hidectx()},a.style.display=i?"none":"block",a=c.getElementsByTagName("li")[5],a.onclick=function(){remove(t,n,o),hidectx()},a.style.display=n?"block":"none";var s=document.body.scrollTop?document.body.scrollTop:document.documentElement.scrollTop,l=document.body.scrollLeft?document.body.scrollLeft:document.documentElement.scrollLeft,r=e.clientX+l+10,d=e.clientY+s-20,m=(c.offsetWidth,c.offsetHeight),u=document.documentElement.clientHeight;d+m>u&&(d=u-m-20),c.style.left=r+"px",c.style.top=d+"px",o&&o.classList.add("selitem")}function drag(e,t,n){let o=n+t.name;isFolder(t)&&(o+="/"),e.dataTransfer.setData("text",o),console.log("drag start "+o)}function drop(e,t){let n=e.dataTransfer.getData("text");n.startsWith(t)||(e.preventDefault(),console.log("Move "+n+" to "+t))}function listFiles(e,t){return console.log("listFiles"),fetch("/api/files/?dir="+t).then((e=>e.json())).then((n=>{if(0==n.length)return!1;let o=e.getElementsByTagName("div")[0];o&&(o.onclick=n=>{i.remove(),o.onclick=()=>{listFiles(e,t)},n.stopPropagation()});let a=e.getElementsByTagName("ul");for(let e=0;e{drag(event,e,t)},a.appendChild(s),s.innerHTML=''+o+"",isFolder(e)){let n=t+e.name+"/";s.classList.add("bold"),s.onclick=function(e){listFiles(a,n)},s.ondragover=e=>{e.preventDefault()},s.ondrop=e=>{drop(e,n)}}else(isText(e)||isImage(e)||isAudio(e))&&(s.onclick=function(n){url(e,t)});s.oncontextmenu=n=>{ctx(n,e,t,a)}}return e.scrollIntoView(),!0}))}function generateToast({message:e,background:t="#00214d",color:n="#fffffe",length:o="7000ms"}){_("toast").insertAdjacentHTML("afterbegin",`

\n ${e}\n

`);const a=_("toast").firstElementChild;a.addEventListener("animationend",(()=>a.remove()))}document.addEventListener("blur",(function(){hidectx()})),document.addEventListener("DOMContentLoaded",(function(){createEditor("editor",void 0,void 0,void 0);listFiles(_("tree"),"/"),_("tree").getElementsByTagName("div")[0].oncontextmenu=e=>{ctx(e,{name:"",children:[]},"",_("tree"))},_("load").onclick=function(e){const t=new FormData;t.append("load",""),fetchData("/edit","PUT",t)},_("init").onclick=function(e){const t=new FormData;t.append("init",""),fetchData("/edit","PUT",t)},_("home").onclick=function(e){window.location.href="/"},_("page").onchange=function(e){const t=new FormData;t.append("page",_("page").value),fetchData("/edit","PUT",t)}})),document.addEventListener("DOMContentLoaded",(function(){const e=document.getElementById("dragMe"),t=e.previousElementSibling,n=e.nextElementSibling;let o=0,a=0,i=0;const c=function(a){const c=a.clientX-o,s=(a.clientY,100*(i+c)/e.parentNode.getBoundingClientRect().width);t.style.width=`${s}%`,t.style.right=t.style.width,e.style.cursor="col-resize",document.body.style.cursor="col-resize",t.style.userSelect="none",t.style.pointerEvents="none",n.style.userSelect="none",n.style.pointerEvents="none",ace.edit("editor").resize()},s=function(){e.style.removeProperty("cursor"),document.body.style.removeProperty("cursor"),t.style.removeProperty("user-select"),t.style.removeProperty("pointer-events"),n.style.removeProperty("user-select"),n.style.removeProperty("pointer-events"),document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",s)};e.addEventListener("mousedown",(function(e){o=e.clientX,a=e.clientY,i=t.getBoundingClientRect().width,document.addEventListener("mousemove",c),document.addEventListener("mouseup",s)})),e.addEventListener("dblclick",(()=>{var e=t.style.visibility="hidden"===t.style.visibility;t.style.visibility=e?"unset":"hidden",t.style.position=e?"unset":"absolute",ace.edit("editor").resize()}))})); \ No newline at end of file +var ctx_el;function _(e){return document.getElementById(e)}function hidectx(){_("ctx").style.display="none",ctx_el&&ctx_el.classList.remove("selitem"),ctx_el=void 0}function doesFontExist(e){var t=document.createElement("canvas"),n=t.getContext("2d"),o="abcdefghijklmnopqrstuvwxyz0123456789";n.font="72px monospace";var a=n.measureText(o).width;return n.font="72px '"+e+"', monospace",t=null,n.measureText(o).width!=a}function createEditor(e,t,n,o,a){function i(e){let t=/(?:\.([^.]+))?$/.exec(e)[1];if(void 0!==typeof t)switch(t){case"htm":case"html":return"html";case"js":return"javascript";case"cmd":case"json":case"jsonl":return"json";case"css":case"svg":case"xml":return t}return"plain_text"}void 0===n&&(n=i(t)),void 0===a&&(a="text/"+n);["basePath","modePath","themePath"].forEach((e=>{ace.config.set(e,"https://cdnjs.cloudflare.com/ajax/libs/ace/1.33.3")}));var c=ace.edit(e,{useWorker:!1,wrap:!0,indentedSoftWrap:!1,showPrintMargin:!1,highlightGutterLine:!0,useSoftTabs:!0,tabSize:2});c.setFontSize(parseFloat(getComputedStyle(document.documentElement).fontSize)),c.setReadOnly(!0),c.getSession().setUndoManager(new ace.UndoManager),void 0===o&&(o=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"monokai":"textmate");var s=_("save"),l=_("undo"),r=_("redo"),d=_("cut"),m=_("copy"),u=_("paste"),p=_("font"),f=_("fontsize"),g="none"!==_(e).display;f.value=parseFloat(c.getFontSize()).toFixed(1),p.onchange=function(){c.setOption("fontFamily","'"+p.value+"',monospace")},f.onchange=function(){var e=parseFloat(f.value);!isNaN(e)&&e>=9&&e<=40&&c.setFontSize(e),f.value=parseFloat(c.getFontSize()).toFixed(1)};function h(){let e=!g||c.session.getSelection().isEmpty();d.disabled=e,m.disabled=e}function y(){let e=c.session.getUndoManager();s.disabled=!g||e.isClean(),l.disabled=!g||!e.hasUndo(),r.disabled=!g||!e.hasRedo()}function v(){if(void 0===t)return;const e=function(e){var t=e.getValue();try{var n=JSON.parse(t);return JSON.stringify(n)}catch(e){return t+""}}(c),n=new FormData;n.append("data",new Blob([e],{type:a}),t),fetch("/edit",{method:"POST",body:n}).then((e=>e.ok?e.text().then((e=>{console.log("Save OK /edit "+e)})):e.text().then((e=>{throw console.log("Save FAIL /edit"),new Error(e)})))).then((e=>{console.log(e),generateToast({message:"Saved "+t,background:"#ddd",color:"#000"})})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{y()}))}function x(){var e=c.getCopyText();if(window.clipboardData&&window.clipboardData.setData)return window.clipboardData.setData("Text",e);if(document.queryCommandSupported&&document.queryCommandSupported("copy")){c.focus();try{return document.execCommand("copy")}catch(t){return console.warn("Copy to clipboard failed.",t),prompt("Copy to clipboard: Ctrl+C, Enter",e)}}}function w(e){_("name").innerHTML=e;fetch(e).then((t=>t.ok?(console.log("OK "+e),t.text()):t.text().then((e=>{throw console.log("ERROR "+url),new Error(e)})))).then((e=>{try{var t=JSON.parse(e);c.setValue(JSON.stringify(t,null,4)),console.log("parse json OK")}catch(t){c.setValue(e),console.log("parse json FAIL")}null!==_("editor")&&(_("editor").style.display="block"),null!==_("preview")&&(_("preview").style.display="none"),g=!0,c.setReadOnly(!1),c.focus(),y()})).catch((e=>{console.log(e),alert(e),c.setReadOnly(!0)})).finally((()=>{c.resize(!0),c.scrollToLine(1,!0,!0,(function(){})),c.gotoLine(1,0,!0),c.clearSelection(),c.session.getUndoManager().reset()}))}return["Courier New","Monaco","Lucida Console","Monospace","ui-monospace","Roboto Mono","Inconsolata","IBM Plex Mono","Space Mono","PT Mono","Ubuntu Mono","Nanum Gothic Coding","Cousine","Fira Mono","Share Tech Mono","Courier Prime","Anonymous Pro","Cutive Mono","Overpass Mono","Fira Code","VT323","DM Mono","Oxygen Mono","Nova Mono","B612 Mono","Spline Sans Mono","Noto Sans Mono","Major Mono Display","Azeret Mono","Red Hat Mono","Syne Mono","Xanh Mono"].sort().forEach((function(e,t){if(doesFontExist(e)){var n=document.createElement("option");n.text=e,p.add(n)}})),null!==s&&null!==l&&null!==r&&c.on("input",y),c.session.selection.on("changeCursor",h),s.onclick=v,l.onclick=e=>{c.undo()&&c.focus()},r.onclick=e=>{c.redo()&&c.focus()},d.onclick=e=>{x()&&c.execCommand("cut")},m.onclick=e=>{x()&&c.execCommand("copy")},u.onclick=function(){try{navigator.clipboard.readText().then((e=>{c.execCommand("paste",e)})).catch((e=>{u.disabled=!0}))}catch{u.disabled=!0}},c.loadUrl=(e,o)=>{n=i(t=e+o),a="text/"+n,"plain"!==n&&c.getSession().setMode("ace/mode/"+n),w(e+o)},c.hide=()=>{g=!1,y(),h(),_("editor").style.display="none"},"plain"!==n&&c.getSession().setMode("ace/mode/"+n),c.setTheme("ace/theme/"+o),c.$blockScrolling=1/0,c.commands.addCommand({name:"save",bindKey:{win:"Ctrl-S",mac:"Command-S"},exec:v,readOnly:!1}),c.commands.addCommand({name:"undo",bindKey:{win:"Ctrl-Z",mac:"Command-Z"},exec:function(){c.undo()}}),c.commands.addCommand({name:"redo",bindKey:{win:"Ctrl-Y",mac:"Command-Y"},exec:function(){c.redo()}}),void 0!==t&&w(t),c.resize(),c}function uploadFileAsync(e,t,n,o,a,i){fetchData("/edit","POST",e).then((e=>{generateToast({message:"Upload "+n+"/"+o+" "+t+" done.",background:"#ddd",color:"#000"}),n==o&&listFiles(a,i)}))}function doUpload(e,t){const n=_("upload"),o=n.files.length;if(0!==o)for(let a=0;a=0}function isText(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"txt":case"cmd":case"json":case"jsonl":case"htm":case"html":case"js":case"c":case"cpp":case"css":case"svg":case"xml":return!0}return!1}function isImage(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"bmp":case"png":case"jpg":case"gif":case"svg":return!0}return!1}function isAudio(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"wav":case"mp3":case"aac":case"m4a":case"wma":return!0}return!1}function icon(e){if(isFolder(e))return"dir";if(isImage(e))return"image";if(isAudio(e))return"audio";var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"cmd":case"css":case"json":case"jsonl":case"ttf":return t;case"zip":case"gz":return"zip";case"html":case"htm":return"html"}return"file"}function preview(e,t){if(isImage(e)){let n=t+e.name;const o=_("preview");o.innerHTML='',o.style.display="block",ace.edit("editor").hide(),_("name").innerHTML=n}}function edit(e,t){isText(e)&&(ace.edit("editor").loadUrl(t,e.name),_("preview").style.display="none")}function url(e,t){console.log("click "+t+e.name),isImage(e)?preview(e,t):isText(e)&&edit(e,t)}async function fetchData(e,t,n,o){await fetch(e,{method:t,body:n}).then((n=>n.ok?(console.log(t+" OK "+e),n.text()):n.text().then((n=>{throw console.log(t+" FAIL "+e),new Error(n)})))).then((e=>{o&&o.remove(),console.log(e)})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{}))}function download(e,t){console.log("download "+t+e.name),document.getElementById("download-frame").src=t+e.name+"?download=true"}function remove(e,t,n){let o=t+e.name;isFolder(e)&&(o+="/"),console.log("remove "+o);const a=new FormData;a.append("path",o),fetchData("/edit","DELETE",a,n)}function create(e,t,n){var o=window.prompt("Create File in "+e,"");if(null==o||""==o||o.includes("/"))return;const a=new FormData;a.append("path",e+o),fetchData("/edit","PUT",a),fetch("/api/files/").then((e=>e.json())).then((o=>{t&&t.remove(),listFiles(n,e),console.log(o)}))}function upload(e,t){_("upload").onchange=()=>{doUpload(e,t)},_("upload").click()}function ctx(e,t,n,o){e.preventDefault(),ctx_el=o;let a,i=isFolder(t),c=_("ctx");c.style.display="block",a=c.getElementsByTagName("li")[0],a.onclick=i?function(){hidectx(),create(n+t.name+"/",o.children.item(1),o)}:function(){hidectx(),create(n,o.parentNode,o.parentNode.parentNode)},a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[1],i&&(a.onclick=function(){hidectx(),upload(o,n+t.name+"/")}),a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[2],a.onclick=function(){edit(t,n),hidectx()},a.style.display=isText(t)?"block":"none",a=c.getElementsByTagName("li")[3],a.onclick=function(){preview(t,n),hidectx()},a.style.display=isImage(t)?"block":"none",a=c.getElementsByTagName("li")[4],a.onclick=function(){download(t,n),hidectx()},a.style.display=i?"none":"block",a=c.getElementsByTagName("li")[5],a.onclick=function(){remove(t,n,o),hidectx()},a.style.display=n?"block":"none";var s=document.body.scrollTop?document.body.scrollTop:document.documentElement.scrollTop,l=document.body.scrollLeft?document.body.scrollLeft:document.documentElement.scrollLeft,r=e.clientX+l+10,d=e.clientY+s-20,m=(c.offsetWidth,c.offsetHeight),u=document.documentElement.clientHeight;d+m>u&&(d=u-m-20),c.style.left=r+"px",c.style.top=d+"px",o&&o.classList.add("selitem")}function drag(e,t,n){let o=n+t.name;isFolder(t)&&(o+="/"),e.dataTransfer.setData("text",o),console.log("drag start "+o)}function drop(e,t){let n=e.dataTransfer.getData("text");n.startsWith(t)||(e.preventDefault(),console.log("Move "+n+" to "+t))}function listFiles(e,t){return console.log("listFiles"),fetch("/api/files/?dir="+t).then((e=>e.json())).then((n=>{if(0==n.length)return!1;let o=e.getElementsByTagName("div")[0];o&&(o.onclick=n=>{i.remove(),o.onclick=()=>{listFiles(e,t)},n.stopPropagation()});let a=e.getElementsByTagName("ul");for(let e=0;e{drag(event,e,t)},a.appendChild(s),s.innerHTML=''+o+"",isFolder(e)){let n=t+e.name+"/";s.classList.add("bold"),s.onclick=function(e){listFiles(a,n)},s.ondragover=e=>{e.preventDefault()},s.ondrop=e=>{drop(e,n)}}else(isText(e)||isImage(e)||isAudio(e))&&(s.onclick=function(n){url(e,t)});s.oncontextmenu=n=>{ctx(n,e,t,a)}}return e.scrollIntoView(),!0}))}function generateToast({message:e,background:t="#00214d",color:n="#fffffe",length:o="7000ms"}){_("toast").insertAdjacentHTML("afterbegin",`

\n ${e}\n

`);const a=_("toast").firstElementChild;a.addEventListener("animationend",(()=>a.remove()))}document.addEventListener("blur",(function(){hidectx()})),document.addEventListener("DOMContentLoaded",(function(){createEditor("editor",void 0,void 0,void 0);listFiles(_("tree"),"/"),_("tree").getElementsByTagName("div")[0].oncontextmenu=e=>{ctx(e,{name:"",children:[]},"",_("tree"))},_("load").onclick=function(e){const t=new FormData;t.append("load",""),fetchData("/edit","PUT",t)},_("init").onclick=function(e){const t=new FormData;t.append("init",""),fetchData("/edit","PUT",t)},_("home").onclick=function(e){window.location.href="/"},_("page").onchange=function(e){const t=new FormData;t.append("page",_("page").value),fetchData("/edit","PUT",t)}})),document.addEventListener("DOMContentLoaded",(function(){const e=document.getElementById("dragMe"),t=e.previousElementSibling,n=e.nextElementSibling;let o=0,a=0,i=0;const c=function(a){const c=a.clientX-o,s=(a.clientY,100*(i+c)/e.parentNode.getBoundingClientRect().width);t.style.width=`${s}%`,t.style.right=t.style.width,e.style.cursor="col-resize",document.body.style.cursor="col-resize",t.style.userSelect="none",t.style.pointerEvents="none",n.style.userSelect="none",n.style.pointerEvents="none",ace.edit("editor").resize()},s=function(){e.style.removeProperty("cursor"),document.body.style.removeProperty("cursor"),t.style.removeProperty("user-select"),t.style.removeProperty("pointer-events"),n.style.removeProperty("user-select"),n.style.removeProperty("pointer-events"),document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",s)};e.addEventListener("mousedown",(function(e){o=e.clientX,a=e.clientY,i=t.getBoundingClientRect().width,document.addEventListener("mousemove",c),document.addEventListener("mouseup",s)})),e.addEventListener("dblclick",(()=>{var e=t.style.visibility="hidden"===t.style.visibility;t.style.visibility=e?"unset":"hidden",t.style.position=e?"unset":"absolute",ace.edit("editor").resize()}))})); \ No newline at end of file From aa09f4bfd43a396816d902428a12a2b940d2f486 Mon Sep 17 00:00:00 2001 From: FreeBear Date: Wed, 22 May 2024 00:51:02 +0100 Subject: [PATCH 11/55] Using size_t limits max number to 2^32. When dealing with SD cards we could be asked to print a uint64 (for example, from SD.totalGytes()). --- src/hasp/hasp_parser.cpp | 26 ++++++++++++++------------ src/hasp/hasp_parser.h | 2 +- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/hasp/hasp_parser.cpp b/src/hasp/hasp_parser.cpp index eee1175d..f6db3854 100644 --- a/src/hasp/hasp_parser.cpp +++ b/src/hasp/hasp_parser.cpp @@ -197,24 +197,26 @@ bool Parser::is_only_digits(const char* s) return strlen(s) == digits; } -int Parser::format_bytes(size_t filesize, char* buf, size_t len) +int Parser::format_bytes(uint64_t filesize, char* buf, size_t len) { - if(filesize < D_FILE_SIZE_DIVIDER) return snprintf_P(buf, len, PSTR("%d " D_FILE_SIZE_BYTES), filesize); - filesize = filesize * 100; + uint32_t tmp = (uint32_t) filesize; // cast to unsigned int here to saye ugly casts in next line + if(filesize < D_FILE_SIZE_DIVIDER) return snprintf_P(buf, len, PSTR("%u " D_FILE_SIZE_BYTES), tmp); - filesize = filesize / D_FILE_SIZE_DIVIDER; // multiply by 100 for 2 decimal place + filesize = filesize / (D_FILE_SIZE_DIVIDER/100); // multiply by 100 for 2 decimal place + tmp = (uint32_t) filesize; if(filesize < D_FILE_SIZE_DIVIDER * 100) - return snprintf_P(buf, len, PSTR("%d" D_DECIMAL_POINT "%02d " D_FILE_SIZE_KILOBYTES), filesize / 100, - filesize % 100); + return snprintf_P(buf, len, PSTR("%u" D_DECIMAL_POINT "%02u " D_FILE_SIZE_KILOBYTES), tmp / 100, + tmp % 100); - filesize = filesize / D_FILE_SIZE_DIVIDER; // multiply by 100 for 2 decimal place + filesize = filesize / D_FILE_SIZE_DIVIDER; + tmp = (uint32_t) filesize; if(filesize < D_FILE_SIZE_DIVIDER * 100) - return snprintf_P(buf, len, PSTR("%d" D_DECIMAL_POINT "%02d " D_FILE_SIZE_MEGABYTES), filesize / 100, - filesize % 100); + return snprintf_P(buf, len, PSTR("%u" D_DECIMAL_POINT "%02u " D_FILE_SIZE_MEGABYTES), tmp / 100, + tmp % 100); - filesize = filesize / D_FILE_SIZE_DIVIDER; // multiply by 100 for 2 decimal place - return snprintf_P(buf, len, PSTR("%d" D_DECIMAL_POINT "%02d " D_FILE_SIZE_GIGABYTES), filesize / 100, - filesize % 100); + tmp = (uint32_t) (filesize / D_FILE_SIZE_DIVIDER); + return snprintf_P(buf, len, PSTR("%u" D_DECIMAL_POINT "%02u " D_FILE_SIZE_GIGABYTES), tmp / 100, + tmp % 100); } uint8_t Parser::get_action_id(const char* action) diff --git a/src/hasp/hasp_parser.h b/src/hasp/hasp_parser.h index d1c44bea..84dcfd1b 100644 --- a/src/hasp/hasp_parser.h +++ b/src/hasp/hasp_parser.h @@ -19,7 +19,7 @@ class Parser { static bool is_true(const char* s); static bool is_true(JsonVariant json); static bool is_only_digits(const char* s); - static int format_bytes(size_t filesize, char* buf, size_t len); + static int format_bytes(uint64_t filesize, char* buf, size_t len); }; #ifndef ARDUINO From 33f3c3691576a187057aa98039d8812e77cdfe0b Mon Sep 17 00:00:00 2001 From: FreeBear Date: Wed, 22 May 2024 11:20:14 +0100 Subject: [PATCH 12/55] Take onboard comment about loss of precision. Using size_t would have overflowed at (approx) 2^28. But with a uint64_t the limit is going to be up in the Exbi range (2^60). --- src/hasp/hasp_parser.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/hasp/hasp_parser.cpp b/src/hasp/hasp_parser.cpp index f6db3854..2f79ffb6 100644 --- a/src/hasp/hasp_parser.cpp +++ b/src/hasp/hasp_parser.cpp @@ -199,22 +199,24 @@ bool Parser::is_only_digits(const char* s) int Parser::format_bytes(uint64_t filesize, char* buf, size_t len) { + filesize *= 100; // Warning - If filesize up in the Zi range (2^60), we will overflow. uint32_t tmp = (uint32_t) filesize; // cast to unsigned int here to saye ugly casts in next line if(filesize < D_FILE_SIZE_DIVIDER) return snprintf_P(buf, len, PSTR("%u " D_FILE_SIZE_BYTES), tmp); - filesize = filesize / (D_FILE_SIZE_DIVIDER/100); // multiply by 100 for 2 decimal place + filesize /= D_FILE_SIZE_DIVIDER; tmp = (uint32_t) filesize; if(filesize < D_FILE_SIZE_DIVIDER * 100) return snprintf_P(buf, len, PSTR("%u" D_DECIMAL_POINT "%02u " D_FILE_SIZE_KILOBYTES), tmp / 100, tmp % 100); - filesize = filesize / D_FILE_SIZE_DIVIDER; + filesize /= D_FILE_SIZE_DIVIDER; tmp = (uint32_t) filesize; - if(filesize < D_FILE_SIZE_DIVIDER * 100) + if(filesize < D_FILE_SIZE_DIVIDER * D_FILE_SIZE_DIVIDER * 100) return snprintf_P(buf, len, PSTR("%u" D_DECIMAL_POINT "%02u " D_FILE_SIZE_MEGABYTES), tmp / 100, tmp % 100); - tmp = (uint32_t) (filesize / D_FILE_SIZE_DIVIDER); + filesize /= D_FILE_SIZE_DIVIDER; + tmp = (uint32_t) filesize; return snprintf_P(buf, len, PSTR("%u" D_DECIMAL_POINT "%02u " D_FILE_SIZE_GIGABYTES), tmp / 100, tmp % 100); } From 7dc3de34f82454b255df143facd0c3ce67f1ad7a Mon Sep 17 00:00:00 2001 From: FreeBear Date: Wed, 22 May 2024 11:56:23 +0100 Subject: [PATCH 13/55] One too many file system dividers used for megabyte comparison. --- src/hasp/hasp_parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hasp/hasp_parser.cpp b/src/hasp/hasp_parser.cpp index 2f79ffb6..64e4729f 100644 --- a/src/hasp/hasp_parser.cpp +++ b/src/hasp/hasp_parser.cpp @@ -211,7 +211,7 @@ int Parser::format_bytes(uint64_t filesize, char* buf, size_t len) filesize /= D_FILE_SIZE_DIVIDER; tmp = (uint32_t) filesize; - if(filesize < D_FILE_SIZE_DIVIDER * D_FILE_SIZE_DIVIDER * 100) + if(filesize < D_FILE_SIZE_DIVIDER * 100) return snprintf_P(buf, len, PSTR("%u" D_DECIMAL_POINT "%02u " D_FILE_SIZE_MEGABYTES), tmp / 100, tmp % 100); From b65bd46b411b44c44a8b51b3310b942a66f7e118 Mon Sep 17 00:00:00 2001 From: FreeBear Date: Wed, 22 May 2024 12:18:03 +0100 Subject: [PATCH 14/55] 2^60 is Exbi (Ei) not Zebi (Zi) --- src/hasp/hasp_parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hasp/hasp_parser.cpp b/src/hasp/hasp_parser.cpp index 64e4729f..fb557cc5 100644 --- a/src/hasp/hasp_parser.cpp +++ b/src/hasp/hasp_parser.cpp @@ -199,7 +199,7 @@ bool Parser::is_only_digits(const char* s) int Parser::format_bytes(uint64_t filesize, char* buf, size_t len) { - filesize *= 100; // Warning - If filesize up in the Zi range (2^60), we will overflow. + filesize *= 100; // Warning - If filesize up in the Ei range (2^60), we will overflow. uint32_t tmp = (uint32_t) filesize; // cast to unsigned int here to saye ugly casts in next line if(filesize < D_FILE_SIZE_DIVIDER) return snprintf_P(buf, len, PSTR("%u " D_FILE_SIZE_BYTES), tmp); From 452c619e97c66698112641503d4a1bb419461e57 Mon Sep 17 00:00:00 2001 From: FreeBear Date: Wed, 22 May 2024 12:44:36 +0100 Subject: [PATCH 15/55] Use a const char* array for format_bytes suffixes at the expense of a little more system memory. --- src/hasp/hasp_parser.cpp | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/src/hasp/hasp_parser.cpp b/src/hasp/hasp_parser.cpp index fb557cc5..ae5fe88c 100644 --- a/src/hasp/hasp_parser.cpp +++ b/src/hasp/hasp_parser.cpp @@ -203,22 +203,14 @@ int Parser::format_bytes(uint64_t filesize, char* buf, size_t len) uint32_t tmp = (uint32_t) filesize; // cast to unsigned int here to saye ugly casts in next line if(filesize < D_FILE_SIZE_DIVIDER) return snprintf_P(buf, len, PSTR("%u " D_FILE_SIZE_BYTES), tmp); - filesize /= D_FILE_SIZE_DIVIDER; + const char* suffix[] = {D_FILE_SIZE_KILOBYTES, D_FILE_SIZE_MEGABYTES, D_FILE_SIZE_GIGABYTES}; + int n = -1; + while (filesize > D_FILE_SIZE_DIVIDER * 100) { + n += 1; + filesize /= D_FILE_SIZE_DIVIDER; + } tmp = (uint32_t) filesize; - if(filesize < D_FILE_SIZE_DIVIDER * 100) - return snprintf_P(buf, len, PSTR("%u" D_DECIMAL_POINT "%02u " D_FILE_SIZE_KILOBYTES), tmp / 100, - tmp % 100); - - filesize /= D_FILE_SIZE_DIVIDER; - tmp = (uint32_t) filesize; - if(filesize < D_FILE_SIZE_DIVIDER * 100) - return snprintf_P(buf, len, PSTR("%u" D_DECIMAL_POINT "%02u " D_FILE_SIZE_MEGABYTES), tmp / 100, - tmp % 100); - - filesize /= D_FILE_SIZE_DIVIDER; - tmp = (uint32_t) filesize; - return snprintf_P(buf, len, PSTR("%u" D_DECIMAL_POINT "%02u " D_FILE_SIZE_GIGABYTES), tmp / 100, - tmp % 100); + return snprintf_P(buf, len, PSTR("%u" D_DECIMAL_POINT "%02u %s"), tmp / 100, tmp % 100, suffix[n]); } uint8_t Parser::get_action_id(const char* action) From e37ca4c318e41e767f6d76fff3e2277700146906 Mon Sep 17 00:00:00 2001 From: FreeBear Date: Wed, 22 May 2024 15:21:44 +0100 Subject: [PATCH 16/55] Just in case file size in the TiB range gets passed, make sure we don't index beyond the end of the array. --- src/hasp/hasp_parser.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hasp/hasp_parser.cpp b/src/hasp/hasp_parser.cpp index ae5fe88c..b3966380 100644 --- a/src/hasp/hasp_parser.cpp +++ b/src/hasp/hasp_parser.cpp @@ -199,16 +199,18 @@ bool Parser::is_only_digits(const char* s) int Parser::format_bytes(uint64_t filesize, char* buf, size_t len) { - filesize *= 100; // Warning - If filesize up in the Ei range (2^60), we will overflow. + filesize *= 102400; // Warning - If filesize up in the Ei range (2^60), we will overflow. uint32_t tmp = (uint32_t) filesize; // cast to unsigned int here to saye ugly casts in next line if(filesize < D_FILE_SIZE_DIVIDER) return snprintf_P(buf, len, PSTR("%u " D_FILE_SIZE_BYTES), tmp); - const char* suffix[] = {D_FILE_SIZE_KILOBYTES, D_FILE_SIZE_MEGABYTES, D_FILE_SIZE_GIGABYTES}; + const char* suffix[] = {D_FILE_SIZE_KILOBYTES, D_FILE_SIZE_MEGABYTES, D_FILE_SIZE_GIGABYTES, "oops"}; + #define UNKNOWN_SUFFIX 2 int n = -1; - while (filesize > D_FILE_SIZE_DIVIDER * 100) { + while (filesize > D_FILE_SIZE_DIVIDER * 100 && n < UNKNOWN_SUFFIX) { n += 1; filesize /= D_FILE_SIZE_DIVIDER; } + tmp = (uint32_t) filesize; return snprintf_P(buf, len, PSTR("%u" D_DECIMAL_POINT "%02u %s"), tmp / 100, tmp % 100, suffix[n]); } From fcd99682b32358be20f8749741f87cb27f30904a Mon Sep 17 00:00:00 2001 From: FreeBear Date: Wed, 22 May 2024 15:26:31 +0100 Subject: [PATCH 17/55] Forgot to roll back on a test. --- src/hasp/hasp_parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hasp/hasp_parser.cpp b/src/hasp/hasp_parser.cpp index b3966380..6177164d 100644 --- a/src/hasp/hasp_parser.cpp +++ b/src/hasp/hasp_parser.cpp @@ -199,7 +199,7 @@ bool Parser::is_only_digits(const char* s) int Parser::format_bytes(uint64_t filesize, char* buf, size_t len) { - filesize *= 102400; // Warning - If filesize up in the Ei range (2^60), we will overflow. + filesize *= 100; // Warning - If filesize up in the Ei range (2^60), we will overflow. uint32_t tmp = (uint32_t) filesize; // cast to unsigned int here to saye ugly casts in next line if(filesize < D_FILE_SIZE_DIVIDER) return snprintf_P(buf, len, PSTR("%u " D_FILE_SIZE_BYTES), tmp); From cc1d6d9458f326dcdcfc4d50d0f0e23ff1e171b1 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Wed, 22 May 2024 18:28:53 +0200 Subject: [PATCH 18/55] Refactor format_bytes --- src/hasp/hasp_parser.cpp | 24 ++++++++++++++---------- src/lang/en_US.h | 1 + 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/hasp/hasp_parser.cpp b/src/hasp/hasp_parser.cpp index 6177164d..bb29307d 100644 --- a/src/hasp/hasp_parser.cpp +++ b/src/hasp/hasp_parser.cpp @@ -199,20 +199,24 @@ bool Parser::is_only_digits(const char* s) int Parser::format_bytes(uint64_t filesize, char* buf, size_t len) { - filesize *= 100; // Warning - If filesize up in the Ei range (2^60), we will overflow. - uint32_t tmp = (uint32_t) filesize; // cast to unsigned int here to saye ugly casts in next line - if(filesize < D_FILE_SIZE_DIVIDER) return snprintf_P(buf, len, PSTR("%u " D_FILE_SIZE_BYTES), tmp); + const char* suffix[] = {D_FILE_SIZE_BYTES, D_FILE_SIZE_KILOBYTES, D_FILE_SIZE_MEGABYTES, D_FILE_SIZE_GIGABYTES, + D_FILE_SIZE_TERABYTES}; + uint32_t factor; + uint16_t remainder = 0; + uint8_t i = 0; + uint8_t last_index = (sizeof(suffix) / sizeof(suffix[0])) - 1; - const char* suffix[] = {D_FILE_SIZE_KILOBYTES, D_FILE_SIZE_MEGABYTES, D_FILE_SIZE_GIGABYTES, "oops"}; - #define UNKNOWN_SUFFIX 2 - int n = -1; - while (filesize > D_FILE_SIZE_DIVIDER * 100 && n < UNKNOWN_SUFFIX) { - n += 1; + while(filesize >= D_FILE_SIZE_DIVIDER && i < last_index) { + i += 1; + remainder = filesize % D_FILE_SIZE_DIVIDER; filesize /= D_FILE_SIZE_DIVIDER; } - tmp = (uint32_t) filesize; - return snprintf_P(buf, len, PSTR("%u" D_DECIMAL_POINT "%02u %s"), tmp / 100, tmp % 100, suffix[n]); + factor = (uint32_t)filesize; + if(i == 0) return snprintf_P(buf, len, PSTR("%u %s"), factor, suffix[i]); + + remainder = remainder * 100 / D_FILE_SIZE_DIVIDER; + return snprintf_P(buf, len, PSTR("%u" D_DECIMAL_POINT "%02u %s"), factor, remainder, suffix[i]); } uint8_t Parser::get_action_id(const char* action) diff --git a/src/lang/en_US.h b/src/lang/en_US.h index 13df8dbc..0ec1b257 100644 --- a/src/lang/en_US.h +++ b/src/lang/en_US.h @@ -30,6 +30,7 @@ #define D_FILE_SIZE_KILOBYTES "KiB" #define D_FILE_SIZE_MEGABYTES "MiB" #define D_FILE_SIZE_GIGABYTES "GiB" +#define D_FILE_SIZE_TERABYTES "TiB" #define D_FILE_SIZE_DIVIDER 1024 // kibi or kilo bytes #define D_DECIMAL_POINT "." // decimal comma or point From d2745abb444b64ece37b40ffc201879494f5dc5e Mon Sep 17 00:00:00 2001 From: fvanroie <15969459+fvanroie@users.noreply.github.com> Date: Wed, 22 May 2024 18:33:49 +0200 Subject: [PATCH 19/55] New translations en_us.h (Romanian) --- src/lang/ro_RO.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lang/ro_RO.h b/src/lang/ro_RO.h index 13df8dbc..0ec1b257 100644 --- a/src/lang/ro_RO.h +++ b/src/lang/ro_RO.h @@ -30,6 +30,7 @@ #define D_FILE_SIZE_KILOBYTES "KiB" #define D_FILE_SIZE_MEGABYTES "MiB" #define D_FILE_SIZE_GIGABYTES "GiB" +#define D_FILE_SIZE_TERABYTES "TiB" #define D_FILE_SIZE_DIVIDER 1024 // kibi or kilo bytes #define D_DECIMAL_POINT "." // decimal comma or point From 6d594e3d53bf7df419e812b70a0061b267f0d61d Mon Sep 17 00:00:00 2001 From: fvanroie <15969459+fvanroie@users.noreply.github.com> Date: Wed, 22 May 2024 18:33:50 +0200 Subject: [PATCH 20/55] New translations en_us.h (French) --- src/lang/fr_FR.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lang/fr_FR.h b/src/lang/fr_FR.h index f84d3995..a752cc6b 100644 --- a/src/lang/fr_FR.h +++ b/src/lang/fr_FR.h @@ -30,6 +30,7 @@ #define D_FILE_SIZE_KILOBYTES "Kio" #define D_FILE_SIZE_MEGABYTES "Mio" #define D_FILE_SIZE_GIGABYTES "Gio" +#define D_FILE_SIZE_TERABYTES "TiB" #define D_FILE_SIZE_DIVIDER 1024 // kibi or kilo bytes #define D_DECIMAL_POINT "," // decimal comma or point From 13095042dca58b0b4c51e97631838600660cb5cc Mon Sep 17 00:00:00 2001 From: fvanroie <15969459+fvanroie@users.noreply.github.com> Date: Wed, 22 May 2024 18:33:51 +0200 Subject: [PATCH 21/55] New translations en_us.h (Spanish) --- src/lang/es_ES.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lang/es_ES.h b/src/lang/es_ES.h index 613e47ba..af77f0d9 100644 --- a/src/lang/es_ES.h +++ b/src/lang/es_ES.h @@ -30,6 +30,7 @@ #define D_FILE_SIZE_KILOBYTES "KiB" // new #define D_FILE_SIZE_MEGABYTES "MiB" // new #define D_FILE_SIZE_GIGABYTES "GiB" // new +#define D_FILE_SIZE_TERABYTES "TiB" #define D_FILE_SIZE_DIVIDER 1024 // new, kibi or kilo bytes #define D_DECIMAL_POINT "," // new, decimal comma or point From 0e1d37c8591393ecd0c9250122734c7b85dd4d41 Mon Sep 17 00:00:00 2001 From: fvanroie <15969459+fvanroie@users.noreply.github.com> Date: Wed, 22 May 2024 18:33:52 +0200 Subject: [PATCH 22/55] New translations en_us.h (Danish) --- src/lang/da_DK.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lang/da_DK.h b/src/lang/da_DK.h index 13df8dbc..0ec1b257 100644 --- a/src/lang/da_DK.h +++ b/src/lang/da_DK.h @@ -30,6 +30,7 @@ #define D_FILE_SIZE_KILOBYTES "KiB" #define D_FILE_SIZE_MEGABYTES "MiB" #define D_FILE_SIZE_GIGABYTES "GiB" +#define D_FILE_SIZE_TERABYTES "TiB" #define D_FILE_SIZE_DIVIDER 1024 // kibi or kilo bytes #define D_DECIMAL_POINT "." // decimal comma or point From de4c1875c39ae2eea41a00e0d87945ea250c9fb7 Mon Sep 17 00:00:00 2001 From: fvanroie <15969459+fvanroie@users.noreply.github.com> Date: Wed, 22 May 2024 18:33:53 +0200 Subject: [PATCH 23/55] New translations en_us.h (German) --- src/lang/de_DE.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lang/de_DE.h b/src/lang/de_DE.h index efd70477..aa83e7b5 100644 --- a/src/lang/de_DE.h +++ b/src/lang/de_DE.h @@ -30,6 +30,7 @@ #define D_FILE_SIZE_KILOBYTES "KiB" #define D_FILE_SIZE_MEGABYTES "MiB" #define D_FILE_SIZE_GIGABYTES "GiB" +#define D_FILE_SIZE_TERABYTES "TiB" #define D_FILE_SIZE_DIVIDER 1024 // kibi or kilo bytes #define D_DECIMAL_POINT "," // decimal comma or point From 00df690a160c603776a02f2d3976d1d92d53fb3e Mon Sep 17 00:00:00 2001 From: fvanroie <15969459+fvanroie@users.noreply.github.com> Date: Wed, 22 May 2024 18:33:54 +0200 Subject: [PATCH 24/55] New translations en_us.h (Hungarian) --- src/lang/hu_HU.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lang/hu_HU.h b/src/lang/hu_HU.h index 13df8dbc..0ec1b257 100644 --- a/src/lang/hu_HU.h +++ b/src/lang/hu_HU.h @@ -30,6 +30,7 @@ #define D_FILE_SIZE_KILOBYTES "KiB" #define D_FILE_SIZE_MEGABYTES "MiB" #define D_FILE_SIZE_GIGABYTES "GiB" +#define D_FILE_SIZE_TERABYTES "TiB" #define D_FILE_SIZE_DIVIDER 1024 // kibi or kilo bytes #define D_DECIMAL_POINT "." // decimal comma or point From c088ddff8e8c75283e20cd9b428dcb4f78c21f87 Mon Sep 17 00:00:00 2001 From: fvanroie <15969459+fvanroie@users.noreply.github.com> Date: Wed, 22 May 2024 18:33:55 +0200 Subject: [PATCH 25/55] New translations en_us.h (Dutch) --- src/lang/nl_NL.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lang/nl_NL.h b/src/lang/nl_NL.h index 92e22846..79afa3d1 100644 --- a/src/lang/nl_NL.h +++ b/src/lang/nl_NL.h @@ -30,6 +30,7 @@ #define D_FILE_SIZE_KILOBYTES "KiB" #define D_FILE_SIZE_MEGABYTES "MiB" #define D_FILE_SIZE_GIGABYTES "GiB" +#define D_FILE_SIZE_TERABYTES "TiB" #define D_FILE_SIZE_DIVIDER 1024 // kibi or kilo bytes #define D_DECIMAL_POINT "," // decimal comma or point From ee5df54676c72dc3409e779f0b61a596f15873b8 Mon Sep 17 00:00:00 2001 From: fvanroie <15969459+fvanroie@users.noreply.github.com> Date: Wed, 22 May 2024 18:33:56 +0200 Subject: [PATCH 26/55] New translations en_us.h (Portuguese) --- src/lang/pt_PT.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lang/pt_PT.h b/src/lang/pt_PT.h index 265b26f0..f20c21ae 100644 --- a/src/lang/pt_PT.h +++ b/src/lang/pt_PT.h @@ -30,6 +30,7 @@ #define D_FILE_SIZE_KILOBYTES "KiB" // new #define D_FILE_SIZE_MEGABYTES "MiB" // new #define D_FILE_SIZE_GIGABYTES "GiB" // new +#define D_FILE_SIZE_TERABYTES "TiB" #define D_FILE_SIZE_DIVIDER 1024 // new, kibi or kilo bytes #define D_DECIMAL_POINT "." // new, decimal comma or point From fba1331c3be4b98fbc2ee338306776d4e1b88805 Mon Sep 17 00:00:00 2001 From: fvanroie <15969459+fvanroie@users.noreply.github.com> Date: Wed, 22 May 2024 18:33:57 +0200 Subject: [PATCH 27/55] New translations en_us.h (Chinese Simplified) --- src/lang/zh_CN.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lang/zh_CN.h b/src/lang/zh_CN.h index 13df8dbc..0ec1b257 100644 --- a/src/lang/zh_CN.h +++ b/src/lang/zh_CN.h @@ -30,6 +30,7 @@ #define D_FILE_SIZE_KILOBYTES "KiB" #define D_FILE_SIZE_MEGABYTES "MiB" #define D_FILE_SIZE_GIGABYTES "GiB" +#define D_FILE_SIZE_TERABYTES "TiB" #define D_FILE_SIZE_DIVIDER 1024 // kibi or kilo bytes #define D_DECIMAL_POINT "." // decimal comma or point From 83bdad83e571df9cf0b4e64464b85d13fa3d00f9 Mon Sep 17 00:00:00 2001 From: fvanroie <15969459+fvanroie@users.noreply.github.com> Date: Wed, 22 May 2024 18:33:58 +0200 Subject: [PATCH 28/55] New translations en_us.h (Portuguese, Brazilian) --- src/lang/pt_BR.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lang/pt_BR.h b/src/lang/pt_BR.h index 169e3a8d..54121409 100644 --- a/src/lang/pt_BR.h +++ b/src/lang/pt_BR.h @@ -30,6 +30,7 @@ #define D_FILE_SIZE_KILOBYTES "KiB" #define D_FILE_SIZE_MEGABYTES "MiB" #define D_FILE_SIZE_GIGABYTES "GiB" +#define D_FILE_SIZE_TERABYTES "TiB" #define D_FILE_SIZE_DIVIDER 1024 // kibi or kilo bytes #define D_DECIMAL_POINT "." // decimal comma or point From 1ea0752004eccd81d1be0b770aee918b319a58df Mon Sep 17 00:00:00 2001 From: fvanroie <15969459+fvanroie@users.noreply.github.com> Date: Wed, 22 May 2024 20:14:23 +0200 Subject: [PATCH 29/55] New translations en_us.h (French) --- src/lang/fr_FR.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lang/fr_FR.h b/src/lang/fr_FR.h index a752cc6b..51183b2f 100644 --- a/src/lang/fr_FR.h +++ b/src/lang/fr_FR.h @@ -30,7 +30,7 @@ #define D_FILE_SIZE_KILOBYTES "Kio" #define D_FILE_SIZE_MEGABYTES "Mio" #define D_FILE_SIZE_GIGABYTES "Gio" -#define D_FILE_SIZE_TERABYTES "TiB" +#define D_FILE_SIZE_TERABYTES "Tio" #define D_FILE_SIZE_DIVIDER 1024 // kibi or kilo bytes #define D_DECIMAL_POINT "," // decimal comma or point @@ -128,7 +128,7 @@ #define D_HTTP_HTTP_SETTINGS "Paramètres HTTP" #define D_HTTP_FTP_SETTINGS "Paramètres FTP" #define D_HTTP_WIFI_SETTINGS "Paramètres Wifi" -#define D_HTTP_WIREGUARD_SETTINGS "WireGuard Settings" +#define D_HTTP_WIREGUARD_SETTINGS "Paramètres WireGuard" #define D_HTTP_MQTT_SETTINGS "Paramètres MQTT" #define D_HTTP_GPIO_SETTINGS "Paramètres GPIO" #define D_HTTP_MDNS_SETTINGS "Paramètres mDNS" @@ -203,8 +203,8 @@ #define D_INFO_MAC_ADDRESS "Adresse MAC" #define D_INFO_GATEWAY "Passerelle" #define D_INFO_DNS_SERVER "Serveur DNS" -#define D_INFO_ENDPOINT_IP "Endpoint IP" -#define D_INFO_ENDPOINT_PORT "Endpoint Port" +#define D_INFO_ENDPOINT_IP "Adresse IP du point final" +#define D_INFO_ENDPOINT_IP "Port du point final" #define D_OOBE_MSG "Touchez l'écran pour configurer le WiFi ou branchez ce point d'accès:" #define D_OOBE_SCAN_TO_CONNECT "Scanner pour se connecter" @@ -217,8 +217,8 @@ #define D_WIFI_RSSI_WEAK "Faible" #define D_WIFI_RSSI_BAD "Très mauvais" -#define D_WG_INITIALIZED "Initialized" -#define D_WG_BAD_CONFIG "Missing or bad configuration" +#define D_WG_INITIALIZED "Initialisé" +#define D_WG_BAD_CONFIG "Configuration manquante ou incorrecte" #define D_GPIO_SWITCH "Interrupteur" #define D_GPIO_BUTTON "Bouton" From 646f8d91fe134f4bccc6e8501f18e7eb01f89ed9 Mon Sep 17 00:00:00 2001 From: fvanroie <15969459+fvanroie@users.noreply.github.com> Date: Wed, 22 May 2024 20:14:25 +0200 Subject: [PATCH 30/55] New translations en_us.h (Spanish) --- src/lang/es_ES.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lang/es_ES.h b/src/lang/es_ES.h index af77f0d9..acee2059 100644 --- a/src/lang/es_ES.h +++ b/src/lang/es_ES.h @@ -13,7 +13,7 @@ #define D_NO "No" // New #define D_ERROR_OUT_OF_MEMORY "Memory llena" -#define D_ERROR_UNKNOWN "Unknown error" +#define D_ERROR_UNKNOWN "Error desconocido" #define D_CONFIG_NOT_CHANGED "No hay cambios en la configuración" #define D_CONFIG_CHANGED "Configuración cambiada" @@ -128,7 +128,7 @@ #define D_HTTP_HTTP_SETTINGS "Ajustes HTTP" #define D_HTTP_HTTP_SETTINGS "Ajustes FTP" #define D_HTTP_WIFI_SETTINGS "Ajustes Wifi" -#define D_HTTP_WIREGUARD_SETTINGS "WireGuard Settings" +#define D_HTTP_GUI_SETTINGS "Ajustes WireGuard" #define D_HTTP_MQTT_SETTINGS "Ajustes MQTT" #define D_HTTP_GPIO_SETTINGS "Ajustes GPIO" #define D_HTTP_MDNS_SETTINGS "Ajustes mDNS" @@ -203,8 +203,8 @@ #define D_INFO_MAC_ADDRESS "Dirección MAC" #define D_INFO_GATEWAY "Gateway" #define D_INFO_DNS_SERVER "Servidor DNS" -#define D_INFO_ENDPOINT_IP "Endpoint IP" -#define D_INFO_ENDPOINT_PORT "Endpoint Port" +#define D_INFO_ENDPOINT_IP "IP de punto final" +#define D_INFO_ENDPOINT_PORT "Puerto de punto final" #define D_OOBE_MSG "Toque la pantalla para ajustar WiFi o conectarse a un punto de acceso" #define D_OOBE_SCAN_TO_CONNECT "Scanee para conectar" @@ -217,8 +217,8 @@ #define D_WIFI_RSSI_WEAK "Débil" #define D_WIFI_RSSI_BAD "Muy baka" -#define D_WG_INITIALIZED "Initialized" -#define D_WG_BAD_CONFIG "Missing or bad configuration" +#define D_WG_INITIALIZED "Inicializado" +#define D_WG_BAD_CONFIG "Falta o mala configuración" #define D_GPIO_SWITCH "Switch" #define D_GPIO_BUTTON "Botón" From 331c1d503d45c940353023b9470f3f421a0aa4ef Mon Sep 17 00:00:00 2001 From: fvanroie <15969459+fvanroie@users.noreply.github.com> Date: Wed, 22 May 2024 20:14:28 +0200 Subject: [PATCH 31/55] New translations en_us.h (Portuguese) --- src/lang/pt_PT.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lang/pt_PT.h b/src/lang/pt_PT.h index f20c21ae..757a1e2f 100644 --- a/src/lang/pt_PT.h +++ b/src/lang/pt_PT.h @@ -128,7 +128,7 @@ #define D_HTTP_HTTP_SETTINGS "Configurar HTTP" #define D_HTTP_FTP_SETTINGS "Configurar FTP" #define D_HTTP_WIFI_SETTINGS "Configurar Wifi" -#define D_HTTP_WIREGUARD_SETTINGS "WireGuard Settings" +#define D_HTTP_WIREGUARD_SETTINGS "Configurar WireGuard" #define D_HTTP_MQTT_SETTINGS "Configurar MQTT" #define D_HTTP_GPIO_SETTINGS "Configurar GPIO" #define D_HTTP_MDNS_SETTINGS "Configurar mDNS" @@ -217,8 +217,8 @@ #define D_WIFI_RSSI_BAD "Muito baixo" #define D_WIFI_RSSI_FAIR "Decente" -#define D_WG_INITIALIZED "Initialized" -#define D_WG_BAD_CONFIG "Missing or bad configuration" +#define D_WG_INITIALIZED "Inicializado" +#define D_WG_BAD_CONFIG "Configuração ausente ou ruim" #define D_GPIO_SWITCH "Interruptor" #define D_GPIO_BUTTON "Botão" From 92f682c6bd8620ae1222dc8f85d546dba0b6183e Mon Sep 17 00:00:00 2001 From: fvanroie <15969459+fvanroie@users.noreply.github.com> Date: Wed, 22 May 2024 20:14:30 +0200 Subject: [PATCH 32/55] New translations en.json (French) --- data/fr_FR.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/data/fr_FR.json b/data/fr_FR.json index 7247c2f6..aacaead0 100644 --- a/data/fr_FR.json +++ b/data/fr_FR.json @@ -86,13 +86,13 @@ "ssid": "SSID" }, "wg": { - "title": "WireGuard Settings", - "btn": "WireGuard Settings", - "vpnip": "VPN IP", - "privkey": "Private Key", - "host": "Remote IP", - "port": "Remote Port", - "pubkey": "Remote Public Key" + "title": "Paramètres WireGuard", + "btn": "Paramètres WireGuard", + "vpnip": "IP du VPN", + "privkey": "Clé Privée", + "host": "Adresse IP distante", + "port": "Port Distant", + "pubkey": "Clé publique distante" }, "mqtt": { "title": "Paramètres MQTT", From 983cf13fd0903ba9bc583fedfeb993e8b0b4ce76 Mon Sep 17 00:00:00 2001 From: fvanroie <15969459+fvanroie@users.noreply.github.com> Date: Wed, 22 May 2024 20:14:31 +0200 Subject: [PATCH 33/55] New translations en.json (Spanish) --- data/es_ES.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/data/es_ES.json b/data/es_ES.json index fa1292a2..7df5c933 100644 --- a/data/es_ES.json +++ b/data/es_ES.json @@ -86,13 +86,13 @@ "ssid": "SSID" }, "wg": { - "title": "WireGuard Settings", - "btn": "WireGuard Settings", - "vpnip": "VPN IP", - "privkey": "Private Key", - "host": "Remote IP", - "port": "Remote Port", - "pubkey": "Remote Public Key" + "title": "Ajustes de WireGuard", + "btn": "Ajustes de WireGuard", + "vpnip": "IP VPN", + "privkey": "Clave Privada", + "host": "IP Remota", + "port": "Puerto Remoto", + "pubkey": "Clave Pública Remota" }, "mqtt": { "title": "Ajustes MQTT", From cd3fa42fc09538c895e02f18ba20eda917da8700 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Wed, 22 May 2024 20:38:51 +0200 Subject: [PATCH 34/55] Update ace.js to 1.34.0 --- data/edit.htm | 2 +- data/script.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/edit.htm b/data/edit.htm index 3d0a9e5a..e15ab495 100644 --- a/data/edit.htm +++ b/data/edit.htm @@ -1 +1 @@ -openHASP File Editor
L:
  • New File
  • Upload Files
  • Edit
  • Preview
  • Download
  • Delete
\ No newline at end of file +openHASP File Editor
L:
  • New File
  • Upload Files
  • Edit
  • Preview
  • Download
  • Delete
\ No newline at end of file diff --git a/data/script.js b/data/script.js index c129c1e6..670b0d92 100644 --- a/data/script.js +++ b/data/script.js @@ -1 +1 @@ -var ctx_el;function _(e){return document.getElementById(e)}function hidectx(){_("ctx").style.display="none",ctx_el&&ctx_el.classList.remove("selitem"),ctx_el=void 0}function doesFontExist(e){var t=document.createElement("canvas"),n=t.getContext("2d"),o="abcdefghijklmnopqrstuvwxyz0123456789";n.font="72px monospace";var a=n.measureText(o).width;return n.font="72px '"+e+"', monospace",t=null,n.measureText(o).width!=a}function createEditor(e,t,n,o,a){function i(e){let t=/(?:\.([^.]+))?$/.exec(e)[1];if(void 0!==typeof t)switch(t){case"htm":case"html":return"html";case"js":return"javascript";case"cmd":case"json":case"jsonl":return"json";case"css":case"svg":case"xml":return t}return"plain_text"}void 0===n&&(n=i(t)),void 0===a&&(a="text/"+n);["basePath","modePath","themePath"].forEach((e=>{ace.config.set(e,"https://cdnjs.cloudflare.com/ajax/libs/ace/1.33.3")}));var c=ace.edit(e,{useWorker:!1,wrap:!0,indentedSoftWrap:!1,showPrintMargin:!1,highlightGutterLine:!0,useSoftTabs:!0,tabSize:2});c.setFontSize(parseFloat(getComputedStyle(document.documentElement).fontSize)),c.setReadOnly(!0),c.getSession().setUndoManager(new ace.UndoManager),void 0===o&&(o=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"monokai":"textmate");var s=_("save"),l=_("undo"),r=_("redo"),d=_("cut"),m=_("copy"),u=_("paste"),p=_("font"),f=_("fontsize"),g="none"!==_(e).display;f.value=parseFloat(c.getFontSize()).toFixed(1),p.onchange=function(){c.setOption("fontFamily","'"+p.value+"',monospace")},f.onchange=function(){var e=parseFloat(f.value);!isNaN(e)&&e>=9&&e<=40&&c.setFontSize(e),f.value=parseFloat(c.getFontSize()).toFixed(1)};function h(){let e=!g||c.session.getSelection().isEmpty();d.disabled=e,m.disabled=e}function y(){let e=c.session.getUndoManager();s.disabled=!g||e.isClean(),l.disabled=!g||!e.hasUndo(),r.disabled=!g||!e.hasRedo()}function v(){if(void 0===t)return;const e=function(e){var t=e.getValue();try{var n=JSON.parse(t);return JSON.stringify(n)}catch(e){return t+""}}(c),n=new FormData;n.append("data",new Blob([e],{type:a}),t),fetch("/edit",{method:"POST",body:n}).then((e=>e.ok?e.text().then((e=>{console.log("Save OK /edit "+e)})):e.text().then((e=>{throw console.log("Save FAIL /edit"),new Error(e)})))).then((e=>{console.log(e),generateToast({message:"Saved "+t,background:"#ddd",color:"#000"})})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{y()}))}function x(){var e=c.getCopyText();if(window.clipboardData&&window.clipboardData.setData)return window.clipboardData.setData("Text",e);if(document.queryCommandSupported&&document.queryCommandSupported("copy")){c.focus();try{return document.execCommand("copy")}catch(t){return console.warn("Copy to clipboard failed.",t),prompt("Copy to clipboard: Ctrl+C, Enter",e)}}}function w(e){_("name").innerHTML=e;fetch(e).then((t=>t.ok?(console.log("OK "+e),t.text()):t.text().then((e=>{throw console.log("ERROR "+url),new Error(e)})))).then((e=>{try{var t=JSON.parse(e);c.setValue(JSON.stringify(t,null,4)),console.log("parse json OK")}catch(t){c.setValue(e),console.log("parse json FAIL")}null!==_("editor")&&(_("editor").style.display="block"),null!==_("preview")&&(_("preview").style.display="none"),g=!0,c.setReadOnly(!1),c.focus(),y()})).catch((e=>{console.log(e),alert(e),c.setReadOnly(!0)})).finally((()=>{c.resize(!0),c.scrollToLine(1,!0,!0,(function(){})),c.gotoLine(1,0,!0),c.clearSelection(),c.session.getUndoManager().reset()}))}return["Courier New","Monaco","Lucida Console","Monospace","ui-monospace","Roboto Mono","Inconsolata","IBM Plex Mono","Space Mono","PT Mono","Ubuntu Mono","Nanum Gothic Coding","Cousine","Fira Mono","Share Tech Mono","Courier Prime","Anonymous Pro","Cutive Mono","Overpass Mono","Fira Code","VT323","DM Mono","Oxygen Mono","Nova Mono","B612 Mono","Spline Sans Mono","Noto Sans Mono","Major Mono Display","Azeret Mono","Red Hat Mono","Syne Mono","Xanh Mono"].sort().forEach((function(e,t){if(doesFontExist(e)){var n=document.createElement("option");n.text=e,p.add(n)}})),null!==s&&null!==l&&null!==r&&c.on("input",y),c.session.selection.on("changeCursor",h),s.onclick=v,l.onclick=e=>{c.undo()&&c.focus()},r.onclick=e=>{c.redo()&&c.focus()},d.onclick=e=>{x()&&c.execCommand("cut")},m.onclick=e=>{x()&&c.execCommand("copy")},u.onclick=function(){try{navigator.clipboard.readText().then((e=>{c.execCommand("paste",e)})).catch((e=>{u.disabled=!0}))}catch{u.disabled=!0}},c.loadUrl=(e,o)=>{n=i(t=e+o),a="text/"+n,"plain"!==n&&c.getSession().setMode("ace/mode/"+n),w(e+o)},c.hide=()=>{g=!1,y(),h(),_("editor").style.display="none"},"plain"!==n&&c.getSession().setMode("ace/mode/"+n),c.setTheme("ace/theme/"+o),c.$blockScrolling=1/0,c.commands.addCommand({name:"save",bindKey:{win:"Ctrl-S",mac:"Command-S"},exec:v,readOnly:!1}),c.commands.addCommand({name:"undo",bindKey:{win:"Ctrl-Z",mac:"Command-Z"},exec:function(){c.undo()}}),c.commands.addCommand({name:"redo",bindKey:{win:"Ctrl-Y",mac:"Command-Y"},exec:function(){c.redo()}}),void 0!==t&&w(t),c.resize(),c}function uploadFileAsync(e,t,n,o,a,i){fetchData("/edit","POST",e).then((e=>{generateToast({message:"Upload "+n+"/"+o+" "+t+" done.",background:"#ddd",color:"#000"}),n==o&&listFiles(a,i)}))}function doUpload(e,t){const n=_("upload"),o=n.files.length;if(0!==o)for(let a=0;a=0}function isText(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"txt":case"cmd":case"json":case"jsonl":case"htm":case"html":case"js":case"c":case"cpp":case"css":case"svg":case"xml":return!0}return!1}function isImage(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"bmp":case"png":case"jpg":case"gif":case"svg":return!0}return!1}function isAudio(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"wav":case"mp3":case"aac":case"m4a":case"wma":return!0}return!1}function icon(e){if(isFolder(e))return"dir";if(isImage(e))return"image";if(isAudio(e))return"audio";var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"cmd":case"css":case"json":case"jsonl":case"ttf":return t;case"zip":case"gz":return"zip";case"html":case"htm":return"html"}return"file"}function preview(e,t){if(isImage(e)){let n=t+e.name;const o=_("preview");o.innerHTML='',o.style.display="block",ace.edit("editor").hide(),_("name").innerHTML=n}}function edit(e,t){isText(e)&&(ace.edit("editor").loadUrl(t,e.name),_("preview").style.display="none")}function url(e,t){console.log("click "+t+e.name),isImage(e)?preview(e,t):isText(e)&&edit(e,t)}async function fetchData(e,t,n,o){await fetch(e,{method:t,body:n}).then((n=>n.ok?(console.log(t+" OK "+e),n.text()):n.text().then((n=>{throw console.log(t+" FAIL "+e),new Error(n)})))).then((e=>{o&&o.remove(),console.log(e)})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{}))}function download(e,t){console.log("download "+t+e.name),document.getElementById("download-frame").src=t+e.name+"?download=true"}function remove(e,t,n){let o=t+e.name;isFolder(e)&&(o+="/"),console.log("remove "+o);const a=new FormData;a.append("path",o),fetchData("/edit","DELETE",a,n)}function create(e,t,n){var o=window.prompt("Create File in "+e,"");if(null==o||""==o||o.includes("/"))return;const a=new FormData;a.append("path",e+o),fetchData("/edit","PUT",a),fetch("/api/files/").then((e=>e.json())).then((o=>{t&&t.remove(),listFiles(n,e),console.log(o)}))}function upload(e,t){_("upload").onchange=()=>{doUpload(e,t)},_("upload").click()}function ctx(e,t,n,o){e.preventDefault(),ctx_el=o;let a,i=isFolder(t),c=_("ctx");c.style.display="block",a=c.getElementsByTagName("li")[0],a.onclick=i?function(){hidectx(),create(n+t.name+"/",o.children.item(1),o)}:function(){hidectx(),create(n,o.parentNode,o.parentNode.parentNode)},a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[1],i&&(a.onclick=function(){hidectx(),upload(o,n+t.name+"/")}),a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[2],a.onclick=function(){edit(t,n),hidectx()},a.style.display=isText(t)?"block":"none",a=c.getElementsByTagName("li")[3],a.onclick=function(){preview(t,n),hidectx()},a.style.display=isImage(t)?"block":"none",a=c.getElementsByTagName("li")[4],a.onclick=function(){download(t,n),hidectx()},a.style.display=i?"none":"block",a=c.getElementsByTagName("li")[5],a.onclick=function(){remove(t,n,o),hidectx()},a.style.display=n?"block":"none";var s=document.body.scrollTop?document.body.scrollTop:document.documentElement.scrollTop,l=document.body.scrollLeft?document.body.scrollLeft:document.documentElement.scrollLeft,r=e.clientX+l+10,d=e.clientY+s-20,m=(c.offsetWidth,c.offsetHeight),u=document.documentElement.clientHeight;d+m>u&&(d=u-m-20),c.style.left=r+"px",c.style.top=d+"px",o&&o.classList.add("selitem")}function drag(e,t,n){let o=n+t.name;isFolder(t)&&(o+="/"),e.dataTransfer.setData("text",o),console.log("drag start "+o)}function drop(e,t){let n=e.dataTransfer.getData("text");n.startsWith(t)||(e.preventDefault(),console.log("Move "+n+" to "+t))}function listFiles(e,t){return console.log("listFiles"),fetch("/api/files/?dir="+t).then((e=>e.json())).then((n=>{if(0==n.length)return!1;let o=e.getElementsByTagName("div")[0];o&&(o.onclick=n=>{i.remove(),o.onclick=()=>{listFiles(e,t)},n.stopPropagation()});let a=e.getElementsByTagName("ul");for(let e=0;e{drag(event,e,t)},a.appendChild(s),s.innerHTML=''+o+"",isFolder(e)){let n=t+e.name+"/";s.classList.add("bold"),s.onclick=function(e){listFiles(a,n)},s.ondragover=e=>{e.preventDefault()},s.ondrop=e=>{drop(e,n)}}else(isText(e)||isImage(e)||isAudio(e))&&(s.onclick=function(n){url(e,t)});s.oncontextmenu=n=>{ctx(n,e,t,a)}}return e.scrollIntoView(),!0}))}function generateToast({message:e,background:t="#00214d",color:n="#fffffe",length:o="7000ms"}){_("toast").insertAdjacentHTML("afterbegin",`

\n ${e}\n

`);const a=_("toast").firstElementChild;a.addEventListener("animationend",(()=>a.remove()))}document.addEventListener("blur",(function(){hidectx()})),document.addEventListener("DOMContentLoaded",(function(){createEditor("editor",void 0,void 0,void 0);listFiles(_("tree"),"/"),_("tree").getElementsByTagName("div")[0].oncontextmenu=e=>{ctx(e,{name:"",children:[]},"",_("tree"))},_("load").onclick=function(e){const t=new FormData;t.append("load",""),fetchData("/edit","PUT",t)},_("init").onclick=function(e){const t=new FormData;t.append("init",""),fetchData("/edit","PUT",t)},_("home").onclick=function(e){window.location.href="/"},_("page").onchange=function(e){const t=new FormData;t.append("page",_("page").value),fetchData("/edit","PUT",t)}})),document.addEventListener("DOMContentLoaded",(function(){const e=document.getElementById("dragMe"),t=e.previousElementSibling,n=e.nextElementSibling;let o=0,a=0,i=0;const c=function(a){const c=a.clientX-o,s=(a.clientY,100*(i+c)/e.parentNode.getBoundingClientRect().width);t.style.width=`${s}%`,t.style.right=t.style.width,e.style.cursor="col-resize",document.body.style.cursor="col-resize",t.style.userSelect="none",t.style.pointerEvents="none",n.style.userSelect="none",n.style.pointerEvents="none",ace.edit("editor").resize()},s=function(){e.style.removeProperty("cursor"),document.body.style.removeProperty("cursor"),t.style.removeProperty("user-select"),t.style.removeProperty("pointer-events"),n.style.removeProperty("user-select"),n.style.removeProperty("pointer-events"),document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",s)};e.addEventListener("mousedown",(function(e){o=e.clientX,a=e.clientY,i=t.getBoundingClientRect().width,document.addEventListener("mousemove",c),document.addEventListener("mouseup",s)})),e.addEventListener("dblclick",(()=>{var e=t.style.visibility="hidden"===t.style.visibility;t.style.visibility=e?"unset":"hidden",t.style.position=e?"unset":"absolute",ace.edit("editor").resize()}))})); \ No newline at end of file +var ctx_el;function _(e){return document.getElementById(e)}function hidectx(){_("ctx").style.display="none",ctx_el&&ctx_el.classList.remove("selitem"),ctx_el=void 0}function doesFontExist(e){var t=document.createElement("canvas"),n=t.getContext("2d"),o="abcdefghijklmnopqrstuvwxyz0123456789";n.font="72px monospace";var a=n.measureText(o).width;return n.font="72px '"+e+"', monospace",t=null,n.measureText(o).width!=a}function createEditor(e,t,n,o,a){function i(e){let t=/(?:\.([^.]+))?$/.exec(e)[1];if(void 0!==typeof t)switch(t){case"htm":case"html":return"html";case"js":return"javascript";case"cmd":case"json":case"jsonl":return"json";case"css":case"svg":case"xml":return t}return"plain_text"}void 0===n&&(n=i(t)),void 0===a&&(a="text/"+n);["basePath","modePath","themePath"].forEach((e=>{ace.config.set(e,"https://cdnjs.cloudflare.com/ajax/libs/ace/1.34.0")}));var c=ace.edit(e,{useWorker:!1,wrap:!0,indentedSoftWrap:!1,showPrintMargin:!1,highlightGutterLine:!0,useSoftTabs:!0,tabSize:2});c.setFontSize(parseFloat(getComputedStyle(document.documentElement).fontSize)),c.setReadOnly(!0),c.getSession().setUndoManager(new ace.UndoManager),void 0===o&&(o=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"monokai":"textmate");var s=_("save"),l=_("undo"),r=_("redo"),d=_("cut"),m=_("copy"),u=_("paste"),p=_("font"),f=_("fontsize"),g="none"!==_(e).display;f.value=parseFloat(c.getFontSize()).toFixed(1),p.onchange=function(){c.setOption("fontFamily","'"+p.value+"',monospace")},f.onchange=function(){var e=parseFloat(f.value);!isNaN(e)&&e>=9&&e<=40&&c.setFontSize(e),f.value=parseFloat(c.getFontSize()).toFixed(1)};function h(){let e=!g||c.session.getSelection().isEmpty();d.disabled=e,m.disabled=e}function y(){let e=c.session.getUndoManager();s.disabled=!g||e.isClean(),l.disabled=!g||!e.hasUndo(),r.disabled=!g||!e.hasRedo()}function v(){if(void 0===t)return;const e=function(e){var t=e.getValue();try{var n=JSON.parse(t);return JSON.stringify(n)}catch(e){return t+""}}(c),n=new FormData;n.append("data",new Blob([e],{type:a}),t),fetch("/edit",{method:"POST",body:n}).then((e=>e.ok?e.text().then((e=>{console.log("Save OK /edit "+e)})):e.text().then((e=>{throw console.log("Save FAIL /edit"),new Error(e)})))).then((e=>{console.log(e),generateToast({message:"Saved "+t,background:"#ddd",color:"#000"})})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{y()}))}function x(){var e=c.getCopyText();if(window.clipboardData&&window.clipboardData.setData)return window.clipboardData.setData("Text",e);if(document.queryCommandSupported&&document.queryCommandSupported("copy")){c.focus();try{return document.execCommand("copy")}catch(t){return console.warn("Copy to clipboard failed.",t),prompt("Copy to clipboard: Ctrl+C, Enter",e)}}}function w(e){_("name").innerHTML=e;fetch(e).then((t=>t.ok?(console.log("OK "+e),t.text()):t.text().then((e=>{throw console.log("ERROR "+url),new Error(e)})))).then((e=>{try{var t=JSON.parse(e);c.setValue(JSON.stringify(t,null,4)),console.log("parse json OK")}catch(t){c.setValue(e),console.log("parse json FAIL")}null!==_("editor")&&(_("editor").style.display="block"),null!==_("preview")&&(_("preview").style.display="none"),g=!0,c.setReadOnly(!1),c.focus(),y()})).catch((e=>{console.log(e),alert(e),c.setReadOnly(!0)})).finally((()=>{c.resize(!0),c.scrollToLine(1,!0,!0,(function(){})),c.gotoLine(1,0,!0),c.clearSelection(),c.session.getUndoManager().reset()}))}return["Courier New","Monaco","Lucida Console","Monospace","ui-monospace","Roboto Mono","Inconsolata","IBM Plex Mono","Space Mono","PT Mono","Ubuntu Mono","Nanum Gothic Coding","Cousine","Fira Mono","Share Tech Mono","Courier Prime","Anonymous Pro","Cutive Mono","Overpass Mono","Fira Code","VT323","DM Mono","Oxygen Mono","Nova Mono","B612 Mono","Spline Sans Mono","Noto Sans Mono","Major Mono Display","Azeret Mono","Red Hat Mono","Syne Mono","Xanh Mono"].sort().forEach((function(e,t){if(doesFontExist(e)){var n=document.createElement("option");n.text=e,p.add(n)}})),null!==s&&null!==l&&null!==r&&c.on("input",y),c.session.selection.on("changeCursor",h),s.onclick=v,l.onclick=e=>{c.undo()&&c.focus()},r.onclick=e=>{c.redo()&&c.focus()},d.onclick=e=>{x()&&c.execCommand("cut")},m.onclick=e=>{x()&&c.execCommand("copy")},u.onclick=function(){try{navigator.clipboard.readText().then((e=>{c.execCommand("paste",e)})).catch((e=>{u.disabled=!0}))}catch{u.disabled=!0}},c.loadUrl=(e,o)=>{n=i(t=e+o),a="text/"+n,"plain"!==n&&c.getSession().setMode("ace/mode/"+n),w(e+o)},c.hide=()=>{g=!1,y(),h(),_("editor").style.display="none"},"plain"!==n&&c.getSession().setMode("ace/mode/"+n),c.setTheme("ace/theme/"+o),c.$blockScrolling=1/0,c.commands.addCommand({name:"save",bindKey:{win:"Ctrl-S",mac:"Command-S"},exec:v,readOnly:!1}),c.commands.addCommand({name:"undo",bindKey:{win:"Ctrl-Z",mac:"Command-Z"},exec:function(){c.undo()}}),c.commands.addCommand({name:"redo",bindKey:{win:"Ctrl-Y",mac:"Command-Y"},exec:function(){c.redo()}}),void 0!==t&&w(t),c.resize(),c}function uploadFileAsync(e,t,n,o,a,i){fetchData("/edit","POST",e).then((e=>{generateToast({message:"Upload "+n+"/"+o+" "+t+" done.",background:"#ddd",color:"#000"}),n==o&&listFiles(a,i)}))}function doUpload(e,t){const n=_("upload"),o=n.files.length;if(0!==o)for(let a=0;a=0}function isText(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"txt":case"cmd":case"json":case"jsonl":case"htm":case"html":case"js":case"c":case"cpp":case"css":case"svg":case"xml":return!0}return!1}function isImage(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"bmp":case"png":case"jpg":case"gif":case"svg":return!0}return!1}function isAudio(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"wav":case"mp3":case"aac":case"m4a":case"wma":return!0}return!1}function icon(e){if(isFolder(e))return"dir";if(isImage(e))return"image";if(isAudio(e))return"audio";var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"cmd":case"css":case"json":case"jsonl":case"ttf":return t;case"zip":case"gz":return"zip";case"html":case"htm":return"html"}return"file"}function preview(e,t){if(isImage(e)){let n=t+e.name;const o=_("preview");o.innerHTML='',o.style.display="block",ace.edit("editor").hide(),_("name").innerHTML=n}}function edit(e,t){isText(e)&&(ace.edit("editor").loadUrl(t,e.name),_("preview").style.display="none")}function url(e,t){console.log("click "+t+e.name),isImage(e)?preview(e,t):isText(e)&&edit(e,t)}async function fetchData(e,t,n,o){await fetch(e,{method:t,body:n}).then((n=>n.ok?(console.log(t+" OK "+e),n.text()):n.text().then((n=>{throw console.log(t+" FAIL "+e),new Error(n)})))).then((e=>{o&&o.remove(),console.log(e)})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{}))}function download(e,t){console.log("download "+t+e.name),document.getElementById("download-frame").src=t+e.name+"?download=true"}function remove(e,t,n){let o=t+e.name;isFolder(e)&&(o+="/"),console.log("remove "+o);const a=new FormData;a.append("path",o),fetchData("/edit","DELETE",a,n)}function create(e,t,n){var o=window.prompt("Create File in "+e,"");if(null==o||""==o||o.includes("/"))return;const a=new FormData;a.append("path",e+o),fetchData("/edit","PUT",a),fetch("/api/files/").then((e=>e.json())).then((o=>{t&&t.remove(),listFiles(n,e),console.log(o)}))}function upload(e,t){_("upload").onchange=()=>{doUpload(e,t)},_("upload").click()}function ctx(e,t,n,o){e.preventDefault(),ctx_el=o;let a,i=isFolder(t),c=_("ctx");c.style.display="block",a=c.getElementsByTagName("li")[0],a.onclick=i?function(){hidectx(),create(n+t.name+"/",o.children.item(1),o)}:function(){hidectx(),create(n,o.parentNode,o.parentNode.parentNode)},a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[1],i&&(a.onclick=function(){hidectx(),upload(o,n+t.name+"/")}),a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[2],a.onclick=function(){edit(t,n),hidectx()},a.style.display=isText(t)?"block":"none",a=c.getElementsByTagName("li")[3],a.onclick=function(){preview(t,n),hidectx()},a.style.display=isImage(t)?"block":"none",a=c.getElementsByTagName("li")[4],a.onclick=function(){download(t,n),hidectx()},a.style.display=i?"none":"block",a=c.getElementsByTagName("li")[5],a.onclick=function(){remove(t,n,o),hidectx()},a.style.display=n?"block":"none";var s=document.body.scrollTop?document.body.scrollTop:document.documentElement.scrollTop,l=document.body.scrollLeft?document.body.scrollLeft:document.documentElement.scrollLeft,r=e.clientX+l+10,d=e.clientY+s-20,m=(c.offsetWidth,c.offsetHeight),u=document.documentElement.clientHeight;d+m>u&&(d=u-m-20),c.style.left=r+"px",c.style.top=d+"px",o&&o.classList.add("selitem")}function drag(e,t,n){let o=n+t.name;isFolder(t)&&(o+="/"),e.dataTransfer.setData("text",o),console.log("drag start "+o)}function drop(e,t){let n=e.dataTransfer.getData("text");n.startsWith(t)||(e.preventDefault(),console.log("Move "+n+" to "+t))}function listFiles(e,t){return console.log("listFiles"),fetch("/api/files/?dir="+t).then((e=>e.json())).then((n=>{if(0==n.length)return!1;let o=e.getElementsByTagName("div")[0];o&&(o.onclick=n=>{i.remove(),o.onclick=()=>{listFiles(e,t)},n.stopPropagation()});let a=e.getElementsByTagName("ul");for(let e=0;e{drag(event,e,t)},a.appendChild(s),s.innerHTML=''+o+"",isFolder(e)){let n=t+e.name+"/";s.classList.add("bold"),s.onclick=function(e){listFiles(a,n)},s.ondragover=e=>{e.preventDefault()},s.ondrop=e=>{drop(e,n)}}else(isText(e)||isImage(e)||isAudio(e))&&(s.onclick=function(n){url(e,t)});s.oncontextmenu=n=>{ctx(n,e,t,a)}}return e.scrollIntoView(),!0}))}function generateToast({message:e,background:t="#00214d",color:n="#fffffe",length:o="7000ms"}){_("toast").insertAdjacentHTML("afterbegin",`

\n ${e}\n

`);const a=_("toast").firstElementChild;a.addEventListener("animationend",(()=>a.remove()))}document.addEventListener("blur",(function(){hidectx()})),document.addEventListener("DOMContentLoaded",(function(){createEditor("editor",void 0,void 0,void 0);listFiles(_("tree"),"/"),_("tree").getElementsByTagName("div")[0].oncontextmenu=e=>{ctx(e,{name:"",children:[]},"",_("tree"))},_("load").onclick=function(e){const t=new FormData;t.append("load",""),fetchData("/edit","PUT",t)},_("init").onclick=function(e){const t=new FormData;t.append("init",""),fetchData("/edit","PUT",t)},_("home").onclick=function(e){window.location.href="/"},_("page").onchange=function(e){const t=new FormData;t.append("page",_("page").value),fetchData("/edit","PUT",t)}})),document.addEventListener("DOMContentLoaded",(function(){const e=document.getElementById("dragMe"),t=e.previousElementSibling,n=e.nextElementSibling;let o=0,a=0,i=0;const c=function(a){const c=a.clientX-o,s=(a.clientY,100*(i+c)/e.parentNode.getBoundingClientRect().width);t.style.width=`${s}%`,t.style.right=t.style.width,e.style.cursor="col-resize",document.body.style.cursor="col-resize",t.style.userSelect="none",t.style.pointerEvents="none",n.style.userSelect="none",n.style.pointerEvents="none",ace.edit("editor").resize()},s=function(){e.style.removeProperty("cursor"),document.body.style.removeProperty("cursor"),t.style.removeProperty("user-select"),t.style.removeProperty("pointer-events"),n.style.removeProperty("user-select"),n.style.removeProperty("pointer-events"),document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",s)};e.addEventListener("mousedown",(function(e){o=e.clientX,a=e.clientY,i=t.getBoundingClientRect().width,document.addEventListener("mousemove",c),document.addEventListener("mouseup",s)})),e.addEventListener("dblclick",(()=>{var e=t.style.visibility="hidden"===t.style.visibility;t.style.visibility=e?"unset":"hidden",t.style.position=e?"unset":"absolute",ace.edit("editor").resize()}))})); \ No newline at end of file From 27a0e7ce7321d58064d4528539a2d90c767a0f6d Mon Sep 17 00:00:00 2001 From: fvanroie Date: Thu, 23 May 2024 16:12:46 +0200 Subject: [PATCH 35/55] Add jc4827w543c_4MB --- .github/workflows/build.yaml | 2 +- user_setups/esp32s3/guition-jc4827w543.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index d4104b2e..8a8a5054 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -35,7 +35,7 @@ jobs: - out: globalsecurity env: gs-t3e_16MB - out: guition - env: esp32-s3-4848s040_16MB + env: esp32-s3-4848s040_16MB -e guition-jc4827w543c_4MB - out: lanbon env: lanbon_l8 - out: lilygo-ttgo diff --git a/user_setups/esp32s3/guition-jc4827w543.ini b/user_setups/esp32s3/guition-jc4827w543.ini index 689b764c..5a3721df 100644 --- a/user_setups/esp32s3/guition-jc4827w543.ini +++ b/user_setups/esp32s3/guition-jc4827w543.ini @@ -41,7 +41,7 @@ build_flags = -D TFT_WIDTH=480 -D TFT_HEIGHT=272 -[guition-jc4827w543c] +[guition-jc4827w543c_4MB] extends = guition-esp32-s3-tft, flash_4mb debug_tool = esp-builtin debug_build_flags = -Os # optimize for size From 6f402cb42dca5717306197e09549ac4a32617bca Mon Sep 17 00:00:00 2001 From: fvanroie Date: Thu, 23 May 2024 16:17:50 +0200 Subject: [PATCH 36/55] Add guition-jc4827w543c_4MB --- user_setups/esp32s3/guition-jc4827w543.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_setups/esp32s3/guition-jc4827w543.ini b/user_setups/esp32s3/guition-jc4827w543.ini index 5a3721df..0d41565c 100644 --- a/user_setups/esp32s3/guition-jc4827w543.ini +++ b/user_setups/esp32s3/guition-jc4827w543.ini @@ -41,7 +41,7 @@ build_flags = -D TFT_WIDTH=480 -D TFT_HEIGHT=272 -[guition-jc4827w543c_4MB] +[env:guition-jc4827w543c_4MB] extends = guition-esp32-s3-tft, flash_4mb debug_tool = esp-builtin debug_build_flags = -Os # optimize for size From cd34d8994fc1c720982c8c4c2b2044a4d16cf1a7 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Fri, 24 May 2024 00:09:52 +0200 Subject: [PATCH 37/55] Add elecrow-s3-8048c050_4MB --- .github/workflows/build.yaml | 2 +- user_setups/esp32s3/crowpanel-hmi.ini | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 8a8a5054..64838bd1 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -31,7 +31,7 @@ jobs: - out: dustinwatts env: "freetouchdeck_4MB -e freetouchdeck_8MB -e esp32-touchdown" - out: elecrow - env: "esp32-terminal-rgb_16MB -e esp32-terminal-spi_16MB -e elecrow-s3-8048c070_4MB" + env: "esp32-terminal-rgb_16MB -e esp32-terminal-spi_16MB -e elecrow-s3-8048c050_4MB -e elecrow-s3-8048c070_4MB" - out: globalsecurity env: gs-t3e_16MB - out: guition diff --git a/user_setups/esp32s3/crowpanel-hmi.ini b/user_setups/esp32s3/crowpanel-hmi.ini index 5a6be7c0..74ebc05c 100644 --- a/user_setups/esp32s3/crowpanel-hmi.ini +++ b/user_setups/esp32s3/crowpanel-hmi.ini @@ -81,9 +81,6 @@ extends = elecrow-esp32-s3-tft, flash_4mb build_flags = -D HASP_MODEL="Elecrow WZ8048C070" - -D HASP_LOG_LEVEL=LOG_LEVEL_WARNING - -D HASP_USE_CAPTIVE_PORTAL=0 - ; -D HASP_USE_CUSTOM=1 ${elecrow-esp32-s3-tft.build_flags} ${elecrow-tft-common-pins.build_flags} @@ -127,9 +124,6 @@ extends = elecrow-esp32-s3-tft, flash_4mb build_flags = -D HASP_MODEL="Elecrow WZ8048C050" - -D HASP_LOG_LEVEL=LOG_LEVEL_WARNING - -D HASP_USE_CAPTIVE_PORTAL=0 - ; -D HASP_USE_CUSTOM=1 ${elecrow-esp32-s3-tft.build_flags} From a9d514b04c5553a7e4bedc6f79df5a947a590268 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Fri, 24 May 2024 04:12:41 +0200 Subject: [PATCH 38/55] Flakey WiFi on Sunton #592 --- user_setups/esp32s3/sunton-esp32-s3-tft.ini | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/user_setups/esp32s3/sunton-esp32-s3-tft.ini b/user_setups/esp32s3/sunton-esp32-s3-tft.ini index 1da68da7..5c4e9139 100644 --- a/user_setups/esp32s3/sunton-esp32-s3-tft.ini +++ b/user_setups/esp32s3/sunton-esp32-s3-tft.ini @@ -142,7 +142,7 @@ build_flags = -D TFT_VSYNC_PULSE_WIDTH=4 ; Typical VSYNC Pulse Width -D TFT_VSYNC_BACK_PORCH=8 ; Typical VSYNC Back Porch -D TFT_PCLK_ACTIVE_NEG=1 - -D TFT_PREFER_SPEED=14000000 ; 1/2 of Typical DCLK Frequency + -D TFT_PREFER_SPEED=13900000 ; 1/2 of Typical DCLK Frequency -D TFT_AUTO_FLUSH=1 ; Touch Settings -D TOUCH_WIDTH=480 @@ -180,7 +180,7 @@ build_flags = -D TFT_VSYNC_PULSE_WIDTH=4 ; Typical VSYNC Pulse Width -D TFT_VSYNC_BACK_PORCH=8 ; Typical VSYNC Back Porch -D TFT_PCLK_ACTIVE_NEG=1 - -D TFT_PREFER_SPEED=14000000 ; 1/2 of Typical DCLK Frequency + -D TFT_PREFER_SPEED=13900000 ; 1/2 of Typical DCLK Frequency -D TFT_AUTO_FLUSH=1 ; Touch Settings -D TOUCH_WIDTH=800 @@ -229,15 +229,15 @@ build_flags = -D TFT_B4=4 ; Panel Settings -D TFT_HSYNC_POLARITY=0 - -D TFT_HSYNC_FRONT_PORCH=8 ; Maximum HSYNC Front Porch / 8 GOOD - -D TFT_HSYNC_PULSE_WIDTH=10 ; Typical HSYNC Pulse Width / 10 GOOD - -D TFT_HSYNC_BACK_PORCH=43 ; Typical HSYNC Back Porch / 43 GOOD + -D TFT_HSYNC_FRONT_PORCH=8 ; Maximum HSYNC Front Porch / 8 GOOD + -D TFT_HSYNC_PULSE_WIDTH=10 ; Typical HSYNC Pulse Width / 10 GOOD + -D TFT_HSYNC_BACK_PORCH=43 ; Typical HSYNC Back Porch / 43 GOOD -D TFT_VSYNC_POLARITY=0 -D TFT_VSYNC_FRONT_PORCH=8 ; Maximum VSYNC Front Porch / 8 GOOD -D TFT_VSYNC_PULSE_WIDTH=8 ; Typical VSYNC Pulse Width / 8 GOOD - -D TFT_VSYNC_BACK_PORCH=12 ; Typical VSYNC Back Porch / 12 GOOD + -D TFT_VSYNC_BACK_PORCH=12 ; Typical VSYNC Back Porch / 12 GOOD -D TFT_PCLK_ACTIVE_NEG=1 - -D TFT_PREFER_SPEED=14500000 ; 1/2 of Typical DCLK Frequency / 12000000 GOOD + -D TFT_PREFER_SPEED=13900000 ; 1/2 of Typical DCLK Frequency / 12000000 GOOD -D TFT_AUTO_FLUSH=1 ; Touch Settings -D TOUCH_WIDTH=800 From 1f471ad308028d92af30b63a524b7e1e2e782b32 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Fri, 24 May 2024 05:03:53 +0200 Subject: [PATCH 39/55] Add custom_state_subtopic #611 --- src/custom/my_custom_fan_template.cpp | 4 ++++ src/custom/my_custom_template.cpp | 5 +++++ src/custom/my_custom_template.h | 5 +++++ src/hasp/hasp_dispatch.cpp | 12 +++++++++++- 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/custom/my_custom_fan_template.cpp b/src/custom/my_custom_fan_template.cpp index b7bed86d..a8775242 100644 --- a/src/custom/my_custom_fan_template.cpp +++ b/src/custom/my_custom_fan_template.cpp @@ -98,4 +98,8 @@ void custom_topic_payload(const char* topic, const char* payload, uint8_t source // LOG_VERBOSE(TAG_CUSTOM, "Handled custom message: %s => %s", topic, payload); } +void custom_state_subtopic(const char* subtopic, const char* payload){ + // Not used +} + #endif // HASP_USE_CUSTOM diff --git a/src/custom/my_custom_template.cpp b/src/custom/my_custom_template.cpp index b41da916..358bbd0f 100644 --- a/src/custom/my_custom_template.cpp +++ b/src/custom/my_custom_template.cpp @@ -53,4 +53,9 @@ void custom_topic_payload(const char* topic, const char* payload, uint8_t source // Not used } +void custom_state_subtopic(const char* subtopic, const char* payload){ + // Not used +} + + #endif // HASP_USE_CUSTOM \ No newline at end of file diff --git a/src/custom/my_custom_template.h b/src/custom/my_custom_template.h index 111df88f..3e25c031 100644 --- a/src/custom/my_custom_template.h +++ b/src/custom/my_custom_template.h @@ -32,6 +32,11 @@ void custom_get_sensors(JsonDocument& doc); /* Receive custom topic & payload messages */ void custom_topic_payload(const char* topic, const char* payload, uint8_t source); +/* Get notified when a state message is sent out */ +/* Can be used to send state changes through other means then MQTT, e.g. Serial2 */ +/* https://github.com/HASwitchPlate/openHASP/issues/611 */ +void custom_state_subtopic(const char* subtopic, const char* payload); + #endif // HASP_USE_CUSTOM #endif // HASP_CUSTOM_H diff --git a/src/hasp/hasp_dispatch.cpp b/src/hasp/hasp_dispatch.cpp index 03b0da9d..39ddae76 100644 --- a/src/hasp/hasp_dispatch.cpp +++ b/src/hasp/hasp_dispatch.cpp @@ -43,7 +43,7 @@ uint16_t dispatchSecondsToNextTeleperiod = 0; uint16_t dispatchSecondsToNextSensordata = 0; uint16_t dispatchSecondsToNextDiscovery = 0; uint8_t nCommands = 0; -haspCommand_t commands[28]; +haspCommand_t commands[29]; moodlight_t moodlight = {.brightness = 255}; uint8_t saved_jsonl_page = 0; @@ -74,6 +74,10 @@ void dispatch_state_subtopic(const char* subtopic, const char* payload) } #endif +#if HASP_USE_CUSTOM > 0 + custom_state_subtopic(subtopic, payload); +#endif + #if HASP_USE_TASMOTA_CLIENT > 0 slave_send_state(subtopic, payload); #endif @@ -864,6 +868,11 @@ void dispatch_run_script(const char*, const char* payload, uint8_t source) #endif } +void dispatch_dir(const char*, const char* payload, uint8_t source) +{ + filesystem_list_path(payload); +} + #if HASP_TARGET_PC static void shell_command_thread(char* cmdline) { @@ -1592,6 +1601,7 @@ void dispatchSetup() dispatch_add_command(PSTR("sensors"), dispatch_send_sensordata); dispatch_add_command(PSTR("theme"), dispatch_theme); dispatch_add_command(PSTR("run"), dispatch_run_script); + dispatch_add_command(PSTR("dir"), dispatch_dir); #if HASP_TARGET_PC dispatch_add_command(PSTR("shell"), dispatch_shell_execute); #endif From 5c80f41fcfa53c08239d4a98acd046d20f2f18e3 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Fri, 24 May 2024 05:14:49 +0200 Subject: [PATCH 40/55] Add custom_state_subtopic --- src/hasp/hasp_dispatch.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/hasp/hasp_dispatch.cpp b/src/hasp/hasp_dispatch.cpp index 39ddae76..72c6b4f0 100644 --- a/src/hasp/hasp_dispatch.cpp +++ b/src/hasp/hasp_dispatch.cpp @@ -52,7 +52,7 @@ uint8_t saved_jsonl_page = 0; */ void dispatch_state_subtopic(const char* subtopic, const char* payload) { -#if HASP_USE_MQTT == 0 && HASP_USE_TASMOTA_CLIENT == 0 +#if HASP_USE_MQTT == 0 && defined(HASP_USE_TASMOTA_CLIENT) && HASP_USE_TASMOTA_CLIENT > 0 LOG_TRACE(TAG_MSGR, F("%s => %s"), subtopic, payload); #else @@ -74,15 +74,15 @@ void dispatch_state_subtopic(const char* subtopic, const char* payload) } #endif -#if HASP_USE_CUSTOM > 0 - custom_state_subtopic(subtopic, payload); -#endif - -#if HASP_USE_TASMOTA_CLIENT > 0 +#if defined(HASP_USE_TASMOTA_CLIENT) && HASP_USE_TASMOTA_CLIENT > 0 slave_send_state(subtopic, payload); #endif #endif + +#if defined(HASP_USE_CUSTOM) && HASP_USE_CUSTOM > 0 + custom_state_subtopic(subtopic, payload); +#endif } void dispatch_state_eventid(const char* topic, hasp_event_t eventid) From 8a341fd09cedcc217355092ef575f56fdf2d08ff Mon Sep 17 00:00:00 2001 From: fvanroie Date: Fri, 24 May 2024 13:50:15 +0200 Subject: [PATCH 41/55] Update ace.js to 1.34.1 --- data/edit.htm | 2 +- data/script.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/edit.htm b/data/edit.htm index e15ab495..4d1ccace 100644 --- a/data/edit.htm +++ b/data/edit.htm @@ -1 +1 @@ -openHASP File Editor
L:
  • New File
  • Upload Files
  • Edit
  • Preview
  • Download
  • Delete
\ No newline at end of file +openHASP File Editor
L:
  • New File
  • Upload Files
  • Edit
  • Preview
  • Download
  • Delete
\ No newline at end of file diff --git a/data/script.js b/data/script.js index 670b0d92..e9705de1 100644 --- a/data/script.js +++ b/data/script.js @@ -1 +1 @@ -var ctx_el;function _(e){return document.getElementById(e)}function hidectx(){_("ctx").style.display="none",ctx_el&&ctx_el.classList.remove("selitem"),ctx_el=void 0}function doesFontExist(e){var t=document.createElement("canvas"),n=t.getContext("2d"),o="abcdefghijklmnopqrstuvwxyz0123456789";n.font="72px monospace";var a=n.measureText(o).width;return n.font="72px '"+e+"', monospace",t=null,n.measureText(o).width!=a}function createEditor(e,t,n,o,a){function i(e){let t=/(?:\.([^.]+))?$/.exec(e)[1];if(void 0!==typeof t)switch(t){case"htm":case"html":return"html";case"js":return"javascript";case"cmd":case"json":case"jsonl":return"json";case"css":case"svg":case"xml":return t}return"plain_text"}void 0===n&&(n=i(t)),void 0===a&&(a="text/"+n);["basePath","modePath","themePath"].forEach((e=>{ace.config.set(e,"https://cdnjs.cloudflare.com/ajax/libs/ace/1.34.0")}));var c=ace.edit(e,{useWorker:!1,wrap:!0,indentedSoftWrap:!1,showPrintMargin:!1,highlightGutterLine:!0,useSoftTabs:!0,tabSize:2});c.setFontSize(parseFloat(getComputedStyle(document.documentElement).fontSize)),c.setReadOnly(!0),c.getSession().setUndoManager(new ace.UndoManager),void 0===o&&(o=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"monokai":"textmate");var s=_("save"),l=_("undo"),r=_("redo"),d=_("cut"),m=_("copy"),u=_("paste"),p=_("font"),f=_("fontsize"),g="none"!==_(e).display;f.value=parseFloat(c.getFontSize()).toFixed(1),p.onchange=function(){c.setOption("fontFamily","'"+p.value+"',monospace")},f.onchange=function(){var e=parseFloat(f.value);!isNaN(e)&&e>=9&&e<=40&&c.setFontSize(e),f.value=parseFloat(c.getFontSize()).toFixed(1)};function h(){let e=!g||c.session.getSelection().isEmpty();d.disabled=e,m.disabled=e}function y(){let e=c.session.getUndoManager();s.disabled=!g||e.isClean(),l.disabled=!g||!e.hasUndo(),r.disabled=!g||!e.hasRedo()}function v(){if(void 0===t)return;const e=function(e){var t=e.getValue();try{var n=JSON.parse(t);return JSON.stringify(n)}catch(e){return t+""}}(c),n=new FormData;n.append("data",new Blob([e],{type:a}),t),fetch("/edit",{method:"POST",body:n}).then((e=>e.ok?e.text().then((e=>{console.log("Save OK /edit "+e)})):e.text().then((e=>{throw console.log("Save FAIL /edit"),new Error(e)})))).then((e=>{console.log(e),generateToast({message:"Saved "+t,background:"#ddd",color:"#000"})})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{y()}))}function x(){var e=c.getCopyText();if(window.clipboardData&&window.clipboardData.setData)return window.clipboardData.setData("Text",e);if(document.queryCommandSupported&&document.queryCommandSupported("copy")){c.focus();try{return document.execCommand("copy")}catch(t){return console.warn("Copy to clipboard failed.",t),prompt("Copy to clipboard: Ctrl+C, Enter",e)}}}function w(e){_("name").innerHTML=e;fetch(e).then((t=>t.ok?(console.log("OK "+e),t.text()):t.text().then((e=>{throw console.log("ERROR "+url),new Error(e)})))).then((e=>{try{var t=JSON.parse(e);c.setValue(JSON.stringify(t,null,4)),console.log("parse json OK")}catch(t){c.setValue(e),console.log("parse json FAIL")}null!==_("editor")&&(_("editor").style.display="block"),null!==_("preview")&&(_("preview").style.display="none"),g=!0,c.setReadOnly(!1),c.focus(),y()})).catch((e=>{console.log(e),alert(e),c.setReadOnly(!0)})).finally((()=>{c.resize(!0),c.scrollToLine(1,!0,!0,(function(){})),c.gotoLine(1,0,!0),c.clearSelection(),c.session.getUndoManager().reset()}))}return["Courier New","Monaco","Lucida Console","Monospace","ui-monospace","Roboto Mono","Inconsolata","IBM Plex Mono","Space Mono","PT Mono","Ubuntu Mono","Nanum Gothic Coding","Cousine","Fira Mono","Share Tech Mono","Courier Prime","Anonymous Pro","Cutive Mono","Overpass Mono","Fira Code","VT323","DM Mono","Oxygen Mono","Nova Mono","B612 Mono","Spline Sans Mono","Noto Sans Mono","Major Mono Display","Azeret Mono","Red Hat Mono","Syne Mono","Xanh Mono"].sort().forEach((function(e,t){if(doesFontExist(e)){var n=document.createElement("option");n.text=e,p.add(n)}})),null!==s&&null!==l&&null!==r&&c.on("input",y),c.session.selection.on("changeCursor",h),s.onclick=v,l.onclick=e=>{c.undo()&&c.focus()},r.onclick=e=>{c.redo()&&c.focus()},d.onclick=e=>{x()&&c.execCommand("cut")},m.onclick=e=>{x()&&c.execCommand("copy")},u.onclick=function(){try{navigator.clipboard.readText().then((e=>{c.execCommand("paste",e)})).catch((e=>{u.disabled=!0}))}catch{u.disabled=!0}},c.loadUrl=(e,o)=>{n=i(t=e+o),a="text/"+n,"plain"!==n&&c.getSession().setMode("ace/mode/"+n),w(e+o)},c.hide=()=>{g=!1,y(),h(),_("editor").style.display="none"},"plain"!==n&&c.getSession().setMode("ace/mode/"+n),c.setTheme("ace/theme/"+o),c.$blockScrolling=1/0,c.commands.addCommand({name:"save",bindKey:{win:"Ctrl-S",mac:"Command-S"},exec:v,readOnly:!1}),c.commands.addCommand({name:"undo",bindKey:{win:"Ctrl-Z",mac:"Command-Z"},exec:function(){c.undo()}}),c.commands.addCommand({name:"redo",bindKey:{win:"Ctrl-Y",mac:"Command-Y"},exec:function(){c.redo()}}),void 0!==t&&w(t),c.resize(),c}function uploadFileAsync(e,t,n,o,a,i){fetchData("/edit","POST",e).then((e=>{generateToast({message:"Upload "+n+"/"+o+" "+t+" done.",background:"#ddd",color:"#000"}),n==o&&listFiles(a,i)}))}function doUpload(e,t){const n=_("upload"),o=n.files.length;if(0!==o)for(let a=0;a=0}function isText(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"txt":case"cmd":case"json":case"jsonl":case"htm":case"html":case"js":case"c":case"cpp":case"css":case"svg":case"xml":return!0}return!1}function isImage(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"bmp":case"png":case"jpg":case"gif":case"svg":return!0}return!1}function isAudio(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"wav":case"mp3":case"aac":case"m4a":case"wma":return!0}return!1}function icon(e){if(isFolder(e))return"dir";if(isImage(e))return"image";if(isAudio(e))return"audio";var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"cmd":case"css":case"json":case"jsonl":case"ttf":return t;case"zip":case"gz":return"zip";case"html":case"htm":return"html"}return"file"}function preview(e,t){if(isImage(e)){let n=t+e.name;const o=_("preview");o.innerHTML='',o.style.display="block",ace.edit("editor").hide(),_("name").innerHTML=n}}function edit(e,t){isText(e)&&(ace.edit("editor").loadUrl(t,e.name),_("preview").style.display="none")}function url(e,t){console.log("click "+t+e.name),isImage(e)?preview(e,t):isText(e)&&edit(e,t)}async function fetchData(e,t,n,o){await fetch(e,{method:t,body:n}).then((n=>n.ok?(console.log(t+" OK "+e),n.text()):n.text().then((n=>{throw console.log(t+" FAIL "+e),new Error(n)})))).then((e=>{o&&o.remove(),console.log(e)})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{}))}function download(e,t){console.log("download "+t+e.name),document.getElementById("download-frame").src=t+e.name+"?download=true"}function remove(e,t,n){let o=t+e.name;isFolder(e)&&(o+="/"),console.log("remove "+o);const a=new FormData;a.append("path",o),fetchData("/edit","DELETE",a,n)}function create(e,t,n){var o=window.prompt("Create File in "+e,"");if(null==o||""==o||o.includes("/"))return;const a=new FormData;a.append("path",e+o),fetchData("/edit","PUT",a),fetch("/api/files/").then((e=>e.json())).then((o=>{t&&t.remove(),listFiles(n,e),console.log(o)}))}function upload(e,t){_("upload").onchange=()=>{doUpload(e,t)},_("upload").click()}function ctx(e,t,n,o){e.preventDefault(),ctx_el=o;let a,i=isFolder(t),c=_("ctx");c.style.display="block",a=c.getElementsByTagName("li")[0],a.onclick=i?function(){hidectx(),create(n+t.name+"/",o.children.item(1),o)}:function(){hidectx(),create(n,o.parentNode,o.parentNode.parentNode)},a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[1],i&&(a.onclick=function(){hidectx(),upload(o,n+t.name+"/")}),a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[2],a.onclick=function(){edit(t,n),hidectx()},a.style.display=isText(t)?"block":"none",a=c.getElementsByTagName("li")[3],a.onclick=function(){preview(t,n),hidectx()},a.style.display=isImage(t)?"block":"none",a=c.getElementsByTagName("li")[4],a.onclick=function(){download(t,n),hidectx()},a.style.display=i?"none":"block",a=c.getElementsByTagName("li")[5],a.onclick=function(){remove(t,n,o),hidectx()},a.style.display=n?"block":"none";var s=document.body.scrollTop?document.body.scrollTop:document.documentElement.scrollTop,l=document.body.scrollLeft?document.body.scrollLeft:document.documentElement.scrollLeft,r=e.clientX+l+10,d=e.clientY+s-20,m=(c.offsetWidth,c.offsetHeight),u=document.documentElement.clientHeight;d+m>u&&(d=u-m-20),c.style.left=r+"px",c.style.top=d+"px",o&&o.classList.add("selitem")}function drag(e,t,n){let o=n+t.name;isFolder(t)&&(o+="/"),e.dataTransfer.setData("text",o),console.log("drag start "+o)}function drop(e,t){let n=e.dataTransfer.getData("text");n.startsWith(t)||(e.preventDefault(),console.log("Move "+n+" to "+t))}function listFiles(e,t){return console.log("listFiles"),fetch("/api/files/?dir="+t).then((e=>e.json())).then((n=>{if(0==n.length)return!1;let o=e.getElementsByTagName("div")[0];o&&(o.onclick=n=>{i.remove(),o.onclick=()=>{listFiles(e,t)},n.stopPropagation()});let a=e.getElementsByTagName("ul");for(let e=0;e{drag(event,e,t)},a.appendChild(s),s.innerHTML=''+o+"",isFolder(e)){let n=t+e.name+"/";s.classList.add("bold"),s.onclick=function(e){listFiles(a,n)},s.ondragover=e=>{e.preventDefault()},s.ondrop=e=>{drop(e,n)}}else(isText(e)||isImage(e)||isAudio(e))&&(s.onclick=function(n){url(e,t)});s.oncontextmenu=n=>{ctx(n,e,t,a)}}return e.scrollIntoView(),!0}))}function generateToast({message:e,background:t="#00214d",color:n="#fffffe",length:o="7000ms"}){_("toast").insertAdjacentHTML("afterbegin",`

\n ${e}\n

`);const a=_("toast").firstElementChild;a.addEventListener("animationend",(()=>a.remove()))}document.addEventListener("blur",(function(){hidectx()})),document.addEventListener("DOMContentLoaded",(function(){createEditor("editor",void 0,void 0,void 0);listFiles(_("tree"),"/"),_("tree").getElementsByTagName("div")[0].oncontextmenu=e=>{ctx(e,{name:"",children:[]},"",_("tree"))},_("load").onclick=function(e){const t=new FormData;t.append("load",""),fetchData("/edit","PUT",t)},_("init").onclick=function(e){const t=new FormData;t.append("init",""),fetchData("/edit","PUT",t)},_("home").onclick=function(e){window.location.href="/"},_("page").onchange=function(e){const t=new FormData;t.append("page",_("page").value),fetchData("/edit","PUT",t)}})),document.addEventListener("DOMContentLoaded",(function(){const e=document.getElementById("dragMe"),t=e.previousElementSibling,n=e.nextElementSibling;let o=0,a=0,i=0;const c=function(a){const c=a.clientX-o,s=(a.clientY,100*(i+c)/e.parentNode.getBoundingClientRect().width);t.style.width=`${s}%`,t.style.right=t.style.width,e.style.cursor="col-resize",document.body.style.cursor="col-resize",t.style.userSelect="none",t.style.pointerEvents="none",n.style.userSelect="none",n.style.pointerEvents="none",ace.edit("editor").resize()},s=function(){e.style.removeProperty("cursor"),document.body.style.removeProperty("cursor"),t.style.removeProperty("user-select"),t.style.removeProperty("pointer-events"),n.style.removeProperty("user-select"),n.style.removeProperty("pointer-events"),document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",s)};e.addEventListener("mousedown",(function(e){o=e.clientX,a=e.clientY,i=t.getBoundingClientRect().width,document.addEventListener("mousemove",c),document.addEventListener("mouseup",s)})),e.addEventListener("dblclick",(()=>{var e=t.style.visibility="hidden"===t.style.visibility;t.style.visibility=e?"unset":"hidden",t.style.position=e?"unset":"absolute",ace.edit("editor").resize()}))})); \ No newline at end of file +var ctx_el;function _(e){return document.getElementById(e)}function hidectx(){_("ctx").style.display="none",ctx_el&&ctx_el.classList.remove("selitem"),ctx_el=void 0}function doesFontExist(e){var t=document.createElement("canvas"),n=t.getContext("2d"),o="abcdefghijklmnopqrstuvwxyz0123456789";n.font="72px monospace";var a=n.measureText(o).width;return n.font="72px '"+e+"', monospace",t=null,n.measureText(o).width!=a}function createEditor(e,t,n,o,a){function i(e){let t=/(?:\.([^.]+))?$/.exec(e)[1];if(void 0!==typeof t)switch(t){case"htm":case"html":return"html";case"js":return"javascript";case"cmd":case"json":case"jsonl":return"json";case"css":case"svg":case"xml":return t}return"plain_text"}void 0===n&&(n=i(t)),void 0===a&&(a="text/"+n);["basePath","modePath","themePath"].forEach((e=>{ace.config.set(e,"https://cdnjs.cloudflare.com/ajax/libs/ace/1.34.1")}));var c=ace.edit(e,{useWorker:!1,wrap:!0,indentedSoftWrap:!1,showPrintMargin:!1,highlightGutterLine:!0,useSoftTabs:!0,tabSize:2});c.setFontSize(parseFloat(getComputedStyle(document.documentElement).fontSize)),c.setReadOnly(!0),c.getSession().setUndoManager(new ace.UndoManager),void 0===o&&(o=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"monokai":"textmate");var s=_("save"),l=_("undo"),r=_("redo"),d=_("cut"),m=_("copy"),u=_("paste"),p=_("font"),f=_("fontsize"),g="none"!==_(e).display;f.value=parseFloat(c.getFontSize()).toFixed(1),p.onchange=function(){c.setOption("fontFamily","'"+p.value+"',monospace")},f.onchange=function(){var e=parseFloat(f.value);!isNaN(e)&&e>=9&&e<=40&&c.setFontSize(e),f.value=parseFloat(c.getFontSize()).toFixed(1)};function h(){let e=!g||c.session.getSelection().isEmpty();d.disabled=e,m.disabled=e}function y(){let e=c.session.getUndoManager();s.disabled=!g||e.isClean(),l.disabled=!g||!e.hasUndo(),r.disabled=!g||!e.hasRedo()}function v(){if(void 0===t)return;const e=function(e){var t=e.getValue();try{var n=JSON.parse(t);return JSON.stringify(n)}catch(e){return t+""}}(c),n=new FormData;n.append("data",new Blob([e],{type:a}),t),fetch("/edit",{method:"POST",body:n}).then((e=>e.ok?e.text().then((e=>{console.log("Save OK /edit "+e)})):e.text().then((e=>{throw console.log("Save FAIL /edit"),new Error(e)})))).then((e=>{console.log(e),generateToast({message:"Saved "+t,background:"#ddd",color:"#000"})})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{y()}))}function x(){var e=c.getCopyText();if(window.clipboardData&&window.clipboardData.setData)return window.clipboardData.setData("Text",e);if(document.queryCommandSupported&&document.queryCommandSupported("copy")){c.focus();try{return document.execCommand("copy")}catch(t){return console.warn("Copy to clipboard failed.",t),prompt("Copy to clipboard: Ctrl+C, Enter",e)}}}function w(e){_("name").innerHTML=e;fetch(e).then((t=>t.ok?(console.log("OK "+e),t.text()):t.text().then((e=>{throw console.log("ERROR "+url),new Error(e)})))).then((e=>{try{var t=JSON.parse(e);c.setValue(JSON.stringify(t,null,4)),console.log("parse json OK")}catch(t){c.setValue(e),console.log("parse json FAIL")}null!==_("editor")&&(_("editor").style.display="block"),null!==_("preview")&&(_("preview").style.display="none"),g=!0,c.setReadOnly(!1),c.focus(),y()})).catch((e=>{console.log(e),alert(e),c.setReadOnly(!0)})).finally((()=>{c.resize(!0),c.scrollToLine(1,!0,!0,(function(){})),c.gotoLine(1,0,!0),c.clearSelection(),c.session.getUndoManager().reset()}))}return["Courier New","Monaco","Lucida Console","Monospace","ui-monospace","Roboto Mono","Inconsolata","IBM Plex Mono","Space Mono","PT Mono","Ubuntu Mono","Nanum Gothic Coding","Cousine","Fira Mono","Share Tech Mono","Courier Prime","Anonymous Pro","Cutive Mono","Overpass Mono","Fira Code","VT323","DM Mono","Oxygen Mono","Nova Mono","B612 Mono","Spline Sans Mono","Noto Sans Mono","Major Mono Display","Azeret Mono","Red Hat Mono","Syne Mono","Xanh Mono"].sort().forEach((function(e,t){if(doesFontExist(e)){var n=document.createElement("option");n.text=e,p.add(n)}})),null!==s&&null!==l&&null!==r&&c.on("input",y),c.session.selection.on("changeCursor",h),s.onclick=v,l.onclick=e=>{c.undo()&&c.focus()},r.onclick=e=>{c.redo()&&c.focus()},d.onclick=e=>{x()&&c.execCommand("cut")},m.onclick=e=>{x()&&c.execCommand("copy")},u.onclick=function(){try{navigator.clipboard.readText().then((e=>{c.execCommand("paste",e)})).catch((e=>{u.disabled=!0}))}catch{u.disabled=!0}},c.loadUrl=(e,o)=>{n=i(t=e+o),a="text/"+n,"plain"!==n&&c.getSession().setMode("ace/mode/"+n),w(e+o)},c.hide=()=>{g=!1,y(),h(),_("editor").style.display="none"},"plain"!==n&&c.getSession().setMode("ace/mode/"+n),c.setTheme("ace/theme/"+o),c.$blockScrolling=1/0,c.commands.addCommand({name:"save",bindKey:{win:"Ctrl-S",mac:"Command-S"},exec:v,readOnly:!1}),c.commands.addCommand({name:"undo",bindKey:{win:"Ctrl-Z",mac:"Command-Z"},exec:function(){c.undo()}}),c.commands.addCommand({name:"redo",bindKey:{win:"Ctrl-Y",mac:"Command-Y"},exec:function(){c.redo()}}),void 0!==t&&w(t),c.resize(),c}function uploadFileAsync(e,t,n,o,a,i){fetchData("/edit","POST",e).then((e=>{generateToast({message:"Upload "+n+"/"+o+" "+t+" done.",background:"#ddd",color:"#000"}),n==o&&listFiles(a,i)}))}function doUpload(e,t){const n=_("upload"),o=n.files.length;if(0!==o)for(let a=0;a=0}function isText(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"txt":case"cmd":case"json":case"jsonl":case"htm":case"html":case"js":case"c":case"cpp":case"css":case"svg":case"xml":return!0}return!1}function isImage(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"bmp":case"png":case"jpg":case"gif":case"svg":return!0}return!1}function isAudio(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"wav":case"mp3":case"aac":case"m4a":case"wma":return!0}return!1}function icon(e){if(isFolder(e))return"dir";if(isImage(e))return"image";if(isAudio(e))return"audio";var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"cmd":case"css":case"json":case"jsonl":case"ttf":return t;case"zip":case"gz":return"zip";case"html":case"htm":return"html"}return"file"}function preview(e,t){if(isImage(e)){let n=t+e.name;const o=_("preview");o.innerHTML='',o.style.display="block",ace.edit("editor").hide(),_("name").innerHTML=n}}function edit(e,t){isText(e)&&(ace.edit("editor").loadUrl(t,e.name),_("preview").style.display="none")}function url(e,t){console.log("click "+t+e.name),isImage(e)?preview(e,t):isText(e)&&edit(e,t)}async function fetchData(e,t,n,o){await fetch(e,{method:t,body:n}).then((n=>n.ok?(console.log(t+" OK "+e),n.text()):n.text().then((n=>{throw console.log(t+" FAIL "+e),new Error(n)})))).then((e=>{o&&o.remove(),console.log(e)})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{}))}function download(e,t){console.log("download "+t+e.name),document.getElementById("download-frame").src=t+e.name+"?download=true"}function remove(e,t,n){let o=t+e.name;isFolder(e)&&(o+="/"),console.log("remove "+o);const a=new FormData;a.append("path",o),fetchData("/edit","DELETE",a,n)}function create(e,t,n){var o=window.prompt("Create File in "+e,"");if(null==o||""==o||o.includes("/"))return;const a=new FormData;a.append("path",e+o),fetchData("/edit","PUT",a),fetch("/api/files/").then((e=>e.json())).then((o=>{t&&t.remove(),listFiles(n,e),console.log(o)}))}function upload(e,t){_("upload").onchange=()=>{doUpload(e,t)},_("upload").click()}function ctx(e,t,n,o){e.preventDefault(),ctx_el=o;let a,i=isFolder(t),c=_("ctx");c.style.display="block",a=c.getElementsByTagName("li")[0],a.onclick=i?function(){hidectx(),create(n+t.name+"/",o.children.item(1),o)}:function(){hidectx(),create(n,o.parentNode,o.parentNode.parentNode)},a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[1],i&&(a.onclick=function(){hidectx(),upload(o,n+t.name+"/")}),a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[2],a.onclick=function(){edit(t,n),hidectx()},a.style.display=isText(t)?"block":"none",a=c.getElementsByTagName("li")[3],a.onclick=function(){preview(t,n),hidectx()},a.style.display=isImage(t)?"block":"none",a=c.getElementsByTagName("li")[4],a.onclick=function(){download(t,n),hidectx()},a.style.display=i?"none":"block",a=c.getElementsByTagName("li")[5],a.onclick=function(){remove(t,n,o),hidectx()},a.style.display=n?"block":"none";var s=document.body.scrollTop?document.body.scrollTop:document.documentElement.scrollTop,l=document.body.scrollLeft?document.body.scrollLeft:document.documentElement.scrollLeft,r=e.clientX+l+10,d=e.clientY+s-20,m=(c.offsetWidth,c.offsetHeight),u=document.documentElement.clientHeight;d+m>u&&(d=u-m-20),c.style.left=r+"px",c.style.top=d+"px",o&&o.classList.add("selitem")}function drag(e,t,n){let o=n+t.name;isFolder(t)&&(o+="/"),e.dataTransfer.setData("text",o),console.log("drag start "+o)}function drop(e,t){let n=e.dataTransfer.getData("text");n.startsWith(t)||(e.preventDefault(),console.log("Move "+n+" to "+t))}function listFiles(e,t){return console.log("listFiles"),fetch("/api/files/?dir="+t).then((e=>e.json())).then((n=>{if(0==n.length)return!1;let o=e.getElementsByTagName("div")[0];o&&(o.onclick=n=>{i.remove(),o.onclick=()=>{listFiles(e,t)},n.stopPropagation()});let a=e.getElementsByTagName("ul");for(let e=0;e{drag(event,e,t)},a.appendChild(s),s.innerHTML=''+o+"",isFolder(e)){let n=t+e.name+"/";s.classList.add("bold"),s.onclick=function(e){listFiles(a,n)},s.ondragover=e=>{e.preventDefault()},s.ondrop=e=>{drop(e,n)}}else(isText(e)||isImage(e)||isAudio(e))&&(s.onclick=function(n){url(e,t)});s.oncontextmenu=n=>{ctx(n,e,t,a)}}return e.scrollIntoView(),!0}))}function generateToast({message:e,background:t="#00214d",color:n="#fffffe",length:o="7000ms"}){_("toast").insertAdjacentHTML("afterbegin",`

\n ${e}\n

`);const a=_("toast").firstElementChild;a.addEventListener("animationend",(()=>a.remove()))}document.addEventListener("blur",(function(){hidectx()})),document.addEventListener("DOMContentLoaded",(function(){createEditor("editor",void 0,void 0,void 0);listFiles(_("tree"),"/"),_("tree").getElementsByTagName("div")[0].oncontextmenu=e=>{ctx(e,{name:"",children:[]},"",_("tree"))},_("load").onclick=function(e){const t=new FormData;t.append("load",""),fetchData("/edit","PUT",t)},_("init").onclick=function(e){const t=new FormData;t.append("init",""),fetchData("/edit","PUT",t)},_("home").onclick=function(e){window.location.href="/"},_("page").onchange=function(e){const t=new FormData;t.append("page",_("page").value),fetchData("/edit","PUT",t)}})),document.addEventListener("DOMContentLoaded",(function(){const e=document.getElementById("dragMe"),t=e.previousElementSibling,n=e.nextElementSibling;let o=0,a=0,i=0;const c=function(a){const c=a.clientX-o,s=(a.clientY,100*(i+c)/e.parentNode.getBoundingClientRect().width);t.style.width=`${s}%`,t.style.right=t.style.width,e.style.cursor="col-resize",document.body.style.cursor="col-resize",t.style.userSelect="none",t.style.pointerEvents="none",n.style.userSelect="none",n.style.pointerEvents="none",ace.edit("editor").resize()},s=function(){e.style.removeProperty("cursor"),document.body.style.removeProperty("cursor"),t.style.removeProperty("user-select"),t.style.removeProperty("pointer-events"),n.style.removeProperty("user-select"),n.style.removeProperty("pointer-events"),document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",s)};e.addEventListener("mousedown",(function(e){o=e.clientX,a=e.clientY,i=t.getBoundingClientRect().width,document.addEventListener("mousemove",c),document.addEventListener("mouseup",s)})),e.addEventListener("dblclick",(()=>{var e=t.style.visibility="hidden"===t.style.visibility;t.style.visibility=e?"unset":"hidden",t.style.position=e?"unset":"absolute",ace.edit("editor").resize()}))})); \ No newline at end of file From d903bc905fb76859852f2c0d92ff6a80e234b8a9 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Fri, 24 May 2024 21:39:57 +0200 Subject: [PATCH 42/55] Add mqttEverySecond --- src/hasp/hasp_task.cpp | 4 ++++ src/main.cpp | 4 ++++ src/mqtt/hasp_mqtt.h | 1 + src/mqtt/hasp_mqtt_esp.cpp | 18 +++++++++++------- src/mqtt/hasp_mqtt_paho_async.cpp | 2 -- src/mqtt/hasp_mqtt_pubsubclient.cpp | 4 ++-- 6 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/hasp/hasp_task.cpp b/src/hasp/hasp_task.cpp index a6d01900..272285d7 100644 --- a/src/hasp/hasp_task.cpp +++ b/src/hasp/hasp_task.cpp @@ -24,6 +24,10 @@ void task_every_second_cb(lv_task_t* task) { haspEverySecond(); // sleep timer & statusupdate +#if HASP_MQTT_TELNET > 0 + mqttEverySecond(); +#endif + #if HASP_USE_TELNET > 0 telnetEverySecond(); #endif diff --git a/src/main.cpp b/src/main.cpp index b065909c..c68c2bf4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -210,6 +210,10 @@ IRAM_ATTR void loop() /* Runs Every Second */ haspEverySecond(); // sleep timer & statusupdate +#if HASP_USE_MQTT > 0 + mqttEverySecond(); +#endif + #if HASP_USE_FTP > 0 ftpEverySecond(); #endif diff --git a/src/mqtt/hasp_mqtt.h b/src/mqtt/hasp_mqtt.h index f5d57196..89ced6c1 100644 --- a/src/mqtt/hasp_mqtt.h +++ b/src/mqtt/hasp_mqtt.h @@ -18,6 +18,7 @@ typedef enum { void mqttSetup(); IRAM_ATTR void mqttLoop(); +void mqttEverySecond(); void mqttEvery5Seconds(bool wifiIsConnected); void mqttStart(); void mqttStop(); diff --git a/src/mqtt/hasp_mqtt_esp.cpp b/src/mqtt/hasp_mqtt_esp.cpp index 453d3a33..8864c107 100644 --- a/src/mqtt/hasp_mqtt_esp.cpp +++ b/src/mqtt/hasp_mqtt_esp.cpp @@ -71,7 +71,7 @@ bool last_mqtt_state = false; bool current_mqtt_state = false; uint16_t mqtt_reconnect_counter = 0; -void mqtt_run_scripts() +static inline void mqtt_run_scripts() { if(last_mqtt_state != current_mqtt_state) { // mqtt_message_t data; @@ -104,8 +104,8 @@ void mqtt_run_scripts() void mqtt_disconnected() { current_mqtt_state = false; // now we are disconnected - // mqtt_run_scripts(); mqtt_reconnect_counter++; + // mqtt_run_scripts(); // must happen in LVGL loop } void mqtt_connected() @@ -115,7 +115,7 @@ void mqtt_connected() current_mqtt_state = true; // now we are connected LOG_VERBOSE(TAG_MQTT, F("%s"), current_mqtt_state ? PSTR(D_SERVICE_CONNECTED) : PSTR(D_SERVICE_DISCONNECTED)); } - // mqtt_run_scripts(); + // mqtt_run_scripts(); // must happen in LVGL loop } int mqttPublish(const char* topic, const char* payload, size_t len, bool retain) @@ -337,7 +337,7 @@ String mqttGetTopic(Preferences preferences, String subtopic, String key, String } */ -void mqttParseTopic(String *topic, String subtopic, bool add_slash) +void mqttParseTopic(String* topic, String subtopic, bool add_slash) { topic->replace(F("%hostname%"), haspDevice.get_hostname()); @@ -509,10 +509,14 @@ IRAM_ATTR void mqttLoop(void) } } -void mqttEvery5Seconds(bool networkIsConnected) +void mqttEverySecond() { mqtt_run_scripts(); - // if(mqttEnabled && networkIsConnected && !mqttClientConnected) { +} + +void mqttEvery5Seconds(bool networkIsConnected) +{ + // if(mqttEnabled && networkIsConnected && !current_mqtt_state) { // LOG_TRACE(TAG_MQTT, F(D_MQTT_RECONNECTING)); // mqttStart(); // } @@ -535,7 +539,7 @@ void mqttStart() nvsOldGroup += preferences.getString(FP_CONFIG_GROUP, MQTT_GROUPNAME); nvsOldGroup += "/%topic%"; - subtopic = F(MQTT_TOPIC_COMMAND); + subtopic = F(MQTT_TOPIC_COMMAND); mqttNodeCommandTopic = preferences.getString(FP_CONFIG_NODE_TOPIC, MQTT_DEFAULT_NODE_TOPIC); mqttParseTopic(&mqttNodeCommandTopic, subtopic, false); mqttGroupCommandTopic = preferences.getString(FP_CONFIG_GROUP_TOPIC, nvsOldGroup.c_str()); diff --git a/src/mqtt/hasp_mqtt_paho_async.cpp b/src/mqtt/hasp_mqtt_paho_async.cpp index 6c4e35f2..fe1c0d47 100644 --- a/src/mqtt/hasp_mqtt_paho_async.cpp +++ b/src/mqtt/hasp_mqtt_paho_async.cpp @@ -3,8 +3,6 @@ /* Multi threaded asynchronous paho client */ -#include - #include "hasp_conf.h" #if HASP_USE_MQTT_ASYNC > 0 diff --git a/src/mqtt/hasp_mqtt_pubsubclient.cpp b/src/mqtt/hasp_mqtt_pubsubclient.cpp index 29e11b2f..9acd5ce8 100644 --- a/src/mqtt/hasp_mqtt_pubsubclient.cpp +++ b/src/mqtt/hasp_mqtt_pubsubclient.cpp @@ -14,10 +14,10 @@ #if defined(ARDUINO_ARCH_ESP32) #include -#include +// #include WiFiClient mqttNetworkClient; // WiFiClientSecure mqttNetworkClient; -extern const uint8_t rootca_crt_bundle_start[] asm("_binary_data_cert_x509_crt_bundle_bin_start"); +// extern const uint8_t rootca_crt_bundle_start[] asm("_binary_data_cert_x509_crt_bundle_bin_start"); #elif defined(ARDUINO_ARCH_ESP8266) #include #include From f175dc599aa2741141d946439fc1410670837f17 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Fri, 24 May 2024 21:58:15 +0200 Subject: [PATCH 43/55] Prepare LVFS support for /sdcard --- include/lv_conf_v7.h | 4 ++-- lib/lv_fs_if/lv_fs_if.c | 18 ++++++++++++++---- lib/lv_fs_if/lv_fs_pc.c | 28 ++++++++++------------------ user_setups/esp32/_esp32.ini | 2 +- user_setups/esp32s2/_esp32s2.ini | 2 +- 5 files changed, 28 insertions(+), 26 deletions(-) diff --git a/include/lv_conf_v7.h b/include/lv_conf_v7.h index 764be7bd..606203cc 100644 --- a/include/lv_conf_v7.h +++ b/include/lv_conf_v7.h @@ -211,7 +211,7 @@ typedef void* lv_group_user_data_t; #define LV_USE_FILESYSTEM 1 #if LV_USE_FILESYSTEM /*Declare the type of the user data of file system drivers (can be e.g. `void *`, `int`, `struct`)*/ -typedef void* lv_fs_drv_user_data_t; +typedef const char* lv_fs_drv_user_data_t; /*File system interface*/ #ifndef LV_USE_FS_IF @@ -229,7 +229,7 @@ typedef void* lv_fs_drv_user_data_t; //# define LV_FS_IF_SPIFFS '\0' // no internal esp Flash #endif #endif /*LV_USE_FS_IF*/ -#if HASP_TARGET_ARDUINO +#if HASP_TARGET_ARDUINO && !defined(LV_FS_PC_PATH) #define LV_FS_PC_PATH "/littlefs" #endif diff --git a/lib/lv_fs_if/lv_fs_if.c b/lib/lv_fs_if/lv_fs_if.c index 472edcf2..45c94def 100644 --- a/lib/lv_fs_if/lv_fs_if.c +++ b/lib/lv_fs_if/lv_fs_if.c @@ -14,6 +14,13 @@ /********************* * DEFINES *********************/ +#ifndef LV_FS_PC_PATH +#ifndef WIN32 +#define LV_FS_PC_PATH "./" /*Project root*/ +#else +#define LV_FS_PC_PATH ".\\" /*Project root*/ +#endif +#endif /*LV_FS_PATH*/ /********************** * TYPEDEFS @@ -26,8 +33,8 @@ void lv_fs_if_fatfs_init(void); #endif -#if LV_FS_IF_PC != '\0' -void lv_fs_if_pc_init(void); +#if LV_FS_IF_PC != '\0' || LV_FS_IF_SD != '\0' +void lv_fs_if_pc_init(char letter, const char* path); #endif /********************** @@ -48,13 +55,16 @@ void lv_fs_if_pc_init(void); void lv_fs_if_init(void) { #if LV_FS_IF_FATFS != '\0' - lv_fs_if_fatfs_init(); + lv_fs_if_fatfs_init(); #endif #if LV_FS_IF_PC != '\0' - lv_fs_if_pc_init(); + lv_fs_if_pc_init(LV_FS_IF_PC, LV_FS_PC_PATH); #endif +#if LV_FS_IF_SD != '\0' + lv_fs_if_pc_init(LV_FS_IF_SD, LV_FS_SD_PATH); +#endif } /********************** diff --git a/lib/lv_fs_if/lv_fs_pc.c b/lib/lv_fs_if/lv_fs_pc.c index 02aa1a41..b83e1ac3 100644 --- a/lib/lv_fs_if/lv_fs_pc.c +++ b/lib/lv_fs_if/lv_fs_pc.c @@ -19,17 +19,6 @@ #include #endif -/********************* - * DEFINES - *********************/ -#ifndef LV_FS_PC_PATH -#ifndef WIN32 -#define LV_FS_PC_PATH "./" /*Projet root*/ -#else -#define LV_FS_PC_PATH ".\\" /*Projet root*/ -#endif -#endif /*LV_FS_PATH*/ - /********************** * TYPEDEFS **********************/ @@ -77,7 +66,7 @@ static lv_fs_res_t fs_dir_close(lv_fs_drv_t* drv, void* dir_p); /** * Register a driver for the File system interface */ -void lv_fs_if_pc_init(void) +void lv_fs_if_pc_init(char letter, const char* path) { /*--------------------------------------------------- * Register the file system interface in LittlevGL @@ -107,6 +96,8 @@ void lv_fs_if_pc_init(void) fs_drv.dir_open_cb = fs_dir_open; fs_drv.dir_read_cb = fs_dir_read; + fs_drv.user_data = LV_FS_PC_PATH; + lv_fs_drv_register(&fs_drv); // char cur_path[512] = ""; @@ -145,10 +136,10 @@ static lv_fs_res_t fs_open(lv_fs_drv_t* drv, void* file_p, const char* path, lv_ #ifndef WIN32 char buf[256]; - sprintf(buf, LV_FS_PC_PATH "/%s", path); + sprintf(buf, "%s/%s", drv->user_data, path); #else char buf[256]; - sprintf(buf, LV_FS_PC_PATH "\\%s", path); + sprintf(buf, "%s\\%s", drv->user_data, path); #endif LV_LOG_USER(buf); @@ -255,6 +246,7 @@ static lv_fs_res_t fs_size(lv_fs_drv_t* drv, void* file_p, uint32_t* size_p) return LV_FS_RES_OK; } + /** * Give the position of the read write pointer * @param drv pointer to a driver where this function belongs @@ -318,8 +310,8 @@ static lv_fs_res_t fs_rename(lv_fs_drv_t* drv, const char* oldname, const char* static char new[512]; static char old[512]; - sprintf(old, LV_FS_PC_PATH "/%s", oldname); - sprintf(new, LV_FS_PC_PATH "/%s", newname); + sprintf(old, "%s/%s", drv->user_data, oldname); + sprintf(new, "%s/%s", drv->user_data, newname); int r = rename(old, new); @@ -365,7 +357,7 @@ static lv_fs_res_t fs_dir_open(lv_fs_drv_t* drv, void* dir_p, const char* path) #ifndef WIN32 /*Make the path relative to the current directory (the projects root folder)*/ char buf[256]; - sprintf(buf, LV_FS_PC_PATH "/%s", path); + sprintf(buf, "%s/%s", drv->user_data, path); if((d = opendir(buf)) == NULL) { return LV_FS_RES_FS_ERR; } else { @@ -380,7 +372,7 @@ static lv_fs_res_t fs_dir_open(lv_fs_drv_t* drv, void* dir_p, const char* path) /*Make the path relative to the current directory (the projects root folder)*/ char buf[256]; - sprintf(buf, LV_FS_PC_PATH "\\%s\\*", path); + sprintf(buf, "%s\\%s\\*", drv->user_data, path); strcpy(next_fn, ""); d = FindFirstFile(buf, &fdata); diff --git a/user_setups/esp32/_esp32.ini b/user_setups/esp32/_esp32.ini index 780997e5..93079589 100644 --- a/user_setups/esp32/_esp32.ini +++ b/user_setups/esp32/_esp32.ini @@ -45,7 +45,7 @@ build_flags = -D LV_ATTRIBUTE_FAST_MEM=IRAM_ATTR -D LV_ATTRIBUTE_TASK_HANDLER=IRAM_ATTR -D LV_USE_FS_IF=1 - ;-D LV_FS_PC_PATH="//littlefs" ; this needs to match the vfs mount pount + -D LV_FS_PC_PATH='"/littlefs"' ; this needs to match the vfs mount pount ; -- ArduinoJson build options ---------------------------- -D ARDUINOJSON_ENABLE_PROGMEM=1 ; for PROGMEM arguments ; -- tft_espi build options ------------------------ diff --git a/user_setups/esp32s2/_esp32s2.ini b/user_setups/esp32s2/_esp32s2.ini index 0cfc0156..7b042521 100644 --- a/user_setups/esp32s2/_esp32s2.ini +++ b/user_setups/esp32s2/_esp32s2.ini @@ -15,7 +15,7 @@ build_flags = -D LV_ATTRIBUTE_FAST_MEM= -D LV_ATTRIBUTE_TASK_HANDLER=IRAM_ATTR -D LV_USE_FS_IF=1 - ;-D LV_FS_PC_PATH="//littlefs" ; this needs to match the vfs mount pount + -D LV_FS_PC_PATH='"/littlefs"' ; this needs to match the vfs mount pount ; -- ArduinoJson build options ---------------------------- -D ARDUINOJSON_ENABLE_PROGMEM=1 ; for PROGMEM arguments ; -- tft_espi build options ------------------------ From b118e5624531d85e071ff8a55c15f53e1192118d Mon Sep 17 00:00:00 2001 From: fvanroie Date: Fri, 24 May 2024 22:06:17 +0200 Subject: [PATCH 44/55] Fix for lv_fs_if_pc_init --- lib/lv_fs_if/lv_fs_pc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/lv_fs_if/lv_fs_pc.c b/lib/lv_fs_if/lv_fs_pc.c index b83e1ac3..cca7afbd 100644 --- a/lib/lv_fs_if/lv_fs_pc.c +++ b/lib/lv_fs_if/lv_fs_pc.c @@ -78,7 +78,7 @@ void lv_fs_if_pc_init(char letter, const char* path) /*Set up fields...*/ fs_drv.file_size = sizeof(file_t); - fs_drv.letter = LV_FS_IF_PC; + fs_drv.letter = letter; fs_drv.open_cb = fs_open; fs_drv.close_cb = fs_close; fs_drv.read_cb = fs_read; @@ -96,7 +96,7 @@ void lv_fs_if_pc_init(char letter, const char* path) fs_drv.dir_open_cb = fs_dir_open; fs_drv.dir_read_cb = fs_dir_read; - fs_drv.user_data = LV_FS_PC_PATH; + fs_drv.user_data = path; lv_fs_drv_register(&fs_drv); From 944f92e588b9ca9fb5c177d0b253d386a788df8b Mon Sep 17 00:00:00 2001 From: fvanroie Date: Fri, 24 May 2024 22:18:57 +0200 Subject: [PATCH 45/55] Add mqttEverySecond --- src/mqtt/hasp_mqtt_paho_async.cpp | 7 +++++-- src/mqtt/hasp_mqtt_paho_single.cpp | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/mqtt/hasp_mqtt_paho_async.cpp b/src/mqtt/hasp_mqtt_paho_async.cpp index fe1c0d47..28b81d10 100644 --- a/src/mqtt/hasp_mqtt_paho_async.cpp +++ b/src/mqtt/hasp_mqtt_paho_async.cpp @@ -45,7 +45,7 @@ const char FP_CONFIG_GROUP[] PROGMEM = "group"; #include "hasp_mqtt.h" // functions to implement here #include "hasp/hasp_dispatch.h" // for dispatch_topic_payload -#include "hasp_debug.h" // for logging +#include "hasp_debug.h" // for logging #if !defined(_WIN32) #include @@ -436,7 +436,10 @@ void mqttSetup() mqttLwtTopic += MQTT_TOPIC_LWT; } -IRAM_ATTR void mqttLoop(){}; +IRAM_ATTR void mqttLoop() {}; + +void mqttEverySecond() +{} void mqttEvery5Seconds(bool wifiIsConnected) { diff --git a/src/mqtt/hasp_mqtt_paho_single.cpp b/src/mqtt/hasp_mqtt_paho_single.cpp index 653a884f..50044044 100644 --- a/src/mqtt/hasp_mqtt_paho_single.cpp +++ b/src/mqtt/hasp_mqtt_paho_single.cpp @@ -391,6 +391,9 @@ IRAM_ATTR void mqttLoop() if(rc == MQTTCLIENT_SUCCESS && message) mqtt_message_arrived(mqtt_client, topicName, topicLen, message); }; +void mqttEverySecond() +{} + void mqttEvery5Seconds(bool wifiIsConnected) { if(!mqttIsConnected()) { From 57207c7119cfc7c3ad5ee4d4723eb956480cdd10 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Mon, 27 May 2024 17:11:00 +0200 Subject: [PATCH 46/55] Update ace.js to 1.34.2 --- data/edit.htm | 2 +- data/script.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/edit.htm b/data/edit.htm index 4d1ccace..41bcd04b 100644 --- a/data/edit.htm +++ b/data/edit.htm @@ -1 +1 @@ -openHASP File Editor
L:
  • New File
  • Upload Files
  • Edit
  • Preview
  • Download
  • Delete
\ No newline at end of file +openHASP File Editor
L:
  • New File
  • Upload Files
  • Edit
  • Preview
  • Download
  • Delete
\ No newline at end of file diff --git a/data/script.js b/data/script.js index e9705de1..da51ed7d 100644 --- a/data/script.js +++ b/data/script.js @@ -1 +1 @@ -var ctx_el;function _(e){return document.getElementById(e)}function hidectx(){_("ctx").style.display="none",ctx_el&&ctx_el.classList.remove("selitem"),ctx_el=void 0}function doesFontExist(e){var t=document.createElement("canvas"),n=t.getContext("2d"),o="abcdefghijklmnopqrstuvwxyz0123456789";n.font="72px monospace";var a=n.measureText(o).width;return n.font="72px '"+e+"', monospace",t=null,n.measureText(o).width!=a}function createEditor(e,t,n,o,a){function i(e){let t=/(?:\.([^.]+))?$/.exec(e)[1];if(void 0!==typeof t)switch(t){case"htm":case"html":return"html";case"js":return"javascript";case"cmd":case"json":case"jsonl":return"json";case"css":case"svg":case"xml":return t}return"plain_text"}void 0===n&&(n=i(t)),void 0===a&&(a="text/"+n);["basePath","modePath","themePath"].forEach((e=>{ace.config.set(e,"https://cdnjs.cloudflare.com/ajax/libs/ace/1.34.1")}));var c=ace.edit(e,{useWorker:!1,wrap:!0,indentedSoftWrap:!1,showPrintMargin:!1,highlightGutterLine:!0,useSoftTabs:!0,tabSize:2});c.setFontSize(parseFloat(getComputedStyle(document.documentElement).fontSize)),c.setReadOnly(!0),c.getSession().setUndoManager(new ace.UndoManager),void 0===o&&(o=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"monokai":"textmate");var s=_("save"),l=_("undo"),r=_("redo"),d=_("cut"),m=_("copy"),u=_("paste"),p=_("font"),f=_("fontsize"),g="none"!==_(e).display;f.value=parseFloat(c.getFontSize()).toFixed(1),p.onchange=function(){c.setOption("fontFamily","'"+p.value+"',monospace")},f.onchange=function(){var e=parseFloat(f.value);!isNaN(e)&&e>=9&&e<=40&&c.setFontSize(e),f.value=parseFloat(c.getFontSize()).toFixed(1)};function h(){let e=!g||c.session.getSelection().isEmpty();d.disabled=e,m.disabled=e}function y(){let e=c.session.getUndoManager();s.disabled=!g||e.isClean(),l.disabled=!g||!e.hasUndo(),r.disabled=!g||!e.hasRedo()}function v(){if(void 0===t)return;const e=function(e){var t=e.getValue();try{var n=JSON.parse(t);return JSON.stringify(n)}catch(e){return t+""}}(c),n=new FormData;n.append("data",new Blob([e],{type:a}),t),fetch("/edit",{method:"POST",body:n}).then((e=>e.ok?e.text().then((e=>{console.log("Save OK /edit "+e)})):e.text().then((e=>{throw console.log("Save FAIL /edit"),new Error(e)})))).then((e=>{console.log(e),generateToast({message:"Saved "+t,background:"#ddd",color:"#000"})})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{y()}))}function x(){var e=c.getCopyText();if(window.clipboardData&&window.clipboardData.setData)return window.clipboardData.setData("Text",e);if(document.queryCommandSupported&&document.queryCommandSupported("copy")){c.focus();try{return document.execCommand("copy")}catch(t){return console.warn("Copy to clipboard failed.",t),prompt("Copy to clipboard: Ctrl+C, Enter",e)}}}function w(e){_("name").innerHTML=e;fetch(e).then((t=>t.ok?(console.log("OK "+e),t.text()):t.text().then((e=>{throw console.log("ERROR "+url),new Error(e)})))).then((e=>{try{var t=JSON.parse(e);c.setValue(JSON.stringify(t,null,4)),console.log("parse json OK")}catch(t){c.setValue(e),console.log("parse json FAIL")}null!==_("editor")&&(_("editor").style.display="block"),null!==_("preview")&&(_("preview").style.display="none"),g=!0,c.setReadOnly(!1),c.focus(),y()})).catch((e=>{console.log(e),alert(e),c.setReadOnly(!0)})).finally((()=>{c.resize(!0),c.scrollToLine(1,!0,!0,(function(){})),c.gotoLine(1,0,!0),c.clearSelection(),c.session.getUndoManager().reset()}))}return["Courier New","Monaco","Lucida Console","Monospace","ui-monospace","Roboto Mono","Inconsolata","IBM Plex Mono","Space Mono","PT Mono","Ubuntu Mono","Nanum Gothic Coding","Cousine","Fira Mono","Share Tech Mono","Courier Prime","Anonymous Pro","Cutive Mono","Overpass Mono","Fira Code","VT323","DM Mono","Oxygen Mono","Nova Mono","B612 Mono","Spline Sans Mono","Noto Sans Mono","Major Mono Display","Azeret Mono","Red Hat Mono","Syne Mono","Xanh Mono"].sort().forEach((function(e,t){if(doesFontExist(e)){var n=document.createElement("option");n.text=e,p.add(n)}})),null!==s&&null!==l&&null!==r&&c.on("input",y),c.session.selection.on("changeCursor",h),s.onclick=v,l.onclick=e=>{c.undo()&&c.focus()},r.onclick=e=>{c.redo()&&c.focus()},d.onclick=e=>{x()&&c.execCommand("cut")},m.onclick=e=>{x()&&c.execCommand("copy")},u.onclick=function(){try{navigator.clipboard.readText().then((e=>{c.execCommand("paste",e)})).catch((e=>{u.disabled=!0}))}catch{u.disabled=!0}},c.loadUrl=(e,o)=>{n=i(t=e+o),a="text/"+n,"plain"!==n&&c.getSession().setMode("ace/mode/"+n),w(e+o)},c.hide=()=>{g=!1,y(),h(),_("editor").style.display="none"},"plain"!==n&&c.getSession().setMode("ace/mode/"+n),c.setTheme("ace/theme/"+o),c.$blockScrolling=1/0,c.commands.addCommand({name:"save",bindKey:{win:"Ctrl-S",mac:"Command-S"},exec:v,readOnly:!1}),c.commands.addCommand({name:"undo",bindKey:{win:"Ctrl-Z",mac:"Command-Z"},exec:function(){c.undo()}}),c.commands.addCommand({name:"redo",bindKey:{win:"Ctrl-Y",mac:"Command-Y"},exec:function(){c.redo()}}),void 0!==t&&w(t),c.resize(),c}function uploadFileAsync(e,t,n,o,a,i){fetchData("/edit","POST",e).then((e=>{generateToast({message:"Upload "+n+"/"+o+" "+t+" done.",background:"#ddd",color:"#000"}),n==o&&listFiles(a,i)}))}function doUpload(e,t){const n=_("upload"),o=n.files.length;if(0!==o)for(let a=0;a=0}function isText(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"txt":case"cmd":case"json":case"jsonl":case"htm":case"html":case"js":case"c":case"cpp":case"css":case"svg":case"xml":return!0}return!1}function isImage(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"bmp":case"png":case"jpg":case"gif":case"svg":return!0}return!1}function isAudio(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"wav":case"mp3":case"aac":case"m4a":case"wma":return!0}return!1}function icon(e){if(isFolder(e))return"dir";if(isImage(e))return"image";if(isAudio(e))return"audio";var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"cmd":case"css":case"json":case"jsonl":case"ttf":return t;case"zip":case"gz":return"zip";case"html":case"htm":return"html"}return"file"}function preview(e,t){if(isImage(e)){let n=t+e.name;const o=_("preview");o.innerHTML='',o.style.display="block",ace.edit("editor").hide(),_("name").innerHTML=n}}function edit(e,t){isText(e)&&(ace.edit("editor").loadUrl(t,e.name),_("preview").style.display="none")}function url(e,t){console.log("click "+t+e.name),isImage(e)?preview(e,t):isText(e)&&edit(e,t)}async function fetchData(e,t,n,o){await fetch(e,{method:t,body:n}).then((n=>n.ok?(console.log(t+" OK "+e),n.text()):n.text().then((n=>{throw console.log(t+" FAIL "+e),new Error(n)})))).then((e=>{o&&o.remove(),console.log(e)})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{}))}function download(e,t){console.log("download "+t+e.name),document.getElementById("download-frame").src=t+e.name+"?download=true"}function remove(e,t,n){let o=t+e.name;isFolder(e)&&(o+="/"),console.log("remove "+o);const a=new FormData;a.append("path",o),fetchData("/edit","DELETE",a,n)}function create(e,t,n){var o=window.prompt("Create File in "+e,"");if(null==o||""==o||o.includes("/"))return;const a=new FormData;a.append("path",e+o),fetchData("/edit","PUT",a),fetch("/api/files/").then((e=>e.json())).then((o=>{t&&t.remove(),listFiles(n,e),console.log(o)}))}function upload(e,t){_("upload").onchange=()=>{doUpload(e,t)},_("upload").click()}function ctx(e,t,n,o){e.preventDefault(),ctx_el=o;let a,i=isFolder(t),c=_("ctx");c.style.display="block",a=c.getElementsByTagName("li")[0],a.onclick=i?function(){hidectx(),create(n+t.name+"/",o.children.item(1),o)}:function(){hidectx(),create(n,o.parentNode,o.parentNode.parentNode)},a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[1],i&&(a.onclick=function(){hidectx(),upload(o,n+t.name+"/")}),a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[2],a.onclick=function(){edit(t,n),hidectx()},a.style.display=isText(t)?"block":"none",a=c.getElementsByTagName("li")[3],a.onclick=function(){preview(t,n),hidectx()},a.style.display=isImage(t)?"block":"none",a=c.getElementsByTagName("li")[4],a.onclick=function(){download(t,n),hidectx()},a.style.display=i?"none":"block",a=c.getElementsByTagName("li")[5],a.onclick=function(){remove(t,n,o),hidectx()},a.style.display=n?"block":"none";var s=document.body.scrollTop?document.body.scrollTop:document.documentElement.scrollTop,l=document.body.scrollLeft?document.body.scrollLeft:document.documentElement.scrollLeft,r=e.clientX+l+10,d=e.clientY+s-20,m=(c.offsetWidth,c.offsetHeight),u=document.documentElement.clientHeight;d+m>u&&(d=u-m-20),c.style.left=r+"px",c.style.top=d+"px",o&&o.classList.add("selitem")}function drag(e,t,n){let o=n+t.name;isFolder(t)&&(o+="/"),e.dataTransfer.setData("text",o),console.log("drag start "+o)}function drop(e,t){let n=e.dataTransfer.getData("text");n.startsWith(t)||(e.preventDefault(),console.log("Move "+n+" to "+t))}function listFiles(e,t){return console.log("listFiles"),fetch("/api/files/?dir="+t).then((e=>e.json())).then((n=>{if(0==n.length)return!1;let o=e.getElementsByTagName("div")[0];o&&(o.onclick=n=>{i.remove(),o.onclick=()=>{listFiles(e,t)},n.stopPropagation()});let a=e.getElementsByTagName("ul");for(let e=0;e{drag(event,e,t)},a.appendChild(s),s.innerHTML=''+o+"",isFolder(e)){let n=t+e.name+"/";s.classList.add("bold"),s.onclick=function(e){listFiles(a,n)},s.ondragover=e=>{e.preventDefault()},s.ondrop=e=>{drop(e,n)}}else(isText(e)||isImage(e)||isAudio(e))&&(s.onclick=function(n){url(e,t)});s.oncontextmenu=n=>{ctx(n,e,t,a)}}return e.scrollIntoView(),!0}))}function generateToast({message:e,background:t="#00214d",color:n="#fffffe",length:o="7000ms"}){_("toast").insertAdjacentHTML("afterbegin",`

\n ${e}\n

`);const a=_("toast").firstElementChild;a.addEventListener("animationend",(()=>a.remove()))}document.addEventListener("blur",(function(){hidectx()})),document.addEventListener("DOMContentLoaded",(function(){createEditor("editor",void 0,void 0,void 0);listFiles(_("tree"),"/"),_("tree").getElementsByTagName("div")[0].oncontextmenu=e=>{ctx(e,{name:"",children:[]},"",_("tree"))},_("load").onclick=function(e){const t=new FormData;t.append("load",""),fetchData("/edit","PUT",t)},_("init").onclick=function(e){const t=new FormData;t.append("init",""),fetchData("/edit","PUT",t)},_("home").onclick=function(e){window.location.href="/"},_("page").onchange=function(e){const t=new FormData;t.append("page",_("page").value),fetchData("/edit","PUT",t)}})),document.addEventListener("DOMContentLoaded",(function(){const e=document.getElementById("dragMe"),t=e.previousElementSibling,n=e.nextElementSibling;let o=0,a=0,i=0;const c=function(a){const c=a.clientX-o,s=(a.clientY,100*(i+c)/e.parentNode.getBoundingClientRect().width);t.style.width=`${s}%`,t.style.right=t.style.width,e.style.cursor="col-resize",document.body.style.cursor="col-resize",t.style.userSelect="none",t.style.pointerEvents="none",n.style.userSelect="none",n.style.pointerEvents="none",ace.edit("editor").resize()},s=function(){e.style.removeProperty("cursor"),document.body.style.removeProperty("cursor"),t.style.removeProperty("user-select"),t.style.removeProperty("pointer-events"),n.style.removeProperty("user-select"),n.style.removeProperty("pointer-events"),document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",s)};e.addEventListener("mousedown",(function(e){o=e.clientX,a=e.clientY,i=t.getBoundingClientRect().width,document.addEventListener("mousemove",c),document.addEventListener("mouseup",s)})),e.addEventListener("dblclick",(()=>{var e=t.style.visibility="hidden"===t.style.visibility;t.style.visibility=e?"unset":"hidden",t.style.position=e?"unset":"absolute",ace.edit("editor").resize()}))})); \ No newline at end of file +var ctx_el;function _(e){return document.getElementById(e)}function hidectx(){_("ctx").style.display="none",ctx_el&&ctx_el.classList.remove("selitem"),ctx_el=void 0}function doesFontExist(e){var t=document.createElement("canvas"),n=t.getContext("2d"),o="abcdefghijklmnopqrstuvwxyz0123456789";n.font="72px monospace";var a=n.measureText(o).width;return n.font="72px '"+e+"', monospace",t=null,n.measureText(o).width!=a}function createEditor(e,t,n,o,a){function i(e){let t=/(?:\.([^.]+))?$/.exec(e)[1];if(void 0!==typeof t)switch(t){case"htm":case"html":return"html";case"js":return"javascript";case"cmd":case"json":case"jsonl":return"json";case"css":case"svg":case"xml":return t}return"plain_text"}void 0===n&&(n=i(t)),void 0===a&&(a="text/"+n);["basePath","modePath","themePath"].forEach((e=>{ace.config.set(e,"https://cdnjs.cloudflare.com/ajax/libs/ace/1.34.2")}));var c=ace.edit(e,{useWorker:!1,wrap:!0,indentedSoftWrap:!1,showPrintMargin:!1,highlightGutterLine:!0,useSoftTabs:!0,tabSize:2});c.setFontSize(parseFloat(getComputedStyle(document.documentElement).fontSize)),c.setReadOnly(!0),c.getSession().setUndoManager(new ace.UndoManager),void 0===o&&(o=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"monokai":"textmate");var s=_("save"),l=_("undo"),r=_("redo"),d=_("cut"),m=_("copy"),u=_("paste"),p=_("font"),f=_("fontsize"),g="none"!==_(e).display;f.value=parseFloat(c.getFontSize()).toFixed(1),p.onchange=function(){c.setOption("fontFamily","'"+p.value+"',monospace")},f.onchange=function(){var e=parseFloat(f.value);!isNaN(e)&&e>=9&&e<=40&&c.setFontSize(e),f.value=parseFloat(c.getFontSize()).toFixed(1)};function h(){let e=!g||c.session.getSelection().isEmpty();d.disabled=e,m.disabled=e}function y(){let e=c.session.getUndoManager();s.disabled=!g||e.isClean(),l.disabled=!g||!e.hasUndo(),r.disabled=!g||!e.hasRedo()}function v(){if(void 0===t)return;const e=function(e){var t=e.getValue();try{var n=JSON.parse(t);return JSON.stringify(n)}catch(e){return t+""}}(c),n=new FormData;n.append("data",new Blob([e],{type:a}),t),fetch("/edit",{method:"POST",body:n}).then((e=>e.ok?e.text().then((e=>{console.log("Save OK /edit "+e)})):e.text().then((e=>{throw console.log("Save FAIL /edit"),new Error(e)})))).then((e=>{console.log(e),generateToast({message:"Saved "+t,background:"#ddd",color:"#000"})})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{y()}))}function x(){var e=c.getCopyText();if(window.clipboardData&&window.clipboardData.setData)return window.clipboardData.setData("Text",e);if(document.queryCommandSupported&&document.queryCommandSupported("copy")){c.focus();try{return document.execCommand("copy")}catch(t){return console.warn("Copy to clipboard failed.",t),prompt("Copy to clipboard: Ctrl+C, Enter",e)}}}function w(e){_("name").innerHTML=e;fetch(e).then((t=>t.ok?(console.log("OK "+e),t.text()):t.text().then((e=>{throw console.log("ERROR "+url),new Error(e)})))).then((e=>{try{var t=JSON.parse(e);c.setValue(JSON.stringify(t,null,4)),console.log("parse json OK")}catch(t){c.setValue(e),console.log("parse json FAIL")}null!==_("editor")&&(_("editor").style.display="block"),null!==_("preview")&&(_("preview").style.display="none"),g=!0,c.setReadOnly(!1),c.focus(),y()})).catch((e=>{console.log(e),alert(e),c.setReadOnly(!0)})).finally((()=>{c.resize(!0),c.scrollToLine(1,!0,!0,(function(){})),c.gotoLine(1,0,!0),c.clearSelection(),c.session.getUndoManager().reset()}))}return["Courier New","Monaco","Lucida Console","Monospace","ui-monospace","Roboto Mono","Inconsolata","IBM Plex Mono","Space Mono","PT Mono","Ubuntu Mono","Nanum Gothic Coding","Cousine","Fira Mono","Share Tech Mono","Courier Prime","Anonymous Pro","Cutive Mono","Overpass Mono","Fira Code","VT323","DM Mono","Oxygen Mono","Nova Mono","B612 Mono","Spline Sans Mono","Noto Sans Mono","Major Mono Display","Azeret Mono","Red Hat Mono","Syne Mono","Xanh Mono"].sort().forEach((function(e,t){if(doesFontExist(e)){var n=document.createElement("option");n.text=e,p.add(n)}})),null!==s&&null!==l&&null!==r&&c.on("input",y),c.session.selection.on("changeCursor",h),s.onclick=v,l.onclick=e=>{c.undo()&&c.focus()},r.onclick=e=>{c.redo()&&c.focus()},d.onclick=e=>{x()&&c.execCommand("cut")},m.onclick=e=>{x()&&c.execCommand("copy")},u.onclick=function(){try{navigator.clipboard.readText().then((e=>{c.execCommand("paste",e)})).catch((e=>{u.disabled=!0}))}catch{u.disabled=!0}},c.loadUrl=(e,o)=>{n=i(t=e+o),a="text/"+n,"plain"!==n&&c.getSession().setMode("ace/mode/"+n),w(e+o)},c.hide=()=>{g=!1,y(),h(),_("editor").style.display="none"},"plain"!==n&&c.getSession().setMode("ace/mode/"+n),c.setTheme("ace/theme/"+o),c.$blockScrolling=1/0,c.commands.addCommand({name:"save",bindKey:{win:"Ctrl-S",mac:"Command-S"},exec:v,readOnly:!1}),c.commands.addCommand({name:"undo",bindKey:{win:"Ctrl-Z",mac:"Command-Z"},exec:function(){c.undo()}}),c.commands.addCommand({name:"redo",bindKey:{win:"Ctrl-Y",mac:"Command-Y"},exec:function(){c.redo()}}),void 0!==t&&w(t),c.resize(),c}function uploadFileAsync(e,t,n,o,a,i){fetchData("/edit","POST",e).then((e=>{generateToast({message:"Upload "+n+"/"+o+" "+t+" done.",background:"#ddd",color:"#000"}),n==o&&listFiles(a,i)}))}function doUpload(e,t){const n=_("upload"),o=n.files.length;if(0!==o)for(let a=0;a=0}function isText(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"txt":case"cmd":case"json":case"jsonl":case"htm":case"html":case"js":case"c":case"cpp":case"css":case"svg":case"xml":return!0}return!1}function isImage(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"bmp":case"png":case"jpg":case"gif":case"svg":return!0}return!1}function isAudio(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"wav":case"mp3":case"aac":case"m4a":case"wma":return!0}return!1}function icon(e){if(isFolder(e))return"dir";if(isImage(e))return"image";if(isAudio(e))return"audio";var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"cmd":case"css":case"json":case"jsonl":case"ttf":return t;case"zip":case"gz":return"zip";case"html":case"htm":return"html"}return"file"}function preview(e,t){if(isImage(e)){let n=t+e.name;const o=_("preview");o.innerHTML='',o.style.display="block",ace.edit("editor").hide(),_("name").innerHTML=n}}function edit(e,t){isText(e)&&(ace.edit("editor").loadUrl(t,e.name),_("preview").style.display="none")}function url(e,t){console.log("click "+t+e.name),isImage(e)?preview(e,t):isText(e)&&edit(e,t)}async function fetchData(e,t,n,o){await fetch(e,{method:t,body:n}).then((n=>n.ok?(console.log(t+" OK "+e),n.text()):n.text().then((n=>{throw console.log(t+" FAIL "+e),new Error(n)})))).then((e=>{o&&o.remove(),console.log(e)})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{}))}function download(e,t){console.log("download "+t+e.name),document.getElementById("download-frame").src=t+e.name+"?download=true"}function remove(e,t,n){let o=t+e.name;isFolder(e)&&(o+="/"),console.log("remove "+o);const a=new FormData;a.append("path",o),fetchData("/edit","DELETE",a,n)}function create(e,t,n){var o=window.prompt("Create File in "+e,"");if(null==o||""==o||o.includes("/"))return;const a=new FormData;a.append("path",e+o),fetchData("/edit","PUT",a),fetch("/api/files/").then((e=>e.json())).then((o=>{t&&t.remove(),listFiles(n,e),console.log(o)}))}function upload(e,t){_("upload").onchange=()=>{doUpload(e,t)},_("upload").click()}function ctx(e,t,n,o){e.preventDefault(),ctx_el=o;let a,i=isFolder(t),c=_("ctx");c.style.display="block",a=c.getElementsByTagName("li")[0],a.onclick=i?function(){hidectx(),create(n+t.name+"/",o.children.item(1),o)}:function(){hidectx(),create(n,o.parentNode,o.parentNode.parentNode)},a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[1],i&&(a.onclick=function(){hidectx(),upload(o,n+t.name+"/")}),a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[2],a.onclick=function(){edit(t,n),hidectx()},a.style.display=isText(t)?"block":"none",a=c.getElementsByTagName("li")[3],a.onclick=function(){preview(t,n),hidectx()},a.style.display=isImage(t)?"block":"none",a=c.getElementsByTagName("li")[4],a.onclick=function(){download(t,n),hidectx()},a.style.display=i?"none":"block",a=c.getElementsByTagName("li")[5],a.onclick=function(){remove(t,n,o),hidectx()},a.style.display=n?"block":"none";var s=document.body.scrollTop?document.body.scrollTop:document.documentElement.scrollTop,l=document.body.scrollLeft?document.body.scrollLeft:document.documentElement.scrollLeft,r=e.clientX+l+10,d=e.clientY+s-20,m=(c.offsetWidth,c.offsetHeight),u=document.documentElement.clientHeight;d+m>u&&(d=u-m-20),c.style.left=r+"px",c.style.top=d+"px",o&&o.classList.add("selitem")}function drag(e,t,n){let o=n+t.name;isFolder(t)&&(o+="/"),e.dataTransfer.setData("text",o),console.log("drag start "+o)}function drop(e,t){let n=e.dataTransfer.getData("text");n.startsWith(t)||(e.preventDefault(),console.log("Move "+n+" to "+t))}function listFiles(e,t){return console.log("listFiles"),fetch("/api/files/?dir="+t).then((e=>e.json())).then((n=>{if(0==n.length)return!1;let o=e.getElementsByTagName("div")[0];o&&(o.onclick=n=>{i.remove(),o.onclick=()=>{listFiles(e,t)},n.stopPropagation()});let a=e.getElementsByTagName("ul");for(let e=0;e{drag(event,e,t)},a.appendChild(s),s.innerHTML=''+o+"",isFolder(e)){let n=t+e.name+"/";s.classList.add("bold"),s.onclick=function(e){listFiles(a,n)},s.ondragover=e=>{e.preventDefault()},s.ondrop=e=>{drop(e,n)}}else(isText(e)||isImage(e)||isAudio(e))&&(s.onclick=function(n){url(e,t)});s.oncontextmenu=n=>{ctx(n,e,t,a)}}return e.scrollIntoView(),!0}))}function generateToast({message:e,background:t="#00214d",color:n="#fffffe",length:o="7000ms"}){_("toast").insertAdjacentHTML("afterbegin",`

\n ${e}\n

`);const a=_("toast").firstElementChild;a.addEventListener("animationend",(()=>a.remove()))}document.addEventListener("blur",(function(){hidectx()})),document.addEventListener("DOMContentLoaded",(function(){createEditor("editor",void 0,void 0,void 0);listFiles(_("tree"),"/"),_("tree").getElementsByTagName("div")[0].oncontextmenu=e=>{ctx(e,{name:"",children:[]},"",_("tree"))},_("load").onclick=function(e){const t=new FormData;t.append("load",""),fetchData("/edit","PUT",t)},_("init").onclick=function(e){const t=new FormData;t.append("init",""),fetchData("/edit","PUT",t)},_("home").onclick=function(e){window.location.href="/"},_("page").onchange=function(e){const t=new FormData;t.append("page",_("page").value),fetchData("/edit","PUT",t)}})),document.addEventListener("DOMContentLoaded",(function(){const e=document.getElementById("dragMe"),t=e.previousElementSibling,n=e.nextElementSibling;let o=0,a=0,i=0;const c=function(a){const c=a.clientX-o,s=(a.clientY,100*(i+c)/e.parentNode.getBoundingClientRect().width);t.style.width=`${s}%`,t.style.right=t.style.width,e.style.cursor="col-resize",document.body.style.cursor="col-resize",t.style.userSelect="none",t.style.pointerEvents="none",n.style.userSelect="none",n.style.pointerEvents="none",ace.edit("editor").resize()},s=function(){e.style.removeProperty("cursor"),document.body.style.removeProperty("cursor"),t.style.removeProperty("user-select"),t.style.removeProperty("pointer-events"),n.style.removeProperty("user-select"),n.style.removeProperty("pointer-events"),document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",s)};e.addEventListener("mousedown",(function(e){o=e.clientX,a=e.clientY,i=t.getBoundingClientRect().width,document.addEventListener("mousemove",c),document.addEventListener("mouseup",s)})),e.addEventListener("dblclick",(()=>{var e=t.style.visibility="hidden"===t.style.visibility;t.style.visibility=e?"unset":"hidden",t.style.position=e?"unset":"absolute",ace.edit("editor").resize()}))})); \ No newline at end of file From c4217a92e893ee7f9d57438220647998639b5bde Mon Sep 17 00:00:00 2001 From: adampr1 Date: Thu, 30 May 2024 17:12:30 +0200 Subject: [PATCH 47/55] Add support for Waveshare ESP32-S3-Touch-LCD-4.3 Add suppor for ws_esp32_s3_touch_lcd_4p3 from post https://github.com/HASwitchPlate/openHASP/discussions/602 --- platformio_override-template.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio_override-template.ini b/platformio_override-template.ini index 69a865c2..c3791ae8 100644 --- a/platformio_override-template.ini +++ b/platformio_override-template.ini @@ -78,6 +78,7 @@ extra_default_envs = ; wt-86-32-3zw1 ; yeacreate-nscreen32 ; wz2432r028 + ; ws_esp32_s3_touch_lcd_4p3 ;endregion ;region -- Define your local COM ports for each environment --- From 91074746039acdb7e90b5ac58988ffd3c0ea090e Mon Sep 17 00:00:00 2001 From: adampr1 Date: Thu, 30 May 2024 17:14:42 +0200 Subject: [PATCH 48/55] Add support for Waveshare ESP32-S3-Touch-LCD-4.3 Add support for Waveshare ESP32-S3-Touch-LCD-4.3 from https://github.com/HASwitchPlate/openHASP/discussions/602 --- .../esp32s3/ws_esp32_s3_touch_lcd_4p3.ini | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 user_setups/esp32s3/ws_esp32_s3_touch_lcd_4p3.ini diff --git a/user_setups/esp32s3/ws_esp32_s3_touch_lcd_4p3.ini b/user_setups/esp32s3/ws_esp32_s3_touch_lcd_4p3.ini new file mode 100644 index 00000000..fd766e4a --- /dev/null +++ b/user_setups/esp32s3/ws_esp32_s3_touch_lcd_4p3.ini @@ -0,0 +1,86 @@ +;***************************************************; +; Waveshare ESP32-S3-Touch-LCD-4.3 ; +; - 16-bit RGB TFT ; +; - GT911 touch controller ; +;***************************************************; + + +[ws_esp32_s3_touch] +extends = arduino_esp32s3_v2, flash_8mb +board = esp32-s3-devkitc-1 +board_build.arduino.memory_type = qio_opi + +build_flags = + ${arduino_esp32s3_v2.build_flags} + ${esp32s3.ps_ram} + ;-DARDUINO_USB_CDC_ON_BOOT + ;-DUSE_USB_CDC_CONSOLE + +;region -- ArduinoGFX build options ------------------------ + -D HASP_USE_ARDUINOGFX=1 + -D HASP_LV_USE_SW_ROTATE=1 +;endregion + +lib_deps = + ${arduino_esp32s3_v2.lib_deps} + ${arduinogfx.lib_deps} + Arduino_RPi_DPI_RGBPanel_mod + ${goodix.lib_deps} + +[env:ws_esp32_s3_touch_lcd_4p3] +extends = ws_esp32_s3_touch + +build_flags = + -D HASP_MODEL="Waveshare ESP32-S3-Touch-LCD-4.3" + ${ws_esp32_s3_touch.build_flags} + ; Bus Settings + -D LV_VDB_SIZE=76800 ; 10% of full framebuffer + -D TFT_WIDTH=800 + -D TFT_HEIGHT=480 + -D TFT_DE=5 + -D TFT_VSYNC=3 + -D TFT_HSYNC=46 + -D TFT_PCLK=7 + -D TFT_B0=14 + -D TFT_B1=38 + -D TFT_B2=18 + -D TFT_B3=17 + -D TFT_B4=10 + -D TFT_G0=39 + -D TFT_G1=0 + -D TFT_G2=45 + -D TFT_G3=48 + -D TFT_G4=47 + -D TFT_G5=21 + -D TFT_R0=1 + -D TFT_R1=2 + -D TFT_R2=42 + -D TFT_R3=41 + -D TFT_R4=40 + -D TFT_BCKL=6 ; use GPIO06 as backlight PIN + ; Panel Settings + -D TFT_HSYNC_POLARITY=0 + -D TFT_HSYNC_FRONT_PORCH=20 ; Maximum HSYNC Front Porch + -D TFT_HSYNC_PULSE_WIDTH=10 ; Typical HSYNC Pulse Width + -D TFT_HSYNC_BACK_PORCH=10 ; Typical HSYNC Back Porch + -D TFT_VSYNC_POLARITY=0 + -D TFT_VSYNC_FRONT_PORCH=10 ; Maximum VSYNC Front Porch + -D TFT_VSYNC_PULSE_WIDTH=10 ; Typical VSYNC Pulse Width + -D TFT_VSYNC_BACK_PORCH=10 ; Typical VSYNC Back Porch + -D TFT_PCLK_ACTIVE_NEG=0 + -D TFT_PREFER_SPEED=14000000 ; 1/2 of Typical DCLK Frequency + -D TFT_AUTO_FLUSH=1 + ; Touch Settings + -D TOUCH_WIDTH=800 + -D TOUCH_HEIGHT=480 + -D TOUCH_DRIVER=0x911 + -D TOUCH_SCL=9 + -D TOUCH_SDA=8 + -D TOUCH_IRQ=-1 + -D TOUCH_RST=-1 + -D I2C_TOUCH_ADDRESS=0x5d ; or 0x5D + -D I2C_TOUCH_FREQUENCY=400000 + -D BACKLIGHT_FREQUENCY=1000 ;adopted frerquency for MP3302DJ-LF-Z (200 to 1000Hz) ->higher is better for sound! +lib_deps = + ${sunton-esp32-s3-tft.lib_deps} + ${goodix.lib_deps} From 94ceaf2cf132d1e1bef4b231ecac40f99779a9a6 Mon Sep 17 00:00:00 2001 From: FreeBear Date: Fri, 14 Jun 2024 00:03:26 +0100 Subject: [PATCH 49/55] Was a mistake to hide TFT_BCKL gpio pin from the user. On some boards, it can be reassigned by the user (on others, it is baked in to the hardware). --- src/drv/tft/tft_driver_arduinogfx.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/drv/tft/tft_driver_arduinogfx.cpp b/src/drv/tft/tft_driver_arduinogfx.cpp index f9fc214f..4bc12004 100644 --- a/src/drv/tft/tft_driver_arduinogfx.cpp +++ b/src/drv/tft/tft_driver_arduinogfx.cpp @@ -296,9 +296,6 @@ bool ArduinoGfx::is_driver_pin(uint8_t pin) #ifdef TFT_HSYNC || (pin == TFT_HSYNC) #endif -#ifdef TFT_BCKL - || (pin == TFT_BCKL) -#endif #ifdef TFT_RST || (pin == TFT_RST) #endif From 20256b2953bf58edb07fc3e5a00e4e0bb6b9d97b Mon Sep 17 00:00:00 2001 From: fvanroie Date: Thu, 18 Jul 2024 20:03:07 +0200 Subject: [PATCH 50/55] Update ace.js to v1.35.3 --- data/edit.htm | 2 +- data/script.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/edit.htm b/data/edit.htm index 41bcd04b..1a112286 100644 --- a/data/edit.htm +++ b/data/edit.htm @@ -1 +1 @@ -openHASP File Editor
L:
  • New File
  • Upload Files
  • Edit
  • Preview
  • Download
  • Delete
\ No newline at end of file +openHASP File Editor
L:
  • New File
  • Upload Files
  • Edit
  • Preview
  • Download
  • Delete
\ No newline at end of file diff --git a/data/script.js b/data/script.js index da51ed7d..93a1d96d 100644 --- a/data/script.js +++ b/data/script.js @@ -1 +1 @@ -var ctx_el;function _(e){return document.getElementById(e)}function hidectx(){_("ctx").style.display="none",ctx_el&&ctx_el.classList.remove("selitem"),ctx_el=void 0}function doesFontExist(e){var t=document.createElement("canvas"),n=t.getContext("2d"),o="abcdefghijklmnopqrstuvwxyz0123456789";n.font="72px monospace";var a=n.measureText(o).width;return n.font="72px '"+e+"', monospace",t=null,n.measureText(o).width!=a}function createEditor(e,t,n,o,a){function i(e){let t=/(?:\.([^.]+))?$/.exec(e)[1];if(void 0!==typeof t)switch(t){case"htm":case"html":return"html";case"js":return"javascript";case"cmd":case"json":case"jsonl":return"json";case"css":case"svg":case"xml":return t}return"plain_text"}void 0===n&&(n=i(t)),void 0===a&&(a="text/"+n);["basePath","modePath","themePath"].forEach((e=>{ace.config.set(e,"https://cdnjs.cloudflare.com/ajax/libs/ace/1.34.2")}));var c=ace.edit(e,{useWorker:!1,wrap:!0,indentedSoftWrap:!1,showPrintMargin:!1,highlightGutterLine:!0,useSoftTabs:!0,tabSize:2});c.setFontSize(parseFloat(getComputedStyle(document.documentElement).fontSize)),c.setReadOnly(!0),c.getSession().setUndoManager(new ace.UndoManager),void 0===o&&(o=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"monokai":"textmate");var s=_("save"),l=_("undo"),r=_("redo"),d=_("cut"),m=_("copy"),u=_("paste"),p=_("font"),f=_("fontsize"),g="none"!==_(e).display;f.value=parseFloat(c.getFontSize()).toFixed(1),p.onchange=function(){c.setOption("fontFamily","'"+p.value+"',monospace")},f.onchange=function(){var e=parseFloat(f.value);!isNaN(e)&&e>=9&&e<=40&&c.setFontSize(e),f.value=parseFloat(c.getFontSize()).toFixed(1)};function h(){let e=!g||c.session.getSelection().isEmpty();d.disabled=e,m.disabled=e}function y(){let e=c.session.getUndoManager();s.disabled=!g||e.isClean(),l.disabled=!g||!e.hasUndo(),r.disabled=!g||!e.hasRedo()}function v(){if(void 0===t)return;const e=function(e){var t=e.getValue();try{var n=JSON.parse(t);return JSON.stringify(n)}catch(e){return t+""}}(c),n=new FormData;n.append("data",new Blob([e],{type:a}),t),fetch("/edit",{method:"POST",body:n}).then((e=>e.ok?e.text().then((e=>{console.log("Save OK /edit "+e)})):e.text().then((e=>{throw console.log("Save FAIL /edit"),new Error(e)})))).then((e=>{console.log(e),generateToast({message:"Saved "+t,background:"#ddd",color:"#000"})})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{y()}))}function x(){var e=c.getCopyText();if(window.clipboardData&&window.clipboardData.setData)return window.clipboardData.setData("Text",e);if(document.queryCommandSupported&&document.queryCommandSupported("copy")){c.focus();try{return document.execCommand("copy")}catch(t){return console.warn("Copy to clipboard failed.",t),prompt("Copy to clipboard: Ctrl+C, Enter",e)}}}function w(e){_("name").innerHTML=e;fetch(e).then((t=>t.ok?(console.log("OK "+e),t.text()):t.text().then((e=>{throw console.log("ERROR "+url),new Error(e)})))).then((e=>{try{var t=JSON.parse(e);c.setValue(JSON.stringify(t,null,4)),console.log("parse json OK")}catch(t){c.setValue(e),console.log("parse json FAIL")}null!==_("editor")&&(_("editor").style.display="block"),null!==_("preview")&&(_("preview").style.display="none"),g=!0,c.setReadOnly(!1),c.focus(),y()})).catch((e=>{console.log(e),alert(e),c.setReadOnly(!0)})).finally((()=>{c.resize(!0),c.scrollToLine(1,!0,!0,(function(){})),c.gotoLine(1,0,!0),c.clearSelection(),c.session.getUndoManager().reset()}))}return["Courier New","Monaco","Lucida Console","Monospace","ui-monospace","Roboto Mono","Inconsolata","IBM Plex Mono","Space Mono","PT Mono","Ubuntu Mono","Nanum Gothic Coding","Cousine","Fira Mono","Share Tech Mono","Courier Prime","Anonymous Pro","Cutive Mono","Overpass Mono","Fira Code","VT323","DM Mono","Oxygen Mono","Nova Mono","B612 Mono","Spline Sans Mono","Noto Sans Mono","Major Mono Display","Azeret Mono","Red Hat Mono","Syne Mono","Xanh Mono"].sort().forEach((function(e,t){if(doesFontExist(e)){var n=document.createElement("option");n.text=e,p.add(n)}})),null!==s&&null!==l&&null!==r&&c.on("input",y),c.session.selection.on("changeCursor",h),s.onclick=v,l.onclick=e=>{c.undo()&&c.focus()},r.onclick=e=>{c.redo()&&c.focus()},d.onclick=e=>{x()&&c.execCommand("cut")},m.onclick=e=>{x()&&c.execCommand("copy")},u.onclick=function(){try{navigator.clipboard.readText().then((e=>{c.execCommand("paste",e)})).catch((e=>{u.disabled=!0}))}catch{u.disabled=!0}},c.loadUrl=(e,o)=>{n=i(t=e+o),a="text/"+n,"plain"!==n&&c.getSession().setMode("ace/mode/"+n),w(e+o)},c.hide=()=>{g=!1,y(),h(),_("editor").style.display="none"},"plain"!==n&&c.getSession().setMode("ace/mode/"+n),c.setTheme("ace/theme/"+o),c.$blockScrolling=1/0,c.commands.addCommand({name:"save",bindKey:{win:"Ctrl-S",mac:"Command-S"},exec:v,readOnly:!1}),c.commands.addCommand({name:"undo",bindKey:{win:"Ctrl-Z",mac:"Command-Z"},exec:function(){c.undo()}}),c.commands.addCommand({name:"redo",bindKey:{win:"Ctrl-Y",mac:"Command-Y"},exec:function(){c.redo()}}),void 0!==t&&w(t),c.resize(),c}function uploadFileAsync(e,t,n,o,a,i){fetchData("/edit","POST",e).then((e=>{generateToast({message:"Upload "+n+"/"+o+" "+t+" done.",background:"#ddd",color:"#000"}),n==o&&listFiles(a,i)}))}function doUpload(e,t){const n=_("upload"),o=n.files.length;if(0!==o)for(let a=0;a=0}function isText(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"txt":case"cmd":case"json":case"jsonl":case"htm":case"html":case"js":case"c":case"cpp":case"css":case"svg":case"xml":return!0}return!1}function isImage(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"bmp":case"png":case"jpg":case"gif":case"svg":return!0}return!1}function isAudio(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"wav":case"mp3":case"aac":case"m4a":case"wma":return!0}return!1}function icon(e){if(isFolder(e))return"dir";if(isImage(e))return"image";if(isAudio(e))return"audio";var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"cmd":case"css":case"json":case"jsonl":case"ttf":return t;case"zip":case"gz":return"zip";case"html":case"htm":return"html"}return"file"}function preview(e,t){if(isImage(e)){let n=t+e.name;const o=_("preview");o.innerHTML='',o.style.display="block",ace.edit("editor").hide(),_("name").innerHTML=n}}function edit(e,t){isText(e)&&(ace.edit("editor").loadUrl(t,e.name),_("preview").style.display="none")}function url(e,t){console.log("click "+t+e.name),isImage(e)?preview(e,t):isText(e)&&edit(e,t)}async function fetchData(e,t,n,o){await fetch(e,{method:t,body:n}).then((n=>n.ok?(console.log(t+" OK "+e),n.text()):n.text().then((n=>{throw console.log(t+" FAIL "+e),new Error(n)})))).then((e=>{o&&o.remove(),console.log(e)})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{}))}function download(e,t){console.log("download "+t+e.name),document.getElementById("download-frame").src=t+e.name+"?download=true"}function remove(e,t,n){let o=t+e.name;isFolder(e)&&(o+="/"),console.log("remove "+o);const a=new FormData;a.append("path",o),fetchData("/edit","DELETE",a,n)}function create(e,t,n){var o=window.prompt("Create File in "+e,"");if(null==o||""==o||o.includes("/"))return;const a=new FormData;a.append("path",e+o),fetchData("/edit","PUT",a),fetch("/api/files/").then((e=>e.json())).then((o=>{t&&t.remove(),listFiles(n,e),console.log(o)}))}function upload(e,t){_("upload").onchange=()=>{doUpload(e,t)},_("upload").click()}function ctx(e,t,n,o){e.preventDefault(),ctx_el=o;let a,i=isFolder(t),c=_("ctx");c.style.display="block",a=c.getElementsByTagName("li")[0],a.onclick=i?function(){hidectx(),create(n+t.name+"/",o.children.item(1),o)}:function(){hidectx(),create(n,o.parentNode,o.parentNode.parentNode)},a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[1],i&&(a.onclick=function(){hidectx(),upload(o,n+t.name+"/")}),a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[2],a.onclick=function(){edit(t,n),hidectx()},a.style.display=isText(t)?"block":"none",a=c.getElementsByTagName("li")[3],a.onclick=function(){preview(t,n),hidectx()},a.style.display=isImage(t)?"block":"none",a=c.getElementsByTagName("li")[4],a.onclick=function(){download(t,n),hidectx()},a.style.display=i?"none":"block",a=c.getElementsByTagName("li")[5],a.onclick=function(){remove(t,n,o),hidectx()},a.style.display=n?"block":"none";var s=document.body.scrollTop?document.body.scrollTop:document.documentElement.scrollTop,l=document.body.scrollLeft?document.body.scrollLeft:document.documentElement.scrollLeft,r=e.clientX+l+10,d=e.clientY+s-20,m=(c.offsetWidth,c.offsetHeight),u=document.documentElement.clientHeight;d+m>u&&(d=u-m-20),c.style.left=r+"px",c.style.top=d+"px",o&&o.classList.add("selitem")}function drag(e,t,n){let o=n+t.name;isFolder(t)&&(o+="/"),e.dataTransfer.setData("text",o),console.log("drag start "+o)}function drop(e,t){let n=e.dataTransfer.getData("text");n.startsWith(t)||(e.preventDefault(),console.log("Move "+n+" to "+t))}function listFiles(e,t){return console.log("listFiles"),fetch("/api/files/?dir="+t).then((e=>e.json())).then((n=>{if(0==n.length)return!1;let o=e.getElementsByTagName("div")[0];o&&(o.onclick=n=>{i.remove(),o.onclick=()=>{listFiles(e,t)},n.stopPropagation()});let a=e.getElementsByTagName("ul");for(let e=0;e{drag(event,e,t)},a.appendChild(s),s.innerHTML=''+o+"",isFolder(e)){let n=t+e.name+"/";s.classList.add("bold"),s.onclick=function(e){listFiles(a,n)},s.ondragover=e=>{e.preventDefault()},s.ondrop=e=>{drop(e,n)}}else(isText(e)||isImage(e)||isAudio(e))&&(s.onclick=function(n){url(e,t)});s.oncontextmenu=n=>{ctx(n,e,t,a)}}return e.scrollIntoView(),!0}))}function generateToast({message:e,background:t="#00214d",color:n="#fffffe",length:o="7000ms"}){_("toast").insertAdjacentHTML("afterbegin",`

\n ${e}\n

`);const a=_("toast").firstElementChild;a.addEventListener("animationend",(()=>a.remove()))}document.addEventListener("blur",(function(){hidectx()})),document.addEventListener("DOMContentLoaded",(function(){createEditor("editor",void 0,void 0,void 0);listFiles(_("tree"),"/"),_("tree").getElementsByTagName("div")[0].oncontextmenu=e=>{ctx(e,{name:"",children:[]},"",_("tree"))},_("load").onclick=function(e){const t=new FormData;t.append("load",""),fetchData("/edit","PUT",t)},_("init").onclick=function(e){const t=new FormData;t.append("init",""),fetchData("/edit","PUT",t)},_("home").onclick=function(e){window.location.href="/"},_("page").onchange=function(e){const t=new FormData;t.append("page",_("page").value),fetchData("/edit","PUT",t)}})),document.addEventListener("DOMContentLoaded",(function(){const e=document.getElementById("dragMe"),t=e.previousElementSibling,n=e.nextElementSibling;let o=0,a=0,i=0;const c=function(a){const c=a.clientX-o,s=(a.clientY,100*(i+c)/e.parentNode.getBoundingClientRect().width);t.style.width=`${s}%`,t.style.right=t.style.width,e.style.cursor="col-resize",document.body.style.cursor="col-resize",t.style.userSelect="none",t.style.pointerEvents="none",n.style.userSelect="none",n.style.pointerEvents="none",ace.edit("editor").resize()},s=function(){e.style.removeProperty("cursor"),document.body.style.removeProperty("cursor"),t.style.removeProperty("user-select"),t.style.removeProperty("pointer-events"),n.style.removeProperty("user-select"),n.style.removeProperty("pointer-events"),document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",s)};e.addEventListener("mousedown",(function(e){o=e.clientX,a=e.clientY,i=t.getBoundingClientRect().width,document.addEventListener("mousemove",c),document.addEventListener("mouseup",s)})),e.addEventListener("dblclick",(()=>{var e=t.style.visibility="hidden"===t.style.visibility;t.style.visibility=e?"unset":"hidden",t.style.position=e?"unset":"absolute",ace.edit("editor").resize()}))})); \ No newline at end of file +var ctx_el;function _(e){return document.getElementById(e)}function hidectx(){_("ctx").style.display="none",ctx_el&&ctx_el.classList.remove("selitem"),ctx_el=void 0}function doesFontExist(e){var t=document.createElement("canvas"),n=t.getContext("2d"),o="abcdefghijklmnopqrstuvwxyz0123456789";n.font="72px monospace";var a=n.measureText(o).width;return n.font="72px '"+e+"', monospace",t=null,n.measureText(o).width!=a}function createEditor(e,t,n,o,a){function i(e){let t=/(?:\.([^.]+))?$/.exec(e)[1];if(void 0!==typeof t)switch(t){case"htm":case"html":return"html";case"js":return"javascript";case"cmd":case"json":case"jsonl":return"json";case"css":case"svg":case"xml":return t}return"plain_text"}void 0===n&&(n=i(t)),void 0===a&&(a="text/"+n);["basePath","modePath","themePath"].forEach((e=>{ace.config.set(e,"https://cdnjs.cloudflare.com/ajax/libs/ace/1.35.3")}));var c=ace.edit(e,{useWorker:!1,wrap:!0,indentedSoftWrap:!1,showPrintMargin:!1,highlightGutterLine:!0,useSoftTabs:!0,tabSize:2});c.setFontSize(parseFloat(getComputedStyle(document.documentElement).fontSize)),c.setReadOnly(!0),c.getSession().setUndoManager(new ace.UndoManager),void 0===o&&(o=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"monokai":"textmate");var s=_("save"),l=_("undo"),r=_("redo"),d=_("cut"),m=_("copy"),u=_("paste"),p=_("font"),f=_("fontsize"),g="none"!==_(e).display;f.value=parseFloat(c.getFontSize()).toFixed(1),p.onchange=function(){c.setOption("fontFamily","'"+p.value+"',monospace")},f.onchange=function(){var e=parseFloat(f.value);!isNaN(e)&&e>=9&&e<=40&&c.setFontSize(e),f.value=parseFloat(c.getFontSize()).toFixed(1)};function h(){let e=!g||c.session.getSelection().isEmpty();d.disabled=e,m.disabled=e}function y(){let e=c.session.getUndoManager();s.disabled=!g||e.isClean(),l.disabled=!g||!e.hasUndo(),r.disabled=!g||!e.hasRedo()}function v(){if(void 0===t)return;const e=function(e){var t=e.getValue();try{var n=JSON.parse(t);return JSON.stringify(n)}catch(e){return t+""}}(c),n=new FormData;n.append("data",new Blob([e],{type:a}),t),fetch("/edit",{method:"POST",body:n}).then((e=>e.ok?e.text().then((e=>{console.log("Save OK /edit "+e)})):e.text().then((e=>{throw console.log("Save FAIL /edit"),new Error(e)})))).then((e=>{console.log(e),generateToast({message:"Saved "+t,background:"#ddd",color:"#000"})})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{y()}))}function x(){var e=c.getCopyText();if(window.clipboardData&&window.clipboardData.setData)return window.clipboardData.setData("Text",e);if(document.queryCommandSupported&&document.queryCommandSupported("copy")){c.focus();try{return document.execCommand("copy")}catch(t){return console.warn("Copy to clipboard failed.",t),prompt("Copy to clipboard: Ctrl+C, Enter",e)}}}function w(e){_("name").innerHTML=e;fetch(e).then((t=>t.ok?(console.log("OK "+e),t.text()):t.text().then((e=>{throw console.log("ERROR "+url),new Error(e)})))).then((e=>{try{var t=JSON.parse(e);c.setValue(JSON.stringify(t,null,4)),console.log("parse json OK")}catch(t){c.setValue(e),console.log("parse json FAIL")}null!==_("editor")&&(_("editor").style.display="block"),null!==_("preview")&&(_("preview").style.display="none"),g=!0,c.setReadOnly(!1),c.focus(),y()})).catch((e=>{console.log(e),alert(e),c.setReadOnly(!0)})).finally((()=>{c.resize(!0),c.scrollToLine(1,!0,!0,(function(){})),c.gotoLine(1,0,!0),c.clearSelection(),c.session.getUndoManager().reset()}))}return["Courier New","Monaco","Lucida Console","Monospace","ui-monospace","Roboto Mono","Inconsolata","IBM Plex Mono","Space Mono","PT Mono","Ubuntu Mono","Nanum Gothic Coding","Cousine","Fira Mono","Share Tech Mono","Courier Prime","Anonymous Pro","Cutive Mono","Overpass Mono","Fira Code","VT323","DM Mono","Oxygen Mono","Nova Mono","B612 Mono","Spline Sans Mono","Noto Sans Mono","Major Mono Display","Azeret Mono","Red Hat Mono","Syne Mono","Xanh Mono"].sort().forEach((function(e,t){if(doesFontExist(e)){var n=document.createElement("option");n.text=e,p.add(n)}})),null!==s&&null!==l&&null!==r&&c.on("input",y),c.session.selection.on("changeCursor",h),s.onclick=v,l.onclick=e=>{c.undo()&&c.focus()},r.onclick=e=>{c.redo()&&c.focus()},d.onclick=e=>{x()&&c.execCommand("cut")},m.onclick=e=>{x()&&c.execCommand("copy")},u.onclick=function(){try{navigator.clipboard.readText().then((e=>{c.execCommand("paste",e)})).catch((e=>{u.disabled=!0}))}catch{u.disabled=!0}},c.loadUrl=(e,o)=>{n=i(t=e+o),a="text/"+n,"plain"!==n&&c.getSession().setMode("ace/mode/"+n),w(e+o)},c.hide=()=>{g=!1,y(),h(),_("editor").style.display="none"},"plain"!==n&&c.getSession().setMode("ace/mode/"+n),c.setTheme("ace/theme/"+o),c.$blockScrolling=1/0,c.commands.addCommand({name:"save",bindKey:{win:"Ctrl-S",mac:"Command-S"},exec:v,readOnly:!1}),c.commands.addCommand({name:"undo",bindKey:{win:"Ctrl-Z",mac:"Command-Z"},exec:function(){c.undo()}}),c.commands.addCommand({name:"redo",bindKey:{win:"Ctrl-Y",mac:"Command-Y"},exec:function(){c.redo()}}),void 0!==t&&w(t),c.resize(),c}function uploadFileAsync(e,t,n,o,a,i){fetchData("/edit","POST",e).then((e=>{generateToast({message:"Upload "+n+"/"+o+" "+t+" done.",background:"#ddd",color:"#000"}),n==o&&listFiles(a,i)}))}function doUpload(e,t){const n=_("upload"),o=n.files.length;if(0!==o)for(let a=0;a=0}function isText(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"txt":case"cmd":case"json":case"jsonl":case"htm":case"html":case"js":case"c":case"cpp":case"css":case"svg":case"xml":return!0}return!1}function isImage(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"bmp":case"png":case"jpg":case"gif":case"svg":return!0}return!1}function isAudio(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"wav":case"mp3":case"aac":case"m4a":case"wma":return!0}return!1}function icon(e){if(isFolder(e))return"dir";if(isImage(e))return"image";if(isAudio(e))return"audio";var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"cmd":case"css":case"json":case"jsonl":case"ttf":return t;case"zip":case"gz":return"zip";case"html":case"htm":return"html"}return"file"}function preview(e,t){if(isImage(e)){let n=t+e.name;const o=_("preview");o.innerHTML='',o.style.display="block",ace.edit("editor").hide(),_("name").innerHTML=n}}function edit(e,t){isText(e)&&(ace.edit("editor").loadUrl(t,e.name),_("preview").style.display="none")}function url(e,t){console.log("click "+t+e.name),isImage(e)?preview(e,t):isText(e)&&edit(e,t)}async function fetchData(e,t,n,o){await fetch(e,{method:t,body:n}).then((n=>n.ok?(console.log(t+" OK "+e),n.text()):n.text().then((n=>{throw console.log(t+" FAIL "+e),new Error(n)})))).then((e=>{o&&o.remove(),console.log(e)})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{}))}function download(e,t){console.log("download "+t+e.name),document.getElementById("download-frame").src=t+e.name+"?download=true"}function remove(e,t,n){let o=t+e.name;isFolder(e)&&(o+="/"),console.log("remove "+o);const a=new FormData;a.append("path",o),fetchData("/edit","DELETE",a,n)}function create(e,t,n){var o=window.prompt("Create File in "+e,"");if(null==o||""==o||o.includes("/"))return;const a=new FormData;a.append("path",e+o),fetchData("/edit","PUT",a),fetch("/api/files/").then((e=>e.json())).then((o=>{t&&t.remove(),listFiles(n,e),console.log(o)}))}function upload(e,t){_("upload").onchange=()=>{doUpload(e,t)},_("upload").click()}function ctx(e,t,n,o){e.preventDefault(),ctx_el=o;let a,i=isFolder(t),c=_("ctx");c.style.display="block",a=c.getElementsByTagName("li")[0],a.onclick=i?function(){hidectx(),create(n+t.name+"/",o.children.item(1),o)}:function(){hidectx(),create(n,o.parentNode,o.parentNode.parentNode)},a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[1],i&&(a.onclick=function(){hidectx(),upload(o,n+t.name+"/")}),a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[2],a.onclick=function(){edit(t,n),hidectx()},a.style.display=isText(t)?"block":"none",a=c.getElementsByTagName("li")[3],a.onclick=function(){preview(t,n),hidectx()},a.style.display=isImage(t)?"block":"none",a=c.getElementsByTagName("li")[4],a.onclick=function(){download(t,n),hidectx()},a.style.display=i?"none":"block",a=c.getElementsByTagName("li")[5],a.onclick=function(){remove(t,n,o),hidectx()},a.style.display=n?"block":"none";var s=document.body.scrollTop?document.body.scrollTop:document.documentElement.scrollTop,l=document.body.scrollLeft?document.body.scrollLeft:document.documentElement.scrollLeft,r=e.clientX+l+10,d=e.clientY+s-20,m=(c.offsetWidth,c.offsetHeight),u=document.documentElement.clientHeight;d+m>u&&(d=u-m-20),c.style.left=r+"px",c.style.top=d+"px",o&&o.classList.add("selitem")}function drag(e,t,n){let o=n+t.name;isFolder(t)&&(o+="/"),e.dataTransfer.setData("text",o),console.log("drag start "+o)}function drop(e,t){let n=e.dataTransfer.getData("text");n.startsWith(t)||(e.preventDefault(),console.log("Move "+n+" to "+t))}function listFiles(e,t){return console.log("listFiles"),fetch("/api/files/?dir="+t).then((e=>e.json())).then((n=>{if(0==n.length)return!1;let o=e.getElementsByTagName("div")[0];o&&(o.onclick=n=>{i.remove(),o.onclick=()=>{listFiles(e,t)},n.stopPropagation()});let a=e.getElementsByTagName("ul");for(let e=0;e{drag(event,e,t)},a.appendChild(s),s.innerHTML=''+o+"",isFolder(e)){let n=t+e.name+"/";s.classList.add("bold"),s.onclick=function(e){listFiles(a,n)},s.ondragover=e=>{e.preventDefault()},s.ondrop=e=>{drop(e,n)}}else(isText(e)||isImage(e)||isAudio(e))&&(s.onclick=function(n){url(e,t)});s.oncontextmenu=n=>{ctx(n,e,t,a)}}return e.scrollIntoView(),!0}))}function generateToast({message:e,background:t="#00214d",color:n="#fffffe",length:o="7000ms"}){_("toast").insertAdjacentHTML("afterbegin",`

\n ${e}\n

`);const a=_("toast").firstElementChild;a.addEventListener("animationend",(()=>a.remove()))}document.addEventListener("blur",(function(){hidectx()})),document.addEventListener("DOMContentLoaded",(function(){createEditor("editor",void 0,void 0,void 0);listFiles(_("tree"),"/"),_("tree").getElementsByTagName("div")[0].oncontextmenu=e=>{ctx(e,{name:"",children:[]},"",_("tree"))},_("load").onclick=function(e){const t=new FormData;t.append("load",""),fetchData("/edit","PUT",t)},_("init").onclick=function(e){const t=new FormData;t.append("init",""),fetchData("/edit","PUT",t)},_("home").onclick=function(e){window.location.href="/"},_("page").onchange=function(e){const t=new FormData;t.append("page",_("page").value),fetchData("/edit","PUT",t)}})),document.addEventListener("DOMContentLoaded",(function(){const e=document.getElementById("dragMe"),t=e.previousElementSibling,n=e.nextElementSibling;let o=0,a=0,i=0;const c=function(a){const c=a.clientX-o,s=(a.clientY,100*(i+c)/e.parentNode.getBoundingClientRect().width);t.style.width=`${s}%`,t.style.right=t.style.width,e.style.cursor="col-resize",document.body.style.cursor="col-resize",t.style.userSelect="none",t.style.pointerEvents="none",n.style.userSelect="none",n.style.pointerEvents="none",ace.edit("editor").resize()},s=function(){e.style.removeProperty("cursor"),document.body.style.removeProperty("cursor"),t.style.removeProperty("user-select"),t.style.removeProperty("pointer-events"),n.style.removeProperty("user-select"),n.style.removeProperty("pointer-events"),document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",s)};e.addEventListener("mousedown",(function(e){o=e.clientX,a=e.clientY,i=t.getBoundingClientRect().width,document.addEventListener("mousemove",c),document.addEventListener("mouseup",s)})),e.addEventListener("dblclick",(()=>{var e=t.style.visibility="hidden"===t.style.visibility;t.style.visibility=e?"unset":"hidden",t.style.position=e?"unset":"absolute",ace.edit("editor").resize()}))})); \ No newline at end of file From 89ef57346a8f8aa51df4b243f8cba9f224cda2a4 Mon Sep 17 00:00:00 2001 From: FreeBear Date: Fri, 19 Jul 2024 15:20:11 +0100 Subject: [PATCH 51/55] TFT_G5 was missing from the list of used GPIO pins. Add the USB TX/RX pins to the list for the Guition ESP32-S3 4848S040 board. --- src/drv/tft/tft_driver_arduinogfx.cpp | 9 +++++++++ user_setups/esp32s3/esp32-s3-4848S040.ini | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/src/drv/tft/tft_driver_arduinogfx.cpp b/src/drv/tft/tft_driver_arduinogfx.cpp index 4bc12004..a1cc3c89 100644 --- a/src/drv/tft/tft_driver_arduinogfx.cpp +++ b/src/drv/tft/tft_driver_arduinogfx.cpp @@ -335,6 +335,9 @@ bool ArduinoGfx::is_driver_pin(uint8_t pin) #ifdef TFT_G4 || (pin == TFT_G4) #endif +#ifdef TFT_G5 + || (pin == TFT_G5) +#endif #ifdef TFT_B0 || (pin == TFT_B0) #endif @@ -361,6 +364,12 @@ bool ArduinoGfx::is_driver_pin(uint8_t pin) #endif #ifdef TOUCH_IRQ || (pin == TOUCH_IRQ) +#endif +#ifdef USB_TXD + || (pin == USB_TXD) +#endif +#ifdef USB_RXD + || (pin == USB_RXD) #endif ) { return true; diff --git a/user_setups/esp32s3/esp32-s3-4848S040.ini b/user_setups/esp32s3/esp32-s3-4848S040.ini index 95c800ac..27d89050 100644 --- a/user_setups/esp32s3/esp32-s3-4848S040.ini +++ b/user_setups/esp32s3/esp32-s3-4848S040.ini @@ -76,6 +76,10 @@ build_flags = -D I2C_TOUCH_FREQUENCY=400000 -D I2C_TOUCH_ADDRESS=0x5D ; or 0x14 -D I2C_TOUCH_PORT=1 + ; USB GPIO - Only need to define these so that the pins do not + ; show up in the list of available GPIO + -D USB_TXD=43 + -D USB_RXD=44 ;endregion lib_deps = From 0b30b075fa806b13ceeff7058654d41745e7685c Mon Sep 17 00:00:00 2001 From: FreeBear Date: Fri, 19 Jul 2024 16:15:45 +0100 Subject: [PATCH 52/55] Move USB_TXD/RXD to is_system_pin() --- src/drv/tft/tft_driver_arduinogfx.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/drv/tft/tft_driver_arduinogfx.cpp b/src/drv/tft/tft_driver_arduinogfx.cpp index a1cc3c89..ae73d504 100644 --- a/src/drv/tft/tft_driver_arduinogfx.cpp +++ b/src/drv/tft/tft_driver_arduinogfx.cpp @@ -364,12 +364,6 @@ bool ArduinoGfx::is_driver_pin(uint8_t pin) #endif #ifdef TOUCH_IRQ || (pin == TOUCH_IRQ) -#endif -#ifdef USB_TXD - || (pin == USB_TXD) -#endif -#ifdef USB_RXD - || (pin == USB_RXD) #endif ) { return true; From 734f11d3d8596d43d889fc60958346067ac5c385 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Mon, 22 Jul 2024 16:44:12 +0200 Subject: [PATCH 53/55] Update ace?js to v1.35.4 --- data/edit.htm | 2 +- data/script.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/edit.htm b/data/edit.htm index 1a112286..c0a35dc2 100644 --- a/data/edit.htm +++ b/data/edit.htm @@ -1 +1 @@ -openHASP File Editor
L:
  • New File
  • Upload Files
  • Edit
  • Preview
  • Download
  • Delete
\ No newline at end of file +openHASP File Editor
L:
  • New File
  • Upload Files
  • Edit
  • Preview
  • Download
  • Delete
\ No newline at end of file diff --git a/data/script.js b/data/script.js index 93a1d96d..afd735c2 100644 --- a/data/script.js +++ b/data/script.js @@ -1 +1 @@ -var ctx_el;function _(e){return document.getElementById(e)}function hidectx(){_("ctx").style.display="none",ctx_el&&ctx_el.classList.remove("selitem"),ctx_el=void 0}function doesFontExist(e){var t=document.createElement("canvas"),n=t.getContext("2d"),o="abcdefghijklmnopqrstuvwxyz0123456789";n.font="72px monospace";var a=n.measureText(o).width;return n.font="72px '"+e+"', monospace",t=null,n.measureText(o).width!=a}function createEditor(e,t,n,o,a){function i(e){let t=/(?:\.([^.]+))?$/.exec(e)[1];if(void 0!==typeof t)switch(t){case"htm":case"html":return"html";case"js":return"javascript";case"cmd":case"json":case"jsonl":return"json";case"css":case"svg":case"xml":return t}return"plain_text"}void 0===n&&(n=i(t)),void 0===a&&(a="text/"+n);["basePath","modePath","themePath"].forEach((e=>{ace.config.set(e,"https://cdnjs.cloudflare.com/ajax/libs/ace/1.35.3")}));var c=ace.edit(e,{useWorker:!1,wrap:!0,indentedSoftWrap:!1,showPrintMargin:!1,highlightGutterLine:!0,useSoftTabs:!0,tabSize:2});c.setFontSize(parseFloat(getComputedStyle(document.documentElement).fontSize)),c.setReadOnly(!0),c.getSession().setUndoManager(new ace.UndoManager),void 0===o&&(o=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"monokai":"textmate");var s=_("save"),l=_("undo"),r=_("redo"),d=_("cut"),m=_("copy"),u=_("paste"),p=_("font"),f=_("fontsize"),g="none"!==_(e).display;f.value=parseFloat(c.getFontSize()).toFixed(1),p.onchange=function(){c.setOption("fontFamily","'"+p.value+"',monospace")},f.onchange=function(){var e=parseFloat(f.value);!isNaN(e)&&e>=9&&e<=40&&c.setFontSize(e),f.value=parseFloat(c.getFontSize()).toFixed(1)};function h(){let e=!g||c.session.getSelection().isEmpty();d.disabled=e,m.disabled=e}function y(){let e=c.session.getUndoManager();s.disabled=!g||e.isClean(),l.disabled=!g||!e.hasUndo(),r.disabled=!g||!e.hasRedo()}function v(){if(void 0===t)return;const e=function(e){var t=e.getValue();try{var n=JSON.parse(t);return JSON.stringify(n)}catch(e){return t+""}}(c),n=new FormData;n.append("data",new Blob([e],{type:a}),t),fetch("/edit",{method:"POST",body:n}).then((e=>e.ok?e.text().then((e=>{console.log("Save OK /edit "+e)})):e.text().then((e=>{throw console.log("Save FAIL /edit"),new Error(e)})))).then((e=>{console.log(e),generateToast({message:"Saved "+t,background:"#ddd",color:"#000"})})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{y()}))}function x(){var e=c.getCopyText();if(window.clipboardData&&window.clipboardData.setData)return window.clipboardData.setData("Text",e);if(document.queryCommandSupported&&document.queryCommandSupported("copy")){c.focus();try{return document.execCommand("copy")}catch(t){return console.warn("Copy to clipboard failed.",t),prompt("Copy to clipboard: Ctrl+C, Enter",e)}}}function w(e){_("name").innerHTML=e;fetch(e).then((t=>t.ok?(console.log("OK "+e),t.text()):t.text().then((e=>{throw console.log("ERROR "+url),new Error(e)})))).then((e=>{try{var t=JSON.parse(e);c.setValue(JSON.stringify(t,null,4)),console.log("parse json OK")}catch(t){c.setValue(e),console.log("parse json FAIL")}null!==_("editor")&&(_("editor").style.display="block"),null!==_("preview")&&(_("preview").style.display="none"),g=!0,c.setReadOnly(!1),c.focus(),y()})).catch((e=>{console.log(e),alert(e),c.setReadOnly(!0)})).finally((()=>{c.resize(!0),c.scrollToLine(1,!0,!0,(function(){})),c.gotoLine(1,0,!0),c.clearSelection(),c.session.getUndoManager().reset()}))}return["Courier New","Monaco","Lucida Console","Monospace","ui-monospace","Roboto Mono","Inconsolata","IBM Plex Mono","Space Mono","PT Mono","Ubuntu Mono","Nanum Gothic Coding","Cousine","Fira Mono","Share Tech Mono","Courier Prime","Anonymous Pro","Cutive Mono","Overpass Mono","Fira Code","VT323","DM Mono","Oxygen Mono","Nova Mono","B612 Mono","Spline Sans Mono","Noto Sans Mono","Major Mono Display","Azeret Mono","Red Hat Mono","Syne Mono","Xanh Mono"].sort().forEach((function(e,t){if(doesFontExist(e)){var n=document.createElement("option");n.text=e,p.add(n)}})),null!==s&&null!==l&&null!==r&&c.on("input",y),c.session.selection.on("changeCursor",h),s.onclick=v,l.onclick=e=>{c.undo()&&c.focus()},r.onclick=e=>{c.redo()&&c.focus()},d.onclick=e=>{x()&&c.execCommand("cut")},m.onclick=e=>{x()&&c.execCommand("copy")},u.onclick=function(){try{navigator.clipboard.readText().then((e=>{c.execCommand("paste",e)})).catch((e=>{u.disabled=!0}))}catch{u.disabled=!0}},c.loadUrl=(e,o)=>{n=i(t=e+o),a="text/"+n,"plain"!==n&&c.getSession().setMode("ace/mode/"+n),w(e+o)},c.hide=()=>{g=!1,y(),h(),_("editor").style.display="none"},"plain"!==n&&c.getSession().setMode("ace/mode/"+n),c.setTheme("ace/theme/"+o),c.$blockScrolling=1/0,c.commands.addCommand({name:"save",bindKey:{win:"Ctrl-S",mac:"Command-S"},exec:v,readOnly:!1}),c.commands.addCommand({name:"undo",bindKey:{win:"Ctrl-Z",mac:"Command-Z"},exec:function(){c.undo()}}),c.commands.addCommand({name:"redo",bindKey:{win:"Ctrl-Y",mac:"Command-Y"},exec:function(){c.redo()}}),void 0!==t&&w(t),c.resize(),c}function uploadFileAsync(e,t,n,o,a,i){fetchData("/edit","POST",e).then((e=>{generateToast({message:"Upload "+n+"/"+o+" "+t+" done.",background:"#ddd",color:"#000"}),n==o&&listFiles(a,i)}))}function doUpload(e,t){const n=_("upload"),o=n.files.length;if(0!==o)for(let a=0;a=0}function isText(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"txt":case"cmd":case"json":case"jsonl":case"htm":case"html":case"js":case"c":case"cpp":case"css":case"svg":case"xml":return!0}return!1}function isImage(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"bmp":case"png":case"jpg":case"gif":case"svg":return!0}return!1}function isAudio(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"wav":case"mp3":case"aac":case"m4a":case"wma":return!0}return!1}function icon(e){if(isFolder(e))return"dir";if(isImage(e))return"image";if(isAudio(e))return"audio";var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"cmd":case"css":case"json":case"jsonl":case"ttf":return t;case"zip":case"gz":return"zip";case"html":case"htm":return"html"}return"file"}function preview(e,t){if(isImage(e)){let n=t+e.name;const o=_("preview");o.innerHTML='',o.style.display="block",ace.edit("editor").hide(),_("name").innerHTML=n}}function edit(e,t){isText(e)&&(ace.edit("editor").loadUrl(t,e.name),_("preview").style.display="none")}function url(e,t){console.log("click "+t+e.name),isImage(e)?preview(e,t):isText(e)&&edit(e,t)}async function fetchData(e,t,n,o){await fetch(e,{method:t,body:n}).then((n=>n.ok?(console.log(t+" OK "+e),n.text()):n.text().then((n=>{throw console.log(t+" FAIL "+e),new Error(n)})))).then((e=>{o&&o.remove(),console.log(e)})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{}))}function download(e,t){console.log("download "+t+e.name),document.getElementById("download-frame").src=t+e.name+"?download=true"}function remove(e,t,n){let o=t+e.name;isFolder(e)&&(o+="/"),console.log("remove "+o);const a=new FormData;a.append("path",o),fetchData("/edit","DELETE",a,n)}function create(e,t,n){var o=window.prompt("Create File in "+e,"");if(null==o||""==o||o.includes("/"))return;const a=new FormData;a.append("path",e+o),fetchData("/edit","PUT",a),fetch("/api/files/").then((e=>e.json())).then((o=>{t&&t.remove(),listFiles(n,e),console.log(o)}))}function upload(e,t){_("upload").onchange=()=>{doUpload(e,t)},_("upload").click()}function ctx(e,t,n,o){e.preventDefault(),ctx_el=o;let a,i=isFolder(t),c=_("ctx");c.style.display="block",a=c.getElementsByTagName("li")[0],a.onclick=i?function(){hidectx(),create(n+t.name+"/",o.children.item(1),o)}:function(){hidectx(),create(n,o.parentNode,o.parentNode.parentNode)},a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[1],i&&(a.onclick=function(){hidectx(),upload(o,n+t.name+"/")}),a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[2],a.onclick=function(){edit(t,n),hidectx()},a.style.display=isText(t)?"block":"none",a=c.getElementsByTagName("li")[3],a.onclick=function(){preview(t,n),hidectx()},a.style.display=isImage(t)?"block":"none",a=c.getElementsByTagName("li")[4],a.onclick=function(){download(t,n),hidectx()},a.style.display=i?"none":"block",a=c.getElementsByTagName("li")[5],a.onclick=function(){remove(t,n,o),hidectx()},a.style.display=n?"block":"none";var s=document.body.scrollTop?document.body.scrollTop:document.documentElement.scrollTop,l=document.body.scrollLeft?document.body.scrollLeft:document.documentElement.scrollLeft,r=e.clientX+l+10,d=e.clientY+s-20,m=(c.offsetWidth,c.offsetHeight),u=document.documentElement.clientHeight;d+m>u&&(d=u-m-20),c.style.left=r+"px",c.style.top=d+"px",o&&o.classList.add("selitem")}function drag(e,t,n){let o=n+t.name;isFolder(t)&&(o+="/"),e.dataTransfer.setData("text",o),console.log("drag start "+o)}function drop(e,t){let n=e.dataTransfer.getData("text");n.startsWith(t)||(e.preventDefault(),console.log("Move "+n+" to "+t))}function listFiles(e,t){return console.log("listFiles"),fetch("/api/files/?dir="+t).then((e=>e.json())).then((n=>{if(0==n.length)return!1;let o=e.getElementsByTagName("div")[0];o&&(o.onclick=n=>{i.remove(),o.onclick=()=>{listFiles(e,t)},n.stopPropagation()});let a=e.getElementsByTagName("ul");for(let e=0;e{drag(event,e,t)},a.appendChild(s),s.innerHTML=''+o+"",isFolder(e)){let n=t+e.name+"/";s.classList.add("bold"),s.onclick=function(e){listFiles(a,n)},s.ondragover=e=>{e.preventDefault()},s.ondrop=e=>{drop(e,n)}}else(isText(e)||isImage(e)||isAudio(e))&&(s.onclick=function(n){url(e,t)});s.oncontextmenu=n=>{ctx(n,e,t,a)}}return e.scrollIntoView(),!0}))}function generateToast({message:e,background:t="#00214d",color:n="#fffffe",length:o="7000ms"}){_("toast").insertAdjacentHTML("afterbegin",`

\n ${e}\n

`);const a=_("toast").firstElementChild;a.addEventListener("animationend",(()=>a.remove()))}document.addEventListener("blur",(function(){hidectx()})),document.addEventListener("DOMContentLoaded",(function(){createEditor("editor",void 0,void 0,void 0);listFiles(_("tree"),"/"),_("tree").getElementsByTagName("div")[0].oncontextmenu=e=>{ctx(e,{name:"",children:[]},"",_("tree"))},_("load").onclick=function(e){const t=new FormData;t.append("load",""),fetchData("/edit","PUT",t)},_("init").onclick=function(e){const t=new FormData;t.append("init",""),fetchData("/edit","PUT",t)},_("home").onclick=function(e){window.location.href="/"},_("page").onchange=function(e){const t=new FormData;t.append("page",_("page").value),fetchData("/edit","PUT",t)}})),document.addEventListener("DOMContentLoaded",(function(){const e=document.getElementById("dragMe"),t=e.previousElementSibling,n=e.nextElementSibling;let o=0,a=0,i=0;const c=function(a){const c=a.clientX-o,s=(a.clientY,100*(i+c)/e.parentNode.getBoundingClientRect().width);t.style.width=`${s}%`,t.style.right=t.style.width,e.style.cursor="col-resize",document.body.style.cursor="col-resize",t.style.userSelect="none",t.style.pointerEvents="none",n.style.userSelect="none",n.style.pointerEvents="none",ace.edit("editor").resize()},s=function(){e.style.removeProperty("cursor"),document.body.style.removeProperty("cursor"),t.style.removeProperty("user-select"),t.style.removeProperty("pointer-events"),n.style.removeProperty("user-select"),n.style.removeProperty("pointer-events"),document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",s)};e.addEventListener("mousedown",(function(e){o=e.clientX,a=e.clientY,i=t.getBoundingClientRect().width,document.addEventListener("mousemove",c),document.addEventListener("mouseup",s)})),e.addEventListener("dblclick",(()=>{var e=t.style.visibility="hidden"===t.style.visibility;t.style.visibility=e?"unset":"hidden",t.style.position=e?"unset":"absolute",ace.edit("editor").resize()}))})); \ No newline at end of file +var ctx_el;function _(e){return document.getElementById(e)}function hidectx(){_("ctx").style.display="none",ctx_el&&ctx_el.classList.remove("selitem"),ctx_el=void 0}function doesFontExist(e){var t=document.createElement("canvas"),n=t.getContext("2d"),o="abcdefghijklmnopqrstuvwxyz0123456789";n.font="72px monospace";var a=n.measureText(o).width;return n.font="72px '"+e+"', monospace",t=null,n.measureText(o).width!=a}function createEditor(e,t,n,o,a){function i(e){let t=/(?:\.([^.]+))?$/.exec(e)[1];if(void 0!==typeof t)switch(t){case"htm":case"html":return"html";case"js":return"javascript";case"cmd":case"json":case"jsonl":return"json";case"css":case"svg":case"xml":return t}return"plain_text"}void 0===n&&(n=i(t)),void 0===a&&(a="text/"+n);["basePath","modePath","themePath"].forEach((e=>{ace.config.set(e,"https://cdnjs.cloudflare.com/ajax/libs/ace/1.35.4")}));var c=ace.edit(e,{useWorker:!1,wrap:!0,indentedSoftWrap:!1,showPrintMargin:!1,highlightGutterLine:!0,useSoftTabs:!0,tabSize:2});c.setFontSize(parseFloat(getComputedStyle(document.documentElement).fontSize)),c.setReadOnly(!0),c.getSession().setUndoManager(new ace.UndoManager),void 0===o&&(o=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"monokai":"textmate");var s=_("save"),l=_("undo"),r=_("redo"),d=_("cut"),m=_("copy"),u=_("paste"),p=_("font"),f=_("fontsize"),g="none"!==_(e).display;f.value=parseFloat(c.getFontSize()).toFixed(1),p.onchange=function(){c.setOption("fontFamily","'"+p.value+"',monospace")},f.onchange=function(){var e=parseFloat(f.value);!isNaN(e)&&e>=9&&e<=40&&c.setFontSize(e),f.value=parseFloat(c.getFontSize()).toFixed(1)};function h(){let e=!g||c.session.getSelection().isEmpty();d.disabled=e,m.disabled=e}function y(){let e=c.session.getUndoManager();s.disabled=!g||e.isClean(),l.disabled=!g||!e.hasUndo(),r.disabled=!g||!e.hasRedo()}function v(){if(void 0===t)return;const e=function(e){var t=e.getValue();try{var n=JSON.parse(t);return JSON.stringify(n)}catch(e){return t+""}}(c),n=new FormData;n.append("data",new Blob([e],{type:a}),t),fetch("/edit",{method:"POST",body:n}).then((e=>e.ok?e.text().then((e=>{console.log("Save OK /edit "+e)})):e.text().then((e=>{throw console.log("Save FAIL /edit"),new Error(e)})))).then((e=>{console.log(e),generateToast({message:"Saved "+t,background:"#ddd",color:"#000"})})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{y()}))}function x(){var e=c.getCopyText();if(window.clipboardData&&window.clipboardData.setData)return window.clipboardData.setData("Text",e);if(document.queryCommandSupported&&document.queryCommandSupported("copy")){c.focus();try{return document.execCommand("copy")}catch(t){return console.warn("Copy to clipboard failed.",t),prompt("Copy to clipboard: Ctrl+C, Enter",e)}}}function w(e){_("name").innerHTML=e;fetch(e).then((t=>t.ok?(console.log("OK "+e),t.text()):t.text().then((e=>{throw console.log("ERROR "+url),new Error(e)})))).then((e=>{try{var t=JSON.parse(e);c.setValue(JSON.stringify(t,null,4)),console.log("parse json OK")}catch(t){c.setValue(e),console.log("parse json FAIL")}null!==_("editor")&&(_("editor").style.display="block"),null!==_("preview")&&(_("preview").style.display="none"),g=!0,c.setReadOnly(!1),c.focus(),y()})).catch((e=>{console.log(e),alert(e),c.setReadOnly(!0)})).finally((()=>{c.resize(!0),c.scrollToLine(1,!0,!0,(function(){})),c.gotoLine(1,0,!0),c.clearSelection(),c.session.getUndoManager().reset()}))}return["Courier New","Monaco","Lucida Console","Monospace","ui-monospace","Roboto Mono","Inconsolata","IBM Plex Mono","Space Mono","PT Mono","Ubuntu Mono","Nanum Gothic Coding","Cousine","Fira Mono","Share Tech Mono","Courier Prime","Anonymous Pro","Cutive Mono","Overpass Mono","Fira Code","VT323","DM Mono","Oxygen Mono","Nova Mono","B612 Mono","Spline Sans Mono","Noto Sans Mono","Major Mono Display","Azeret Mono","Red Hat Mono","Syne Mono","Xanh Mono"].sort().forEach((function(e,t){if(doesFontExist(e)){var n=document.createElement("option");n.text=e,p.add(n)}})),null!==s&&null!==l&&null!==r&&c.on("input",y),c.session.selection.on("changeCursor",h),s.onclick=v,l.onclick=e=>{c.undo()&&c.focus()},r.onclick=e=>{c.redo()&&c.focus()},d.onclick=e=>{x()&&c.execCommand("cut")},m.onclick=e=>{x()&&c.execCommand("copy")},u.onclick=function(){try{navigator.clipboard.readText().then((e=>{c.execCommand("paste",e)})).catch((e=>{u.disabled=!0}))}catch{u.disabled=!0}},c.loadUrl=(e,o)=>{n=i(t=e+o),a="text/"+n,"plain"!==n&&c.getSession().setMode("ace/mode/"+n),w(e+o)},c.hide=()=>{g=!1,y(),h(),_("editor").style.display="none"},"plain"!==n&&c.getSession().setMode("ace/mode/"+n),c.setTheme("ace/theme/"+o),c.$blockScrolling=1/0,c.commands.addCommand({name:"save",bindKey:{win:"Ctrl-S",mac:"Command-S"},exec:v,readOnly:!1}),c.commands.addCommand({name:"undo",bindKey:{win:"Ctrl-Z",mac:"Command-Z"},exec:function(){c.undo()}}),c.commands.addCommand({name:"redo",bindKey:{win:"Ctrl-Y",mac:"Command-Y"},exec:function(){c.redo()}}),void 0!==t&&w(t),c.resize(),c}function uploadFileAsync(e,t,n,o,a,i){fetchData("/edit","POST",e).then((e=>{generateToast({message:"Upload "+n+"/"+o+" "+t+" done.",background:"#ddd",color:"#000"}),n==o&&listFiles(a,i)}))}function doUpload(e,t){const n=_("upload"),o=n.files.length;if(0!==o)for(let a=0;a=0}function isText(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"txt":case"cmd":case"json":case"jsonl":case"htm":case"html":case"js":case"c":case"cpp":case"css":case"svg":case"xml":return!0}return!1}function isImage(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"bmp":case"png":case"jpg":case"gif":case"svg":return!0}return!1}function isAudio(e){if(isFolder(e))return!1;var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"wav":case"mp3":case"aac":case"m4a":case"wma":return!0}return!1}function icon(e){if(isFolder(e))return"dir";if(isImage(e))return"image";if(isAudio(e))return"audio";var t=/(?:\.([^.]+))?$/.exec(e.name)[1];if(void 0!==typeof t)switch(t){case"cmd":case"css":case"json":case"jsonl":case"ttf":return t;case"zip":case"gz":return"zip";case"html":case"htm":return"html"}return"file"}function preview(e,t){if(isImage(e)){let n=t+e.name;const o=_("preview");o.innerHTML='',o.style.display="block",ace.edit("editor").hide(),_("name").innerHTML=n}}function edit(e,t){isText(e)&&(ace.edit("editor").loadUrl(t,e.name),_("preview").style.display="none")}function url(e,t){console.log("click "+t+e.name),isImage(e)?preview(e,t):isText(e)&&edit(e,t)}async function fetchData(e,t,n,o){await fetch(e,{method:t,body:n}).then((n=>n.ok?(console.log(t+" OK "+e),n.text()):n.text().then((n=>{throw console.log(t+" FAIL "+e),new Error(n)})))).then((e=>{o&&o.remove(),console.log(e)})).catch((e=>{console.warn("AbortError"===e.name?"Promise Aborted":"Promise Rejected"),alert(e)})).finally((()=>{}))}function download(e,t){console.log("download "+t+e.name),document.getElementById("download-frame").src=t+e.name+"?download=true"}function remove(e,t,n){let o=t+e.name;isFolder(e)&&(o+="/"),console.log("remove "+o);const a=new FormData;a.append("path",o),fetchData("/edit","DELETE",a,n)}function create(e,t,n){var o=window.prompt("Create File in "+e,"");if(null==o||""==o||o.includes("/"))return;const a=new FormData;a.append("path",e+o),fetchData("/edit","PUT",a),fetch("/api/files/").then((e=>e.json())).then((o=>{t&&t.remove(),listFiles(n,e),console.log(o)}))}function upload(e,t){_("upload").onchange=()=>{doUpload(e,t)},_("upload").click()}function ctx(e,t,n,o){e.preventDefault(),ctx_el=o;let a,i=isFolder(t),c=_("ctx");c.style.display="block",a=c.getElementsByTagName("li")[0],a.onclick=i?function(){hidectx(),create(n+t.name+"/",o.children.item(1),o)}:function(){hidectx(),create(n,o.parentNode,o.parentNode.parentNode)},a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[1],i&&(a.onclick=function(){hidectx(),upload(o,n+t.name+"/")}),a.style.display=i?"block":"none",a=c.getElementsByTagName("li")[2],a.onclick=function(){edit(t,n),hidectx()},a.style.display=isText(t)?"block":"none",a=c.getElementsByTagName("li")[3],a.onclick=function(){preview(t,n),hidectx()},a.style.display=isImage(t)?"block":"none",a=c.getElementsByTagName("li")[4],a.onclick=function(){download(t,n),hidectx()},a.style.display=i?"none":"block",a=c.getElementsByTagName("li")[5],a.onclick=function(){remove(t,n,o),hidectx()},a.style.display=n?"block":"none";var s=document.body.scrollTop?document.body.scrollTop:document.documentElement.scrollTop,l=document.body.scrollLeft?document.body.scrollLeft:document.documentElement.scrollLeft,r=e.clientX+l+10,d=e.clientY+s-20,m=(c.offsetWidth,c.offsetHeight),u=document.documentElement.clientHeight;d+m>u&&(d=u-m-20),c.style.left=r+"px",c.style.top=d+"px",o&&o.classList.add("selitem")}function drag(e,t,n){let o=n+t.name;isFolder(t)&&(o+="/"),e.dataTransfer.setData("text",o),console.log("drag start "+o)}function drop(e,t){let n=e.dataTransfer.getData("text");n.startsWith(t)||(e.preventDefault(),console.log("Move "+n+" to "+t))}function listFiles(e,t){return console.log("listFiles"),fetch("/api/files/?dir="+t).then((e=>e.json())).then((n=>{if(0==n.length)return!1;let o=e.getElementsByTagName("div")[0];o&&(o.onclick=n=>{i.remove(),o.onclick=()=>{listFiles(e,t)},n.stopPropagation()});let a=e.getElementsByTagName("ul");for(let e=0;e{drag(event,e,t)},a.appendChild(s),s.innerHTML=''+o+"",isFolder(e)){let n=t+e.name+"/";s.classList.add("bold"),s.onclick=function(e){listFiles(a,n)},s.ondragover=e=>{e.preventDefault()},s.ondrop=e=>{drop(e,n)}}else(isText(e)||isImage(e)||isAudio(e))&&(s.onclick=function(n){url(e,t)});s.oncontextmenu=n=>{ctx(n,e,t,a)}}return e.scrollIntoView(),!0}))}function generateToast({message:e,background:t="#00214d",color:n="#fffffe",length:o="7000ms"}){_("toast").insertAdjacentHTML("afterbegin",`

\n ${e}\n

`);const a=_("toast").firstElementChild;a.addEventListener("animationend",(()=>a.remove()))}document.addEventListener("blur",(function(){hidectx()})),document.addEventListener("DOMContentLoaded",(function(){createEditor("editor",void 0,void 0,void 0);listFiles(_("tree"),"/"),_("tree").getElementsByTagName("div")[0].oncontextmenu=e=>{ctx(e,{name:"",children:[]},"",_("tree"))},_("load").onclick=function(e){const t=new FormData;t.append("load",""),fetchData("/edit","PUT",t)},_("init").onclick=function(e){const t=new FormData;t.append("init",""),fetchData("/edit","PUT",t)},_("home").onclick=function(e){window.location.href="/"},_("page").onchange=function(e){const t=new FormData;t.append("page",_("page").value),fetchData("/edit","PUT",t)}})),document.addEventListener("DOMContentLoaded",(function(){const e=document.getElementById("dragMe"),t=e.previousElementSibling,n=e.nextElementSibling;let o=0,a=0,i=0;const c=function(a){const c=a.clientX-o,s=(a.clientY,100*(i+c)/e.parentNode.getBoundingClientRect().width);t.style.width=`${s}%`,t.style.right=t.style.width,e.style.cursor="col-resize",document.body.style.cursor="col-resize",t.style.userSelect="none",t.style.pointerEvents="none",n.style.userSelect="none",n.style.pointerEvents="none",ace.edit("editor").resize()},s=function(){e.style.removeProperty("cursor"),document.body.style.removeProperty("cursor"),t.style.removeProperty("user-select"),t.style.removeProperty("pointer-events"),n.style.removeProperty("user-select"),n.style.removeProperty("pointer-events"),document.removeEventListener("mousemove",c),document.removeEventListener("mouseup",s)};e.addEventListener("mousedown",(function(e){o=e.clientX,a=e.clientY,i=t.getBoundingClientRect().width,document.addEventListener("mousemove",c),document.addEventListener("mouseup",s)})),e.addEventListener("dblclick",(()=>{var e=t.style.visibility="hidden"===t.style.visibility;t.style.visibility=e?"unset":"hidden",t.style.position=e?"unset":"absolute",ace.edit("editor").resize()}))})); \ No newline at end of file From 348852476ddc87aa14776b64eb8b2439654b7433 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Tue, 23 Jul 2024 22:28:36 +0200 Subject: [PATCH 54/55] Use "event" group for pushbuttons in discovery { --- src/hasp/hasp_dispatch.cpp | 44 ++++++++++++++++++++++++++++++++++---- src/sys/gpio/hasp_gpio.cpp | 8 +++++-- src/sys/gpio/hasp_gpio.h | 2 +- 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/hasp/hasp_dispatch.cpp b/src/hasp/hasp_dispatch.cpp index 72c6b4f0..33cffc77 100644 --- a/src/hasp/hasp_dispatch.cpp +++ b/src/hasp/hasp_dispatch.cpp @@ -868,10 +868,45 @@ void dispatch_run_script(const char*, const char* payload, uint8_t source) #endif } -void dispatch_dir(const char*, const char* payload, uint8_t source) +/* +void dispatch_fs(const char*, const char* payload, uint8_t source) { - filesystem_list_path(payload); + StaticJsonDocument<512> json; + + // Note: Deserialization needs to be (const char *) so the objects WILL be copied + // this uses more memory but otherwise the mqtt receive buffer can get overwritten by the send buffer !! + DeserializationError jsonError = deserializeJson(json, payload); + // json.shrinkToFit(); + + if(!jsonError && json.is()) { // Only JsonObject is valid + JsonVariant action; + + const char* cmd = json["cmd"].as(); + const char* src = json["src"].as(); + const char* dst = json["dst"].as(); + int res = 0; + + if(String(cmd) == "stat") { + res = filesystem_vfs_file_exists(src); + } + if(String(cmd) == "rm") { + res = filesystem_vfs_delete_file(src); + } + if(String(cmd) == "cp") { + res = filesystem_vfs_copy_file(src, dst); + } + if(String(cmd) == "ls") { + filesystem_list_path(src); + } + + if(res) { + LOG_WARNING(TAG_MSGR, "Succes"); + } else { + LOG_WARNING(TAG_MSGR, "Failed"); + } + } } +*/ #if HASP_TARGET_PC static void shell_command_thread(char* cmdline) @@ -1327,9 +1362,10 @@ void dispatch_get_discovery_data(JsonDocument& doc) JsonArray relay = doc.createNestedArray(F("power")); JsonArray led = doc.createNestedArray(F("light")); JsonArray dimmer = doc.createNestedArray(F("dim")); + JsonArray event = doc.createNestedArray(F("event")); #if HASP_USE_GPIO > 0 - gpio_discovery(input, relay, led, dimmer); + gpio_discovery(input, relay, led, dimmer, event); #endif } @@ -1601,7 +1637,7 @@ void dispatchSetup() dispatch_add_command(PSTR("sensors"), dispatch_send_sensordata); dispatch_add_command(PSTR("theme"), dispatch_theme); dispatch_add_command(PSTR("run"), dispatch_run_script); - dispatch_add_command(PSTR("dir"), dispatch_dir); + // dispatch_add_command(PSTR("fs"), dispatch_fs); #if HASP_TARGET_PC dispatch_add_command(PSTR("shell"), dispatch_shell_execute); #endif diff --git a/src/sys/gpio/hasp_gpio.cpp b/src/sys/gpio/hasp_gpio.cpp index 0094f80b..69f1feb8 100644 --- a/src/sys/gpio/hasp_gpio.cpp +++ b/src/sys/gpio/hasp_gpio.cpp @@ -835,7 +835,7 @@ hasp_gpio_config_t gpioGetPinConfig(uint8_t num) return gpioConfig[num]; } -void gpio_discovery(JsonObject& input, JsonArray& relay, JsonArray& light, JsonArray& dimmer) +void gpio_discovery(JsonObject& input, JsonArray& relay, JsonArray& light, JsonArray& dimmer, JsonArray& event) { char description[20] = ""; @@ -848,6 +848,10 @@ void gpio_discovery(JsonObject& input, JsonArray& relay, JsonArray& light, JsonA case hasp_gpio_type_t::POWER_RELAY: relay.add(gpioConfig[i].pin); break; + + case BUTTON ... TOUCH: + event.add(gpioConfig[i].pin); + break; case hasp_gpio_type_t::HASP_DAC: case hasp_gpio_type_t::LED: // Don't include the moodlight @@ -857,8 +861,8 @@ void gpio_discovery(JsonObject& input, JsonArray& relay, JsonArray& light, JsonA dimmer.add(gpioConfig[i].pin); break; + // case BUTTON ... TOUCH: case SWITCH: - case BUTTON ... TOUCH: strcpy_P(description, PSTR("none")); break; case BATTERY: diff --git a/src/sys/gpio/hasp_gpio.h b/src/sys/gpio/hasp_gpio.h index df093048..105f4460 100644 --- a/src/sys/gpio/hasp_gpio.h +++ b/src/sys/gpio/hasp_gpio.h @@ -47,7 +47,7 @@ bool gpio_set_pin_state(uint8_t pin, bool power, int32_t val); void gpio_set_moodlight(moodlight_t& moodlight); -void gpio_discovery(JsonObject& input, JsonArray& relay, JsonArray& light, JsonArray& dimmer); +void gpio_discovery(JsonObject& input, JsonArray& relay, JsonArray& light, JsonArray& dimmer, JsonArray& event); bool gpioSavePinConfig(uint8_t config_num, uint8_t pin, uint8_t type, uint8_t group, uint8_t pinfunc, bool inverted); bool gpioIsSystemPin(uint8_t gpio); From 31572ef9d05722ae53ec72ec57f3b6c1150917fb Mon Sep 17 00:00:00 2001 From: fvanroie Date: Tue, 23 Jul 2024 22:44:50 +0200 Subject: [PATCH 55/55] Add "event" key to discovery message for push button events --- src/sys/gpio/hasp_gpio.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sys/gpio/hasp_gpio.cpp b/src/sys/gpio/hasp_gpio.cpp index 69f1feb8..693eec7b 100644 --- a/src/sys/gpio/hasp_gpio.cpp +++ b/src/sys/gpio/hasp_gpio.cpp @@ -954,8 +954,8 @@ void gpio_discovery(JsonObject& input, JsonArray& relay, JsonArray& light, JsonA strcpy_P(description, PSTR("unknown")); } - if((gpioConfig[i].type >= hasp_gpio_type_t::SWITCH && gpioConfig[i].type <= hasp_gpio_type_t::WINDOW) || - (gpioConfig[i].type >= hasp_gpio_type_t::BUTTON && gpioConfig[i].type <= hasp_gpio_type_t::TOUCH)) { + if((gpioConfig[i].type >= hasp_gpio_type_t::SWITCH && gpioConfig[i].type <= hasp_gpio_type_t::WINDOW)) { + // || (gpioConfig[i].type >= hasp_gpio_type_t::BUTTON && gpioConfig[i].type <= hasp_gpio_type_t::TOUCH)) { JsonArray arr = input[description]; if(arr.isNull()) arr = input.createNestedArray(description); arr.add(gpioConfig[i].pin);