Merge branch 'mdev' into ESP32-HUB75-MatrixPanel-DMA
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
|
||||
<meta http-equiv="Pragma" content="no-cache">
|
||||
<meta http-equiv="Expires" content="0">
|
||||
@@ -45,6 +46,7 @@
|
||||
width: 7px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
touch-action: none;
|
||||
}
|
||||
.color-picker-marker {
|
||||
height: 7px;
|
||||
@@ -94,9 +96,14 @@
|
||||
line-height: 1;
|
||||
}
|
||||
.wrap {
|
||||
width: 800px;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
@media (min-width: 800px) {
|
||||
.wrap {
|
||||
width: 800px;
|
||||
}
|
||||
}
|
||||
.palette {
|
||||
height: 20px;
|
||||
}
|
||||
@@ -136,6 +143,9 @@
|
||||
.sendSpan, .editSpan{
|
||||
cursor: pointer;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -191,6 +201,7 @@
|
||||
var gradientLength = rect.width;
|
||||
var mOffs = Math.round((gradientLength / 256) / 2) - 5;
|
||||
var paletteArray = []; //Holds the palettes after load.
|
||||
var paletteName = []; // Holds the names of the palettes after load.
|
||||
var svgSave = '<svg style="width:25px;height:25px" viewBox="0 0 24 24"><path fill=#fff d="M22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2A10,10 0 0,1 22,12M7,12L12,17V14H16V10H12V7L7,12Z"/></svg>'
|
||||
var svgEdit = '<svg style="width:25px;height:25px" viewBox="0 0 24 24"><path fill=#fff d="M12,2C6.47,2 2,6.47 2,12C2,17.53 6.47,22 12,22C17.53,22 22,17.53 22,12C22,6.47 17.53,2 12,2M15.1,7.07C15.24,7.07 15.38,7.12 15.5,7.23L16.77,8.5C17,8.72 17,9.07 16.77,9.28L15.77,10.28L13.72,8.23L14.72,7.23C14.82,7.12 14.96,7.07 15.1,7.07M13.13,8.81L15.19,10.87L9.13,16.93H7.07V14.87L13.13,8.81Z"/></svg>'
|
||||
|
||||
@@ -349,24 +360,31 @@
|
||||
var gradientLength = maxX - minX + 1;
|
||||
|
||||
elmnt.onmousedown = dragMouseDown;
|
||||
elmnt.ontouchstart = dragMouseDown;
|
||||
|
||||
function dragMouseDown(e) {
|
||||
removeTrashcan(event)
|
||||
e = e || window.event;
|
||||
e.preventDefault();
|
||||
var isTouch = e.type.startsWith('touch');
|
||||
if (!isTouch) e.preventDefault();
|
||||
// get the mouse cursor position at startup:
|
||||
mousePos = e.clientX;
|
||||
mousePos = isTouch ? e.touches[0].clientX : e.clientX;
|
||||
d.onmouseup = closeDragElement;
|
||||
d.ontouchcancel = closeDragElement;
|
||||
d.ontouchend = closeDragElement;
|
||||
// call a function whenever the cursor moves:
|
||||
d.onmousemove = elementDrag;
|
||||
d.ontouchmove = elementDrag;
|
||||
}
|
||||
|
||||
function elementDrag(e) {
|
||||
e = e || window.event;
|
||||
e.preventDefault();
|
||||
var isTouch = e.type.startsWith('touch');
|
||||
if (!isTouch) e.preventDefault();
|
||||
// calculate the new cursor position:
|
||||
posNew = mousePos - e.clientX;
|
||||
mousePos = e.clientX;
|
||||
var clientX = isTouch ? e.touches[0].clientX : e.clientX;
|
||||
posNew = mousePos - clientX;
|
||||
mousePos = clientX;
|
||||
mousePosInGradient = mousePos - (minX + 1)
|
||||
|
||||
truePos = Math.round((mousePosInGradient/gradientLength)*256);
|
||||
@@ -393,7 +411,10 @@
|
||||
function closeDragElement() {
|
||||
/* stop moving when mouse button is released:*/
|
||||
d.onmouseup = null;
|
||||
d.ontouchcancel = null;
|
||||
d.ontouchend = null;
|
||||
d.onmousemove = null;
|
||||
d.ontouchmove = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -485,7 +506,7 @@
|
||||
console.log('Error: ', e); console.log(' Status: ', this.status);
|
||||
//Show some error notification for some time
|
||||
setTimeout(()=>{
|
||||
//Remove it when time has pased
|
||||
//Remove it when time has passed
|
||||
}, 1000);
|
||||
});
|
||||
req.open("POST", "/upload");
|
||||
@@ -500,8 +521,10 @@
|
||||
if (hst.length > 0 ) {
|
||||
try {
|
||||
var arr = [];
|
||||
const response = await fetch('http://'+hst+'/json/info');
|
||||
const json = await response.json();
|
||||
const responseInfo = await fetch('http://'+hst+'/json/info');
|
||||
const responsePalettes = await fetch('http://'+hst+'/json/palettes');
|
||||
const json = await responseInfo.json();
|
||||
paletteName = await responsePalettes.json();
|
||||
cpalc = json.cpalcount;
|
||||
fetchPalettes(cpalc-1);
|
||||
} catch (error) {
|
||||
@@ -530,7 +553,7 @@
|
||||
paletteArray.push({"palette":[0,70,70,70,255,70,70,70]});
|
||||
}
|
||||
|
||||
//Get static palettes from localStorage and do some magic to reformat them into the same format as the pallete JSONs
|
||||
//Get static palettes from localStorage and do some magic to reformat them into the same format as the palette JSONs
|
||||
//This code excludes any objects with "non valid integer colors", i.e. r, c1, c2, c3 and such
|
||||
//This code also fixes potentially broken palettes which doesn't end on 255
|
||||
//The code finally also removes any representations of the custom palettes, since we read them from file
|
||||
@@ -540,6 +563,7 @@
|
||||
alert("The cache of palettes are missig from your browser. You should probably return to the main page and let it load properly for the palettes cache to regenerate before returning here.","Missing cached palettes!")
|
||||
} else {
|
||||
for (const key in wledPalx.p) {
|
||||
wledPalx.p[key].name = paletteName[key];
|
||||
if (key > 245) {
|
||||
delete wledPalx.p[key];
|
||||
continue;
|
||||
@@ -571,8 +595,11 @@
|
||||
}
|
||||
|
||||
const pArray = Object.entries(wledPalx.p).map(([key, value]) => ({
|
||||
[key]: value.flat()
|
||||
[key]: value.flat(),
|
||||
name: value.name
|
||||
}));
|
||||
// Sort pArray by name
|
||||
pArray.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
paletteArray.push( ...pArray);
|
||||
}
|
||||
@@ -614,6 +641,9 @@
|
||||
editSpan.id = `editSpan${i}`;
|
||||
editSpan.onclick = function() {loadForEdit(i)};
|
||||
editSpan.setAttribute('title', `Copy slot ${i} palette to editor`);
|
||||
if (paletteArray[i].name) {
|
||||
editSpan.setAttribute('title', `Copy ${paletteArray[i].name} palette to editor`);
|
||||
}
|
||||
editSpan.innerHTML = svgEdit;
|
||||
editSpan.classList.add("editSpan")
|
||||
|
||||
|
||||
@@ -33,15 +33,17 @@ var hol = [
|
||||
[0,11,24,4,"https://aircoookie.github.io/xmas.png"], // christmas
|
||||
[0,2,17,1,"https://images.alphacoders.com/491/491123.jpg"], // st. Patrick's day
|
||||
[2025,3,20,2,"https://aircoookie.github.io/easter.png"],
|
||||
[2023,3,9,2,"https://aircoookie.github.io/easter.png"],
|
||||
[2024,2,31,2,"https://aircoookie.github.io/easter.png"],
|
||||
[0,6,4,1,"https://initiate.alphacoders.com/download/wallpaper/516792/images/jpg/510921363292536"], // 4th of July
|
||||
[0,0,1,1,"https://initiate.alphacoders.com/download/wallpaper/1198800/images/jpg/2522807481585600"] // new year
|
||||
[0,6,4,1,"https://images.alphacoders.com/516/516792.jpg"], // 4th of July
|
||||
[0,0,1,1,"https://images.alphacoders.com/119/1198800.jpg"] // new year
|
||||
];
|
||||
var ctx = null; // WLEDMM
|
||||
var ledmapNr = -1; //WLEDMM
|
||||
var ledmapFileNames = []; //WLEDMM
|
||||
let nodesData = []; //WLEDMM
|
||||
let ibtglChecked = true; //WLEDMM
|
||||
let sbtglChecked = true; //WLEDMM
|
||||
let sbchkChecked = false; //WLEDMM
|
||||
|
||||
function handleVisibilityChange() {if (!d.hidden && new Date () - lastUpdate > 3000) requestJson();}
|
||||
function sCol(na, col) {d.documentElement.style.setProperty(na, col);}
|
||||
@@ -673,11 +675,11 @@ function populateInfo(i)
|
||||
if (i.cn) vcn = i.cn;
|
||||
|
||||
//WLEDMM: add total heap and total PSRAM, and build number, add bin name
|
||||
if (i.ver.includes("0.14.1")) vcn = "Sitting Ducks"; // easter egg
|
||||
if (i.ver.includes("0.14.0")) vcn = "Lupo"; // check for MM versioning scheme
|
||||
if (i.ver.includes("0.14.0-b15")) vcn = "Sitting Ducks"; // late easter egg
|
||||
if (i.ver.includes("0.14.0-b2")) vcn = "This is the way"; // recently watched The Mandalorian? I have spoken ;-)
|
||||
if (i.ver.includes("0.14.0-b15.22")) vcn = "Lupo";
|
||||
if (i.ver.includes("0.14.1-b3")) vcn = "Fried Chicken"; // final line of "One Vision" by Queen
|
||||
cn += `v${i.ver} <i>"${vcn}"</i><p>(WLEDMM_${i.ver} ${i.rel}.bin)</p><p><em>build ${i.vid}</em></p><table>
|
||||
${urows}
|
||||
${urows===""?'':'<tr><td colspan=2><hr style="height:1px;border-width:0;color:SeaGreen;background-color:Seagreen"></td></tr>'}
|
||||
@@ -695,6 +697,7 @@ ${inforow("Filesystem",i.fs.u + "/" + i.fs.t + " kB (" +Math.round(i.fs.u*100/i.
|
||||
${theap>0?inforow("Heap ☾",((i.totalheap-i.freeheap)/1000).toFixed(0)+"/"+theap.toFixed(0)+" kB"," ("+Math.round((i.totalheap-i.freeheap)/(10*theap))+"%)"):""}
|
||||
${i.minfreeheap?inforow("Max used heap ☾",((i.totalheap-i.minfreeheap)/1000).toFixed(1)+" kB"," ("+Math.round((i.totalheap-i.minfreeheap)/(10*theap))+"%)"):""}
|
||||
${inforow("Free heap",heap," kB")}
|
||||
${i.freestack?inforow("Free stack ☾",(i.freestack/1024).toFixed(3)," kB"):""} <!--WLEDMM-->
|
||||
${inforow("Flash Size ☾",flashsize," kB")} <!--WLEDMM and Athom-->
|
||||
${i.tpram?inforow("PSRAM ☾",(i.tpram/1024).toFixed(1)," kB"):""}
|
||||
${i.psram?((i.tpram-i.psram)>16383?inforow("Used PSRAM ☾",((i.tpram-i.psram)/1024).toFixed(1)," kB"):inforow("Used PSRAM ☾",(i.tpram-i.psram)," B")):""}
|
||||
@@ -974,6 +977,11 @@ function redrawPalPrev()
|
||||
}
|
||||
}
|
||||
|
||||
// WLEDMM experimental - revert gamma correction in the browser (for palette preview)
|
||||
function unGamma(val, gamma){
|
||||
return Math.round(Math.pow(val / 255.0, 1.0/gamma) * 255.0);
|
||||
}
|
||||
|
||||
function genPalPrevCss(id)
|
||||
{
|
||||
if (!palettesData) return;
|
||||
@@ -996,15 +1004,17 @@ function genPalPrevCss(id)
|
||||
let r, g, b;
|
||||
let index = false;
|
||||
if (Array.isArray(e)) {
|
||||
// fastLED palettes, with gammas (2.6, 2.2, 2.5) - we revert with slightly reduced values, to better preserve contrast
|
||||
index = Math.round(e[0]/255*100);
|
||||
r = e[1];
|
||||
g = e[2];
|
||||
b = e[3];
|
||||
r = unGamma(e[1], 2.5);
|
||||
g = unGamma(e[2], 2.3);
|
||||
b = unGamma(e[3], 2.4);
|
||||
} else if (e == 'r') {
|
||||
r = Math.random() * 255;
|
||||
g = Math.random() * 255;
|
||||
b = Math.random() * 255;
|
||||
} else {
|
||||
// gradient palettes have custom gamma ~2.6 - don't revert, so their look matches the custom colors display
|
||||
let i = e[1] - 1;
|
||||
var cd = gId('csl').children;
|
||||
r = parseInt(cd[i].dataset.r);
|
||||
@@ -1104,7 +1114,7 @@ function ddpAll() {
|
||||
callNode(lastinfo.ip, "cfg", {"hw":{"led":{"ins":ins}}}); //self
|
||||
}
|
||||
|
||||
//curl -s -F "update=@/Users/ewoudwijma/Developer/GitHub/MoonModules/WLED/build_output/release/WLEDMM_0.14.0-b27.31_esp32_4MB_M.bin" 192.168.8.105/update >nul &
|
||||
//curl -s -F "update=@/Users/ewoudwijma/Developer/GitHub/MoonModules/WLED/build_output/release/WLEDMM_0.14.0-b28.35_esp32_4MB_M.bin" 192.168.8.105/update >nul &
|
||||
|
||||
//WLEDMM
|
||||
function SuperSync() {
|
||||
@@ -1180,7 +1190,7 @@ function populateNodes(i,n)
|
||||
}
|
||||
|
||||
//fetch both cfg.json and info from a node and store in nodesData array
|
||||
function fetchInfoAndCfg(ip, nodeNr, parms, callback) {
|
||||
function fetchInfoAndCfg(ip, nodeNr, callback) {
|
||||
//add td placeholders
|
||||
urows += `<tr>`;
|
||||
for (let nm of ["ins", "pwr", "ip", "type", "rel", "ver", "vid", "fx", "scale-bri", "gcc", "fps", "fpsr", "lpc", "lvc", "mrx", "pnl0", "pnlC", "pnlX", "ssu"])
|
||||
@@ -1188,22 +1198,24 @@ function populateNodes(i,n)
|
||||
urows += `</tr>`;
|
||||
|
||||
//fetch info, state and effects
|
||||
fetchAndExecute(`http://${ip}/`, "json", nodeNr, function(nodeNr, text) {
|
||||
fetchAndExecute(`http://${ip}/`, "json/si", nodeNr, function(nodeNr, text) {
|
||||
let info = JSON.parse(text)["info"];
|
||||
let state = JSON.parse(text)["state"];
|
||||
let effects = JSON.parse(text)["effects"];
|
||||
|
||||
//set values
|
||||
let name = n.nodes[nodeNr].name;
|
||||
let url = `<button class="btn" ${(ip == lastinfo.ip)?'style="background-color: red;"':''} title="${ip}" onclick="location.assign('http://${ip}');">${name}</button>`;
|
||||
gId(`ins${nodeNr}`).innerHTML = url;
|
||||
gId(`ip${nodeNr}`).innerText = ip;
|
||||
gId(`pwr${nodeNr}`).innerHTML = "<button class=\"btn btn-xs\" onclick=\"callNode('"+info.ip+"','state',{'on':"+(state.on?"false":"true")+"});\"><i class=\"icons "+(state.on?"on":"off")+"\"></i></button>";
|
||||
gId(`type${nodeNr}`).innerText = info.arch;
|
||||
gId(`vid${nodeNr}`).innerText = info.vid;
|
||||
gId(`ip${nodeNr}`).innerText = info.ip;
|
||||
gId(`rel${nodeNr}`).innerText = info.rel;
|
||||
gId(`ver${nodeNr}`).innerText = info.ver;
|
||||
gId(`lvc${nodeNr}`).innerText = info.leds.count;
|
||||
gId(`lpc${nodeNr}`).innerText = info.leds.countP;
|
||||
gId(`fpsr${nodeNr}`).innerText = info.leds.fps;
|
||||
gId(`fx${nodeNr}`).innerText = effects[state.seg[0].fx];
|
||||
gId(`fx${nodeNr}`).innerText = eJson.find((o)=>{return o.id==state.seg[0].fx}).name;
|
||||
|
||||
//store data
|
||||
if (!nodesData[nodeNr]) nodesData[nodeNr] = {};
|
||||
@@ -1215,12 +1227,10 @@ function populateNodes(i,n)
|
||||
}
|
||||
|
||||
//fetch cfg.json
|
||||
fetchAndExecute(`http://${ip}/`, "cfg.json", nodeNr, function(nodeNr,text) {
|
||||
fetchAndExecute(`http://${ip}/`, "cfg.json", nodeNr, function(nodeNr, text) {
|
||||
let cfg = JSON.parse(text);
|
||||
|
||||
//set values
|
||||
let url = `<button class="btn" ${(ip == lastinfo.ip)?'style="background-color: red;"':''} title="${ip}" onclick="location.assign('http://${ip}');">${cfg.id.name}</button>`;
|
||||
gId(`ins${nodeNr}`).innerHTML = url;
|
||||
gId(`scale-bri${nodeNr}`).innerText = cfg.light["scale-bri"];
|
||||
gId(`gcc${nodeNr}`).innerText = cfg.light.gc.col > 1;
|
||||
gId(`fps${nodeNr}`).innerText = cfg.hw.led.fps;
|
||||
@@ -1281,15 +1291,12 @@ function populateNodes(i,n)
|
||||
}
|
||||
}
|
||||
callback(nodeNr);
|
||||
}, function(nodeNr, text) {console.log("cfg error", nodeNr, n.nodes[nodeNr].name, text);callback(nodeNr);}); //also callback on error
|
||||
}, function(nodeNr, text) {
|
||||
console.log("cfg error", nodeNr, ip, n.nodes[nodeNr].name, text);
|
||||
callback(nodeNr);
|
||||
}); //also callback on error
|
||||
}, function(nodeNr, text) {
|
||||
//to show nodes which failed in providing json info
|
||||
let ip = n.nodes[nodeNr].ip;
|
||||
let name = n.nodes[nodeNr].name;
|
||||
let url = `<button class="btn" ${(ip == lastinfo.ip)?'style="background-color: red;"':''} title="${ip}" onclick="location.assign('http://${ip}');">${name}</button>`;
|
||||
gId(`ins${nodeNr}`).innerHTML = url;
|
||||
gId(`ip${nodeNr}`).innerText = ip;
|
||||
console.log("json error", nodeNr, ip, name, text);
|
||||
console.log("json error", nodeNr, ip, n.nodes[nodeNr].name, text);
|
||||
callback(nodeNr); //also callback on error
|
||||
});
|
||||
} //fetchInfoAndCfg
|
||||
@@ -1315,7 +1322,7 @@ function populateNodes(i,n)
|
||||
for (let o of n.nodes) {
|
||||
if (o.name) {
|
||||
if (o.ip) { //in ap mode no ip...
|
||||
fetchInfoAndCfg(o.ip, nnodes, -1, function(nodeNr) {
|
||||
fetchInfoAndCfg(o.ip, nnodes, function(nodeNr) {
|
||||
nodesDone++;
|
||||
console.log("nodesDone", nodesDone, nodeNr, n.nodes.length, nnodes, n.nodes[nodeNr].name);
|
||||
//if all done
|
||||
@@ -1365,7 +1372,7 @@ function updateTrail(e)
|
||||
{
|
||||
if (e==null) return;
|
||||
let sd = e.parentNode.getElementsByClassName('sliderdisplay')[0];
|
||||
if (sd && getComputedStyle(sd).getPropertyValue("--bg") !== "none") {
|
||||
if (sd && getComputedStyle(sd).getPropertyValue("--bg").trim() !== "none") { // trim() for Safari
|
||||
var max = e.hasAttribute('max') ? e.attributes.max.value : 255;
|
||||
var perc = Math.round(e.value * 100 / max);
|
||||
if (perc < 50) perc += 2;
|
||||
@@ -1384,7 +1391,7 @@ function toggleBubble(e)
|
||||
}
|
||||
|
||||
// updates segment length upon input of segment values
|
||||
function updateLen(s, draw=true) //WLEDMM conditonally draw segment view
|
||||
function updateLen(s, draw=true) //WLEDMM conditionally draw segment view
|
||||
{
|
||||
if (!gId(`seg${s}s`)) return;
|
||||
var start = parseInt(gId(`seg${s}s`).value);
|
||||
@@ -1725,7 +1732,7 @@ function updateUI()
|
||||
if (hasRGB) {
|
||||
updateTrail(gId('sliderR'));
|
||||
updateTrail(gId('sliderG'));
|
||||
updateTrail(gId('sliderB'));
|
||||
updateTrail(gId('sliderB'));
|
||||
}
|
||||
if (hasWhite) updateTrail(gId('sliderW'));
|
||||
|
||||
@@ -1978,9 +1985,9 @@ function readState(s,command=false)
|
||||
// - For AC effects (id<128) 2 sliders and 3 colors and the palette will be shown
|
||||
// - For SR effects (id>128) 5 sliders and 3 colors and the palette will be shown
|
||||
// If effective (@)
|
||||
// - a ; seperates slider controls (left) from color controls (middle) and palette control (right)
|
||||
// - a ; separates slider controls (left) from color controls (middle) and palette control (right)
|
||||
// - if left, middle or right is empty no controls are shown
|
||||
// - a , seperates slider controls (max 5) or color controls (max 3). Palette has only one value
|
||||
// - a , separates slider controls (max 5) or color controls (max 3). Palette has only one value
|
||||
// - a ! means that the default is used.
|
||||
// - For sliders: Effect speeds, Effect intensity, Custom 1, Custom 2, Custom 3
|
||||
// - For colors: Fx color, Background color, Custom
|
||||
@@ -2438,7 +2445,7 @@ function makeP(i,pl)
|
||||
end: 0
|
||||
};
|
||||
var rep = plJson[i].repeat ? plJson[i].repeat : 0;
|
||||
content =
|
||||
content =
|
||||
`<div id="ple${i}" style="margin-top:10px;"></div><label class="check revchkl">Shuffle
|
||||
<input type="checkbox" id="pl${i}rtgl" onchange="plR(${i})" ${plJson[i].r||rep<0?"checked":""}>
|
||||
<span class="checkmark"></span>
|
||||
@@ -2463,21 +2470,21 @@ ${makePlSel(plJson[i].end?plJson[i].end:0, true)}
|
||||
<span class="lstIname">
|
||||
Include brightness
|
||||
</span>
|
||||
<input type="checkbox" id="p${i}ibtgl" checked>
|
||||
<input type="checkbox" id="p${i}ibtgl" ${ibtglChecked?"checked":""}> <!--WLEDMM-->
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
<label class="check revchkl">
|
||||
<span class="lstIname">
|
||||
Save segment bounds
|
||||
</span>
|
||||
<input type="checkbox" id="p${i}sbtgl" checked>
|
||||
<input type="checkbox" id="p${i}sbtgl" ${sbtglChecked?"checked":""}> <!--WLEDMM-->
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
<label class="check revchkl">
|
||||
<span class="lstIname">
|
||||
Checked segments only
|
||||
</span>
|
||||
<input type="checkbox" id="p${i}sbchk">
|
||||
<input type="checkbox" id="p${i}sbchk" ${sbchkChecked?"checked":""}> <!--WLEDMM-->
|
||||
<span class="checkmark"></span>
|
||||
</label>`;
|
||||
if (Array.isArray(lastinfo.maps) && lastinfo.maps.length>0) { //WLEDMM >0 instead of 1 to show also first ledmap. Attention: WLED AC has isM check, in MM Matrices are supported so do not check on isM
|
||||
@@ -2518,7 +2525,15 @@ function makePUtil()
|
||||
p.innerHTML = `<div class="presin expanded">${makeP(0)}</div>`;
|
||||
let pTx = gId('p0txt');
|
||||
pTx.focus();
|
||||
pTx.value = eJson.find((o)=>{return o.id==selectedFx}).name;
|
||||
//WLEDMM: take the name PLUS the icons as default name
|
||||
let fxName = eJson.find((o)=>{return o.id==selectedFx}).name;
|
||||
|
||||
let sE = gId('fxlist').querySelector(`.lstI[data-id="${selectedFx}"]`);
|
||||
if (sE) {
|
||||
fxName = sE.querySelector(".lstIname").innerText;
|
||||
}
|
||||
|
||||
pTx.value = fxName;
|
||||
pTx.select();
|
||||
p.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
@@ -2906,8 +2921,11 @@ function saveP(i,pl)
|
||||
obj.o = true;
|
||||
} else {
|
||||
obj.ib = gId(`p${i}ibtgl`).checked;
|
||||
ibtglChecked = obj.ib; //WLEDMM
|
||||
obj.sb = gId(`p${i}sbtgl`).checked;
|
||||
sbtglChecked = obj.sb; //WLEDMM
|
||||
obj.sc = gId(`p${i}sbchk`).checked;
|
||||
sbchkChecked = obj.sc; //WLEDMM
|
||||
if (gId(`p${i}lmp`) && gId(`p${i}lmp`).value!=="") obj.ledmap = parseInt(gId(`p${i}lmp`).value);
|
||||
}
|
||||
}
|
||||
@@ -3239,7 +3257,7 @@ function genPresets()
|
||||
addToPlaylist("All", ef.id);
|
||||
if (m.includes("1")) addToPlaylist("All1", ef.id);
|
||||
if (m.includes("2")) addToPlaylist("All2", ef.id);
|
||||
} //fxData is array
|
||||
} //fxdata is array
|
||||
} //not RSVD
|
||||
} //all effects
|
||||
|
||||
@@ -3266,13 +3284,15 @@ function genPresets()
|
||||
//WLEDMM: utility function to load contents of file from FS (used in draw)
|
||||
function fetchAndExecute(url, name, parms, callback, callError = null)
|
||||
{
|
||||
let errorCalled = false;
|
||||
fetch
|
||||
(url+name, {
|
||||
method: 'get'
|
||||
})
|
||||
.then(res => {
|
||||
if (!res.ok) {
|
||||
callError("File " + name + " not found");
|
||||
if (!errorCalled && callError) callError(parms, "File " + name + " not found");
|
||||
errorCalled = true;
|
||||
return "";
|
||||
}
|
||||
return res.text();
|
||||
@@ -3281,7 +3301,8 @@ function fetchAndExecute(url, name, parms, callback, callError = null)
|
||||
callback(parms, text);
|
||||
})
|
||||
.catch(function (error) {
|
||||
if (callError) callError(parms, "Error getting " + name);
|
||||
if (!errorCalled && callError) callError(parms, "Error getting " + name);
|
||||
errorCalled = true;
|
||||
console.log(error);
|
||||
})
|
||||
.finally(() => {
|
||||
|
||||
@@ -25,7 +25,7 @@ function peek(c) {
|
||||
let mW = leds[2]; // matrix width
|
||||
let mH = leds[3]; // matrix height
|
||||
let pPL = Math.min(c.width / mW, c.height / mH); // pixels per LED (width of circle)
|
||||
let lOf = Math.floor((c.width - pPL*mW)/2); //left offeset (to center matrix)
|
||||
let lOf = Math.floor((c.width - pPL*mW)/2); //left offset (to center matrix)
|
||||
var i = 4; //same offset as in ws.cpp
|
||||
ctx.clearRect(0, 0, c.width, c.height); //WLEDMM
|
||||
function colorAmp(color) {
|
||||
|
||||
@@ -69,7 +69,7 @@ function getPixelRGBValues(base64Image) {
|
||||
let sizeY = szY.value;
|
||||
|
||||
if (color != accentColor || sizeX < 1 || sizeY < 1){
|
||||
//image will not be rezised Set desitred size to original size
|
||||
//image will not be resized Set desired size to original size
|
||||
sizeX = image.width;
|
||||
sizeY = image.height;
|
||||
//failsafe for not generating huge images automatically
|
||||
@@ -153,7 +153,7 @@ function getPixelRGBValues(base64Image) {
|
||||
let curentColorIndex = 0
|
||||
let commandArray = [];
|
||||
|
||||
//For evry pixel in the LED array
|
||||
//For every pixel in the LED array
|
||||
for (let i = 0; i < maxi; i++) {
|
||||
let pixel = ledRGBValues[i];
|
||||
let r = pixel[0];
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
GetV();checkSi();setABL();
|
||||
GetV();
|
||||
checkSi();
|
||||
setABL();
|
||||
if (d.um_p[0]==-1) d.um_p.shift();
|
||||
});
|
||||
// error event
|
||||
@@ -345,7 +347,7 @@
|
||||
${i+1}:
|
||||
<select name="LT${i}" onchange="UI(true)">${i>=maxB ? '' :
|
||||
'<option value="22" selected>WS281x</option>\
|
||||
<option value="30">SK6812 RGBW</option>\
|
||||
<option value="30">SK6812/WS2814 RGBW</option>\
|
||||
<option value="31">TM1814</option>\
|
||||
<option value="24">400kHz</option>\
|
||||
<option value="25">TM1829</option>\
|
||||
|
||||
@@ -168,8 +168,8 @@
|
||||
<option value="6">US-MST/MDT</option>
|
||||
<option value="7">US-AZ</option>
|
||||
<option value="8">US-PST/PDT</option>
|
||||
<option value="9">CST(AWST)</option>
|
||||
<option value="10">JST(KST)</option>
|
||||
<option value="9">CST (AWST, PHST)</option>
|
||||
<option value="10">JST (KST)</option>
|
||||
<option value="11">AEST/AEDT</option>
|
||||
<option value="12">NZST/NZDT</option>
|
||||
<option value="13">North Korea</option>
|
||||
|
||||
@@ -370,7 +370,7 @@
|
||||
<span id="lssuc" style="color:green; display:none">✔ Configuration saved!</span>
|
||||
<span id="lserr" style="color:red; display:none">⚠ Could not load configuration.</span>
|
||||
</div>
|
||||
<!-- WLEDMM: no gpios here as it is generated -->
|
||||
<!-- WLEDMM: no GPIOs here as it is generated -->
|
||||
<div id="um">Loading settings...</div>
|
||||
<div name="errorMessage"></div>
|
||||
<hr><button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
).reduce(
|
||||
// Filter out duplicate SSIDs. Since it is sorted by signal
|
||||
// strength, the strongest signal will be kept in the
|
||||
// order it orginally appeared in the array.
|
||||
// order it as originally appeared in the array.
|
||||
(unique, other) => {
|
||||
if(!unique.some(obj => obj.ssid === other.ssid)) {
|
||||
unique.push(other);
|
||||
@@ -178,6 +178,7 @@
|
||||
<option value="3">Never (not recommended)</option></select><br>
|
||||
AP IP: <span class="sip"> Not active </span><br>
|
||||
<h3>Experimental</h3>
|
||||
Force 802.11g mode (ESP8266 only): <input type="checkbox" name="FG"><br>
|
||||
Disable WiFi sleep: <input type="checkbox" name="WS"><br>
|
||||
<i>Can help with connectivity issues.<br>
|
||||
Do not enable if WiFi is working correctly, increases power consumption.</i>
|
||||
|
||||
@@ -965,7 +965,7 @@ function readState(s,command=false)
|
||||
errstr = "Missing IR.json.";
|
||||
break;
|
||||
case 19:
|
||||
errstr = "A filesystem error has occured.";
|
||||
errstr = "A filesystem error has occurred.";
|
||||
break;
|
||||
}
|
||||
showToast('Error ' + s.error + ": " + errstr, true);
|
||||
|
||||
@@ -61,6 +61,12 @@ button.sml {
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
.err {
|
||||
color: #f00;
|
||||
}
|
||||
.warn {
|
||||
color: #fa0;
|
||||
}
|
||||
input {
|
||||
background: #333;
|
||||
color: #fff;
|
||||
@@ -114,6 +120,10 @@ select {
|
||||
font-family: Verdana, sans-serif;
|
||||
border: 0.5ch solid #333;
|
||||
}
|
||||
select.pin {
|
||||
max-width: 120px;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
tr {
|
||||
line-height: 100%;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user