Merge branch 'mdev' into ESP32-HUB75-MatrixPanel-DMA

This commit is contained in:
Will Tatam
2024-02-10 13:44:01 +00:00
124 changed files with 5969 additions and 5959 deletions

View File

@@ -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")

View File

@@ -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} &nbsp;<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")+"\">&#xe08f;</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(() => {

View File

@@ -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) {

View File

@@ -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];

View File

@@ -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>\

View File

@@ -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>

View File

@@ -370,7 +370,7 @@
<span id="lssuc" style="color:green; display:none">&#10004; Configuration saved!</span>
<span id="lserr" style="color:red; display:none">&#9888; 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>

View File

@@ -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>

View File

@@ -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);

View File

@@ -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%;
}