Merge pull request #3511 from WoodyLetsCode/simple-mode

New implementation of the simplified UI
This commit is contained in:
Blaž Kristan 2023-12-16 13:02:18 +01:00 committed by GitHub
commit 37c9fd278c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 2277 additions and 5930 deletions

View File

@ -219,36 +219,10 @@ function writeChunks(srcDir, specs, resultFile) {
}
writeHtmlGzipped("wled00/data/index.htm", "wled00/html_ui.h", 'index');
writeHtmlGzipped("wled00/data/simple.htm", "wled00/html_simple.h", 'simple');
writeHtmlGzipped("wled00/data/pixart/pixart.htm", "wled00/html_pixart.h", 'pixart');
writeHtmlGzipped("wled00/data/cpal/cpal.htm", "wled00/html_cpal.h", 'cpal');
writeHtmlGzipped("wled00/data/pxmagic/pxmagic.htm", "wled00/html_pxmagic.h", 'pxmagic');
/*
writeChunks(
"wled00/data",
[
{
file: "simple.css",
name: "PAGE_simpleCss",
method: "gzip",
filter: "css-minify",
},
{
file: "simple.js",
name: "PAGE_simpleJs",
method: "gzip",
filter: "js-minify",
},
{
file: "simple.htm",
name: "PAGE_simple",
method: "gzip",
filter: "html-minify-ui",
}
],
"wled00/html_simplex.h"
);
*/
writeChunks(
"wled00/data",
[

View File

@ -31,9 +31,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
getStringFromJson(cmDNS, id[F("mdns")], 33);
getStringFromJson(serverDescription, id[F("name")], 33);
getStringFromJson(alexaInvocationName, id[F("inv")], 33);
#ifdef WLED_ENABLE_SIMPLE_UI
CJSON(simplifiedUI, id[F("sui")]);
#endif
JsonObject nw = doc["nw"];
#ifndef WLED_DISABLE_ESPNOW
@ -655,9 +653,7 @@ void serializeConfig() {
id[F("mdns")] = cmDNS;
id[F("name")] = serverDescription;
id[F("inv")] = alexaInvocationName;
#ifdef WLED_ENABLE_SIMPLE_UI
id[F("sui")] = simplifiedUI;
#endif
JsonObject nw = doc.createNestedObject("nw");
#ifndef WLED_DISABLE_ESPNOW

View File

@ -370,6 +370,16 @@ button {
padding: 5px 0 0;
}
/* Quick load magin for simplified UI */
.simplified #pql {
margin-bottom: 8px;
}
/* Button margin for simplified UI */
.simplified #fx .btn, .simplified #palw .btn {
margin-top: 0;
}
.smooth { transition: transform calc(var(--f, 1)*.5s) ease-out }
.tab-label {
@ -413,6 +423,7 @@ button {
position: sticky;
bottom: 0;
max-width: 300px;
z-index: 2;
}
#sliders .labels {
@ -754,13 +765,17 @@ input[type=range]::-moz-range-thumb {
}
#Colors .sliderwrap {
margin: 4px 0 0;
margin: 2px 0 0;
}
/* Dynamically hide brightness slider label */
/* Dynamically hide labels */
.hd {
display: var(--bhd);
}
/* Do not hide quick load label in simplified mode on small screen widths */
.simplified #pql .hd {
display: var(--bhd) !important;
}
#briwrap {
min-width: 300px;
@ -1284,6 +1299,12 @@ TD .checkmark, TD .radiomark {
margin-top: 0;
}
/* Simplify segments */
.simplified #segcont .lstI {
margin-top: 4px;
min-height: unset;
}
/* selected item/element */
.selected { /* has to be after .lstI since !important is not ok */
background: var(--c-4);
@ -1324,6 +1345,19 @@ TD .checkmark, TD .radiomark {
top: calc(var(--sti) + 42px);
}
dialog::backdrop {
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
dialog {
max-height: 70%;
border: 0;
border-radius: 10px;
background: linear-gradient(rgba(0, 0, 0, 0.15), rgba(0, 0, 0, 0.1)), var(--c-3);
box-shadow: 4px 4px 10px 4px var(--c-1);
color: var(--c-f);
}
#fxlist .lstI.sticky,
#pallist .lstI.sticky {
top: var(--sti);

View File

@ -168,7 +168,7 @@
<input id="hexc" tooltip="Hex RGB" type="text" class="noslide" onkeydown="hexEnter()" autocomplete="off" maxlength="8" />
<button id="hexcnf" class="btn btn-xs" onclick="fromHex();"><i class="icons btn-icon">&#xe390;</i></button>
</div>
<div style="padding: 8px 0;">
<div style="padding: 8px 0;" id="btns">
<button class="btn btn-xs" tooltip="Pixel Magic Tool" type="button" id="pxmb" onclick="window.location.href=getURL('/pxmagic.htm')"><i class="icons btn-icon">&#xe410;</i></button>
<button class="btn btn-xs" tooltip="Add custom palette" type="button" onclick="window.location.href=getURL('/cpal.htm')"><i class="icons btn-icon">&#xe18a;</i></button>
<button class="btn btn-xs" tooltip="Remove custom palette" type="button" id="rmPal" onclick="palettesData=null;localStorage.removeItem('wledPalx');requestJson({rmcpal:true});setTimeout(loadPalettes,250,loadPalettesData);"><i class="icons btn-icon">&#xe037;</i></button>

View File

@ -12,6 +12,7 @@ var currentPreset = -1;
var lastUpdate = 0;
var segCount = 0, ledCount = 0, lowestUnused = 0, maxSeg = 0, lSeg = 0;
var pcMode = false, pcModeA = false, lastw = 0, wW;
var simplifiedUI = false;
var tr = 7;
var d = document;
var palettesData;
@ -624,11 +625,12 @@ function parseInfo(i) {
if (name === "Dinnerbone") d.documentElement.style.transform = "rotate(180deg)"; // Minecraft easter egg
if (i.live) name = "(Live) " + name;
if (loc) name = "(L) " + name;
d.title = name;
ledCount = i.leds.count;
//syncTglRecv = i.str;
maxSeg = i.leds.maxseg;
pmt = i.fs.pmt;
d.title = name;
simplifiedUI = i.simplifiedui;
ledCount = i.leds.count;
//syncTglRecv = i.str;
maxSeg = i.leds.maxseg;
pmt = i.fs.pmt;
gId('buttonNodes').style.display = lastinfo.ndc > 0 ? null:"none";
// do we have a matrix set-up
mw = i.leds.matrix ? i.leds.matrix.w : 0;
@ -750,6 +752,7 @@ function populateSegments(s)
let rvXck = `<label class="check revchkl">Reverse ${isM?'':'direction'}<input type="checkbox" id="seg${i}rev" onchange="setRev(${i})" ${inst.rev?"checked":""}><span class="checkmark"></span></label>`;
let miXck = `<label class="check revchkl">Mirror<input type="checkbox" id="seg${i}mi" onchange="setMi(${i})" ${inst.mi?"checked":""}><span class="checkmark"></span></label>`;
let rvYck = "", miYck ="";
let smpl = simplifiedUI ? 'hide' : '';
if (isMSeg) {
rvYck = `<label class="check revchkl">Reverse<input type="checkbox" id="seg${i}rY" onchange="setRevY(${i})" ${inst.rY?"checked":""}><span class="checkmark"></span></label>`;
miYck = `<label class="check revchkl">Mirror<input type="checkbox" id="seg${i}mY" onchange="setMiY(${i})" ${inst.mY?"checked":""}><span class="checkmark"></span></label>`;
@ -768,23 +771,23 @@ function populateSegments(s)
`<option value="1" ${inst.si==1?' selected':''}>WeWillRockYou</option>`+
`</select></div>`+
`</div>`;
cn += `<div class="seg lstI ${i==s.mainseg ? 'selected' : ''} ${exp ? "expanded":""}" id="seg${i}" data-set="${inst.set}">`+
`<label class="check schkl">`+
cn += `<div class="seg lstI ${i==s.mainseg && !simplifiedUI ? 'selected' : ''} ${exp ? "expanded":""}" id="seg${i}" data-set="${inst.set}">`+
`<label class="check schkl ${smpl}">`+
`<input type="checkbox" id="seg${i}sel" onchange="selSeg(${i})" ${inst.sel ? "checked":""}>`+
`<span class="checkmark"></span>`+
`</label>`+
`<div class="segname" onclick="selSegEx(${i})">`+
`<div class="segname ${smpl}" onclick="selSegEx(${i})">`+
`<i class="icons e-icon frz" id="seg${i}frz" onclick="event.preventDefault();tglFreeze(${i});">&#x${inst.frz ? (li.live && li.liveseg==i?'e410':'e0e8') : 'e325'};</i>`+
(inst.n ? inst.n : "Segment "+i) +
`<div class="pop hide" onclick="event.preventDefault();event.stopPropagation();">`+
`<i class="icons g-icon" style="color:${cG};" onclick="this.nextElementSibling.classList.toggle('hide');">&#x278${String.fromCharCode(inst.set+"A".charCodeAt(0))};</i>`+
`<div class="pop-c hide"><span style="color:var(--c-f);" onclick="setGrp(${i},0);">&#x278A;</span><span style="color:var(--c-r);" onclick="setGrp(${i},1);">&#x278B;</span><span style="color:var(--c-g);" onclick="setGrp(${i},2);">&#x278C;</span><span style="color:var(--c-l);" onclick="setGrp(${i},3);">&#x278D;</span></div>`+
`</div> `+
`<i class="icons edit-icon flr" id="seg${i}nedit" onclick="tglSegn(${i})">&#xe2c6;</i>`+
`<i class="icons edit-icon flr ${smpl}" id="seg${i}nedit" onclick="tglSegn(${i})">&#xe2c6;</i>`+
`</div>`+
`<i class="icons e-icon flr" id="sege${i}" onclick="expand(${i})">&#xe395;</i>`+
`<i class="icons e-icon flr ${smpl}" id="sege${i}" onclick="expand(${i})">&#xe395;</i>`+
(cfg.comp.segpwr ? segp : '') +
`<div class="segin" id="seg${i}in">`+
`<div class="segin ${smpl}" id="seg${i}in">`+
`<input type="text" class="ptxt" id="seg${i}t" autocomplete="off" maxlength=${li.arch=="esp8266"?32:64} value="${inst.n?inst.n:""}" placeholder="Enter name..."/>`+
`<table class="infot segt">`+
`<tr>`+
@ -834,6 +837,7 @@ function populateSegments(s)
}
gId('segcont').innerHTML = cn;
gId("segcont").classList.remove("hide");
let noNewSegs = (lowestUnused >= maxSeg);
resetUtil(noNewSegs);
if (gId('selall')) gId('selall').checked = true;
@ -847,6 +851,8 @@ function populateSegments(s)
if (segCount < 2) {
gId(`segd${lSeg}`).classList.add("hide");
if (parseInt(gId("seg0bri").value)==255) gId(`segp0`).classList.add("hide");
// hide segment controls if there is only one segment in simplified UI
if (simplifiedUI) gId("segcont").classList.add("hide");
}
if (!isM && !noNewSegs && (cfg.comp.seglen?parseInt(gId(`seg${lSeg}s`).value):0)+parseInt(gId(`seg${lSeg}e`).value)<ledCount) gId(`segr${lSeg}`).classList.remove("hide");
gId('segutil2').style.display = (segCount > 1) ? "block":"none"; // rsbtn parent
@ -1258,6 +1264,12 @@ function updateSelectedPalette(s)
var selectedPalette = parent.querySelector(`.lstI[data-id="${s}"]`);
if (selectedPalette) parent.querySelector(`.lstI[data-id="${s}"]`).classList.add('selected');
// Display selected palette name on button in simplified UI
let selectedName = selectedPalette.querySelector(".lstIname").innerText;
if (simplifiedUI) {
gId("palwbtn").innerText = "Palette: " + selectedName;
}
// in case of special palettes (* Colors...), force show color selectors (if hidden by effect data)
let cd = gId('csl').children; // color selectors
if (s > 1 && s < 6) {
@ -1299,8 +1311,15 @@ function updateSelectedFx()
}
}
});
// hide 2D mapping and/or sound simulation options
var selectedName = selectedEffect.querySelector(".lstIname").innerText;
// Display selected effect name on button in simplified UI
let selectedNameOnlyAscii = selectedName.replace(/[^\x00-\x7F]/g, "");
if (simplifiedUI) {
gId("fxbtn").innerText = "Effect: " + selectedNameOnlyAscii;
}
// hide 2D mapping and/or sound simulation options
var segs = gId("segcont").querySelectorAll(`div[data-map="map2D"]`);
for (const seg of segs) if (selectedName.indexOf("\u25A6")<0) seg.classList.remove('hide'); else seg.classList.add('hide');
var segs = gId("segcont").querySelectorAll(`div[data-snd="si"]`);
@ -1530,6 +1549,7 @@ function setEffectParameters(idx)
// set the bottom position of selected effect (sticky) as the top of sliders div
function setSelectedEffectPosition() {
if (simplifiedUI) return;
let top = parseInt(getComputedStyle(gId("sliders")).height);
top += 5;
let sel = d.querySelector('#fxlist .selected');
@ -1596,6 +1616,10 @@ function setEffectParameters(idx)
// disable palette list
text += ' not used';
palw.style.display = "none";
// Close palette dialog if not available
if (gId("palw").lastElementChild.tagName == "DIALOG") {
gId("palw").lastElementChild.close();
}
}
pall.innerHTML = icon + text;
// not all color selectors shown, hide palettes created from color selectors
@ -1661,6 +1685,7 @@ function requestJson(command=null)
parseInfo(i);
populatePalettes(i);
if (isInfo) populateInfo(i);
if (simplifiedUI) simplifyUI();
}
var s = json.state ? json.state : json;
readState(s);
@ -2259,6 +2284,12 @@ function setFX(ind = null)
} else {
d.querySelector(`#fxlist input[name="fx"][value="${ind}"]`).checked = true;
}
// Close effect dialog in simplified UI
if (simplifiedUI) {
gId("fx").lastElementChild.close();
}
var obj = {"seg": {"fx": parseInt(ind), "fxdef": cfg.comp.fxdef}}; // fxdef sets effect parameters to default values
requestJson(obj);
}
@ -2271,6 +2302,11 @@ function setPalette(paletteId = null)
d.querySelector(`#pallist input[name="palette"][value="${paletteId}"]`).checked = true;
}
// Close palette dialog in simplified UI
if (simplifiedUI) {
gId("palw").lastElementChild.close();
}
var obj = {"seg": {"pal": paletteId}};
requestJson(obj);
}
@ -2903,7 +2939,7 @@ function hasIroClass(classList)
//required by rangetouch.js
function lock(e)
{
if (pcMode) return;
if (pcMode || simplifiedUI) return;
var l = e.target.classList;
var pl = e.target.parentElement.classList;
@ -2917,7 +2953,7 @@ function lock(e)
//required by rangetouch.js
function move(e)
{
if(!locked || pcMode) return;
if(!locked || pcMode || simplifiedUI) return;
var clientX = unify(e).clientX;
var dx = clientX - x0;
var s = Math.sign(dx);
@ -2963,7 +2999,7 @@ function togglePcMode(fromB = false)
gId('buttonPcm').className = (pcMode) ? "active":"";
gId('bot').style.height = (pcMode && !cfg.comp.pcmbot) ? "0":"auto";
sCol('--bh', gId('bot').clientHeight + "px");
_C.style.width = (pcMode)?'100%':'400%';
_C.style.width = (pcMode || simplifiedUI)?'100%':'400%';
}
function mergeDeep(target, ...sources)
@ -3018,6 +3054,98 @@ function tooltip()
});
};
// Transforms the default UI into the simple UI
function simplifyUI() {
// Create dropdown dialog
function createDropdown(id, buttonText, dialogElements = null) {
// Create dropdown dialog
const dialog = document.createElement("dialog");
// Move every dialogElement to the dropdown dialog or if none are given, move all children of the element with the given id
if (dialogElements) {
dialogElements.forEach((e) => {
dialog.appendChild(e);
});
} else {
while (gId(id).firstChild) {
dialog.appendChild(gId(id).firstChild);
}
}
// Create button for the dropdown
const btn = document.createElement("button");
btn.id = id + "btn";
btn.classList.add("btn");
btn.innerText = buttonText;
function toggleDialog(e) {
if (e.target != btn && e.target != dialog) return;
if (dialog.open) {
dialog.close();
return;
}
// Prevent autofocus on dialog open
dialog.inert = true;
dialog.showModal();
dialog.inert = false;
clean(dialog.firstElementChild.children[1]);
dialog.scrollTop = 0;
};
btn.addEventListener("click", toggleDialog);
dialog.addEventListener("click", toggleDialog);
// Add the dialog and button to the element with the given id
gId(id).append(btn);
gId(id).append(dialog);
}
// Check if the UI was already simplified
if (gId("Colors").classList.contains("simplified")) return;
// Disable PC Mode as it does not exist in simple UI
if (pcMode) togglePcMode(true);
_C.style.width = '100%'
_C.style.setProperty('--n', 1);
gId("Colors").classList.add("simplified");
// Put effects below palett list
gId("Colors").append(gId("fx"));
gId("Colors").append(gId("sliders"));
// Put segments before palette list
gId("Colors").insertBefore(gId("segcont"), gId("pall"));
// Put preset quick load before palette list and segemts
gId("Colors").insertBefore(gId("pql"), gId("pall"));
// Create dropdown for palette list
createDropdown("palw", "Change palette");
createDropdown("fx", "Change effect", [gId("fxFind"), gId("fxlist")]);
// Hide pallete label
gId("pall").style.display = "none";
gId("Colors").insertBefore(document.createElement("br"), gId("pall"));
// Hide effect label
gId("modeLabel").style.display = "none";
// Hide buttons in top bar
gId("buttonNl").style.display = "none";
gId("buttonSync").style.display = "none";
gId("buttonSr").style.display = "none";
gId("buttonPcm").style.display = "none";
// Hide bottom bar
gId("bot").style.display = "none";
document.documentElement.style.setProperty('--bh', '0px');
// Hide other tabs
gId("Effects").style.display = "none";
gId("Segments").style.display = "none";
gId("Presets").style.display = "none";
// Hide filter options
gId("filters").style.display = "none";
// Hide buttons for pixel art and custom palettes (add / delete)
gId("btns").style.display = "none";
}
size();
_C.style.setProperty('--n', N);

View File

@ -267,10 +267,7 @@
<h2>Web Setup</h2>
Server description: <input type="text" name="DS" maxlength="32"><br>
<!-- Sync button toggles both send and receive: <input type="checkbox" name="ST"><br> -->
<div id="NoSimple" class="hide">
<i class="warn">This firmware build does not include simplified UI support.<br></i>
</div>
<div id="Simple">Enable simplified UI: <input type="checkbox" name="SU"><br></div>
Enable simplified UI: <input type="checkbox" name="SU"><br>
<i>The following UI customization settings are unique both to the WLED device and this browser.<br>
You will need to set them again if using a different browser, device or WLED IP address.<br>
Refresh the main UI to apply changes.</i><br>

View File

@ -1,933 +0,0 @@
@font-face {
font-family: "WIcons";
src: url(data:font/woff2;charset=utf-8;base64,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) format('woff');
}
:root {
--c-1: #111;
--c-f: #fff;
--c-2: #222;
--c-3: #333;
--c-4: #444;
--c-5: #555;
--c-6: #666;
--c-8: #888;
--c-b: #bbb;
--c-c: #ccc;
--c-e: #eee;
--c-d: #ddd;
--c-r: #e42;
--c-g: #4e2;
--c-l: #48a;
--t-b: .5;
--c-o: rgba(34, 34, 34, .9);
--c-tb : rgba(34, 34, 34, var(--t-b));
--c-tba: rgba(102, 102, 102, var(--t-b));
--c-tbh: rgba(51, 51, 51, var(--t-b));
/*following are internal*/
--th: 70px;
--tp: 70px;
--bh: 63px;
--tbp: 14px 8px 10px;
--bbp: 9px 0 7px 0;
--bhd: none;
--bmt: 0;
}
html {
touch-action: manipulation;
}
body {
margin: 0;
background-color: var(--c-1);
font-family: Helvetica, Verdana, sans-serif;
font-size: 17px;
color: var(--c-f);
text-align: center;
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-tap-highlight-color: transparent;
scrollbar-width: 6px;
scrollbar-color: var(--c-sb) transparent;
}
html,
body {
height: 100%;
width: 100%;
position: fixed;
overscroll-behavior: none;
}
#bg {
height: 100vh;
width: 100vw;
position: fixed;
z-index: -10;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
opacity: 0;
transition: opacity 2s;
}
p {
margin: 10px 0 2px 0;
}
a, p, a:visited {
color: var(--c-d);
}
a, a:visited {
text-decoration: none;
}
button {
outline: 0;
cursor: pointer;
background-color: transparent;
border: 0;
transition: color .3s, background-color .3s;
font-size: 19px;
color: var(--c-c);
min-width: 40px;
min-height: 40px;
}
button:hover {
background: var(--c-4);
}
.label {
margin: 0;
padding: 6px 0 0;
}
#namelabel {
position: fixed;
bottom: calc(var(--bh) + 6px);
right: 4px;
color: var(--c-6);
cursor: pointer;
writing-mode: vertical-rl;
}
.wrapper {
position: fixed;
top: 0;
left: 0;
right: 0;
background: var(--c-tb);
z-index: 1;
}
.center {
margin: 0 auto;
width: 320px;
}
.icons {
font-family: 'WIcons';
font-style: normal;
font-size: 24px;
line-height: 1;
display: inline-block;
margin: -2px 0 4px 0;
text-shadow: -1px -1px 0 var(--c-3), 1px -1px 0 var(--c-3), -1px 1px 0 var(--c-3), 1px 1px 0 var(--c-3);
}
.huge {
font-size: 42px;
}
.infot {
table-layout: fixed;
width: 100%;
}
.keytd {
text-align: left;
padding-bottom: 8px;
}
.valtd {
text-align: right;
padding-bottom: 8px;
}
.valtd i {
font-size: small;
}
.slider-icon
{
transform: translate(4px,3px);
color: var(--c-d);
}
.il {
display: inline-block;
vertical-align: middle;
}
.tab {
background-color: transparent;
color: var(--c-d);
}
.tab button {
background-color: transparent;
float: left;
border: 0;
transition: color .3s, background-color .3s;
font-size: 17px;
color: var(--c-c);
min-width: 44px;
}
.top button {
padding: var(--tbp);
margin: 0;
}
.tab button:hover {
background-color: var(--c-tbh);
color: var(--c-e);
}
.tab button.active {
background-color: var(--c-tba) !important;
color: var(--c-f);
}
.active {
background-color: var(--c-6) !important;
color: var(--c-f);
}
.container {
width: 100%;
height: calc(100% - var(--tp) - var(--bh));
margin-top: var(--tp);
overscroll-behavior: none;
}
.tabcontent {
position: relative;
width: 100%;
box-sizing: border-box;
border: 0;
overflow: auto;
height: 100%;
overscroll-behavior: none;
}
.smooth { transition: transform calc(var(--f, 1)*.5s) ease-out }
.tab-label {
margin: 0 0 -5px 0;
padding-bottom: 4px;
}
.overlay {
position: fixed;
height: 100%;
width: 100%;
top: 0;
left: 0;
background-color: var(--c-3);
font-size: 24px;
display: flex;
align-items: center;
justify-content: center;
z-index: 11;
opacity: .95;
transition: .7s;
pointer-events: none;
}
#toast {
opacity: 0;
background-color: var(--c-5);
max-width: 90%;
color: var(--c-f);
text-align: center;
border-radius: 5px;
padding: 16px;
position: fixed;
z-index: 5;
left: 50%;
transform: translateX(-50%);
bottom: calc(var(--bh) + 22px);
font-size: 17px;
pointer-events: none;
}
#toast.show {
opacity: 1;
animation: fadein .5s, fadein .5s 2.5s reverse;
}
#toast.error {
opacity: 1;
background-color: #b21;
animation: fadein .5s;
}
.modal {
position: fixed;
left: 0;
bottom: 0;
right: 0;
top: calc(var(--th) - 1px);
background-color: var(--c-o);
transform: translateY(100%);
transition: transform .4s;
padding: 8px;
font-size: 20px;
overflow: auto;
}
#info, #nodes {
z-index: 3;
}
#rover {
z-index: 2;
}
#ndlt {
margin: 12px 0;
}
#roverstar {
position: fixed;
top: calc(var(--th) + 5px);
left: 1px;
display: none;
cursor: pointer;
}
#connind {
position: fixed;
bottom: calc(var(--bh) + 5px);
left: 4px;
padding: 5px;
border-radius: 5px;
background-color: #a90;
z-index: -2;
}
#imgw {
display: inline-block;
margin: 8px;
}
#kv, #kn {
/*max-width: 490px;*/
display: inline-block;
}
#info table, #nodes table {
table-layout: fixed;
width: 100%;
}
#info td, #nodes td {
padding-bottom: 8px;
}
#info .btn {
margin: 5px;
}
#info table .btn, #nodes table .btn {
margin: 0;
width: 180px;
}
#info div, #nodes div {
width: 490px;
margin: 0 auto;
}
#kn td {
padding-bottom: 12px;
}
#heart {
transition: color .9s;
font-size: 16px;
color: #f00;
}
img {
max-width: 100%;
max-height: 100%;
}
.wi {
image-rendering: pixelated;
image-rendering: crisp-edges;
width: 210px;
}
@keyframes fadein {
from {bottom: 0; opacity: 0;}
to {bottom: calc(var(--bh) + 22px); opacity: 1;}
}
.sliderwrap {
height: 30px;
width: 250px;
position: relative;
margin: 4px 0;
}
#Colors .sliderwrap {
width: 260px;
margin: 10px 0 0;
}
.sliderdisplay {
content:'';
position: absolute;
top: 10px; left: 8px; right: 8px;
height: 8px;
background: var(--c-4);
border-radius: 16px;
pointer-events: none;
z-index: -1;
}
#Colors .sliderdisplay {
height: 28px;
top: 0; bottom: 0;
left: 0; right: 0;
/*border: 1px solid var(--c-b);*/
}
#rwrap .sliderdisplay { background: linear-gradient(90deg, #000 0%, #f00); }
#gwrap .sliderdisplay { background: linear-gradient(90deg, #000 0%, #0f0); }
#bwrap .sliderdisplay { background: linear-gradient(90deg, #000 0%, #00f); }
#wwrap .sliderdisplay { background: linear-gradient(90deg, #000 0%, #fff); }
#kwrap .sliderdisplay { background: linear-gradient(90deg, #ff8f1f 0%, #fff 50%, #cbdbff); }
#wbal .sliderdisplay { background: linear-gradient(90deg, #ff8f1f 0%, #fff 50%, #d4e0ff); }
.sliderbubble {
width: 24px;
position: relative;
display: inline-block;
border-radius: 10px;
background: var(--c-3);
color: var(--c-f);
padding: 4px 4px 2px;
font-size: 14px;
right: 3px;
transition: visibility .25s ease, opacity .25s ease;
opacity: 0;
visibility: hidden;
}
output.sliderbubbleshow {
visibility: visible;
opacity: 1;
}
.hidden {
display: none;
}
input[type=range] {
-webkit-appearance: none;
width: 100%;
padding: 0;
margin: 0;
background-color: transparent;
cursor: pointer;
}
#Colors input[type=range] {
width: 252px;
margin: 0;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 30px;
cursor: pointer;
background: transparent;
}
input[type=range]::-webkit-slider-thumb {
border: 2px solid #000;
height: 20px;
width: 20px;
border-radius: 50%;
background: var(--c-f);
cursor: pointer;
-webkit-appearance: none;
margin-top: 4px;
}
input[type=range]::-moz-range-track {
width: 100%;
height: 30px;
background-color: var(--c-0);
}
input[type=range]::-moz-range-thumb {
border: 2px solid var(--c-3);
height: 20px;
width: 20px;
border-radius: 50%;
background: var(--c-f);
transform: translateY(5px);
}
#Colors input[type=range]::-webkit-slider-thumb {
border: 2px solid #000;
}
#Colors input[type=range]::-moz-range-thumb {
border: 2px solid var(--c-1);
}
#Presets .list {
max-height: 215px;
overflow-y: scroll;
overflow-x: hidden;
width: 280px;
margin: 0 0 0 20px;
-ms-overflow-style: none;
scrollbar-width: none; /* Firefox */
}
/* Hide scrollbar for Chrome, Safari and Opera */
#Presets .list::-webkit-scrollbar {
display: none;
}
#Segments .sliderwrap{
width: 225px;
}
#picker, #rgbwrap, #kwrap, #vwrap, #wwrap, #wbal {
display: none;
}
.hd {
display: var(--bhd);
}
#briwrap {
float: right;
margin-top: var(--bmt);
}
#picker {
width: 260px;
}
#picker, #csl, #segcont {
margin: 10px auto 0;
}
.btn {
margin: 10px auto 0;
width: 280px;
font-size: 19px;
background-color: var(--c-3);
color: var(--c-d);
cursor: pointer;
border: 1px solid var(--c-3);
border-radius: 25px;
transition-duration: .3s;
-webkit-backface-visibility: hidden;
-webkit-transform: translate3d(0,0,0);
overflow: clip;
text-overflow: clip;
min-height: 40px;
line-height: 40px;
}
.btn:hover {
background-color: var(--c-4);
border: 1px solid var(--c-4);
}
.btn-xs {
width: 42px;
height: 42px;
margin: 4px;
padding: 0;
}
#fxBtn, #palBtn {
background-color: var(--c-2);
border: 1px solid var(--c-2);
}
#fxBtn:hover, #palBtn:hover {
background-color: var(--c-3);
border: 1px solid var(--c-3);
}
.btn-icon {
margin-right: 8px;
vertical-align: middle;
display: inline-block;
}
.qcs {
margin: 2px;
border-radius: 14px;
display: inline-block;
width: 28px;
height: 28px;
line-height: 28px;}
.qcsb {
width: 26px;
height: 26px;
line-height: 26px;
border: 1px solid var(--c-f);
}
option {
background-color: var(--c-3);
color: var(--c-f);
}
input[type=number], input[type=text] {
background: var(--c-3);
color: var(--c-f);
border: 0 solid var(--c-f);
border-radius: 5px;
padding: 8px;
margin: 6px 6px 6px 0;
font-size: 19px;
transition: background-color .2s;
outline: 0;
width: 50px;
-webkit-appearance: textfield;
-moz-appearance: textfield;
appearance: textfield;
}
::selection {
background: var(--c-b);
}
input[type=number]:focus, input[type=text]:focus {
background: var(--c-6);
}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
}
.pid {
position: absolute;
top: 0;
left: 0;
padding: 12px 0 0 12px;
font-size: 16px;
width: 20px;
text-align: center;
color: var(--c-b);
}
.xxs {
border: 2px solid var(--c-e) !important;
width: 44px;
height: 44px;
margin: 5px;
padding: 0;
}
.xxs-w {
border-width: 4px !important;
margin: 2px;
width: 50px;
height: 50px;
padding: 0;
}
.qcs, .xxs {
text-shadow: -1px -1px 0 var(--c-6), 1px -1px 0 var(--c-6), -1px 1px 0 var(--c-6), 1px 1px 0 var(--c-6);
}
.psts {
color: var(--c-f);
margin: 6px;
}
.pwr {
color: var(--c-6);
cursor: pointer;
}
.act {
color: var(--c-f);
}
.check, .radio {
display: inline-block;
position: relative;
cursor: pointer;
text-align: center;
}
.schkl {
width: 24px;
top: -2px;
}
.check input, .radio input {
position: absolute;
opacity: 0;
cursor: pointer;
height: 0;
width: 0;
}
.checkmark, .radiomark {
position: absolute;
top: 0;
bottom: 0;
left: 0;
background-color: var(--c-3);
border: 1px solid var(--c-2);
}
.radiomark {
height: 24px;
width: 24px;
border-radius: 50%;
}
.checkmark {
height: 25px;
width: 25px;
border-radius: 10px;
}
.check:hover input ~ .checkmark {
background-color: var(--c-4);
}
.check input:checked ~ .checkmark {
background-color: var(--c-6);
}
.checkmark:after, .radiomark:after {
content: "";
position: absolute;
display: none;
}
.check input:checked ~ .checkmark:after, .radio input:checked ~ .radiomark:after {
display: block;
}
.check .checkmark:after {
left: 9px;
top: 5px;
width: 5px;
height: 10px;
border: solid var(--c-f);
border-width: 0 3px 3px 0;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.radio .radiomark:after {
width: 12px;
height: 12px;
top: 50%;
left: 50%;
margin: -6px;
border-radius: 50%;
background: var(--c-f);
}
.h {
font-size: 13px;
color: var(--c-b);
}
.list {
position: relative;
width: 280px;
transition: background-color .5s;
margin: auto auto 20px;
font-size: 19px;
line-height: 24px;
}
.lstI {
cursor: pointer;
background-color: var(--c-2);
overflow: hidden;
border-radius: 20px;
display: block;
position: relative;
border: 1px solid var(--c-2);
padding: 8px 10px;
margin: 10px 0;
min-height: 24px;
}
.selected { /* has to be after .lstI */
background: var(--c-5);
}
.lstI:hover {
background: var(--c-4);
}
/*
.lstI:last-child {
border: 0;
border-radius: 0 0 20px 20px;
padding-bottom: 10px;
}
*/
.lstIcontent {
width: 100%;
vertical-align: middle;
padding: 0 20px 0 5px;
text-align: left;
}
.lstIname {
white-space: nowrap;
cursor: pointer;
}
.lstIprev {
width: 100%;
height: 8px;
position: absolute;
bottom: 0;
left: 0;
}
/* Dropdown Content (Hidden by Default) */
.dd-content {
display: none;
position: absolute;
width: 284px;
z-index: 1;
height: 260px;
overflow-y: scroll;
overflow-x: hidden;
padding: 0 18px;
margin-top: 10px;
-ms-overflow-style: none;
scrollbar-width: none; /* Firefox */
}
/* Hide scrollbar for Chrome, Safari and Opera */
.dd-content::-webkit-scrollbar {
display: none;
}
.fnd {
position: sticky;
top: 0;
z-index: 1;
width: 280px;
margin: 0 auto;
}
.search-icon {
position: absolute;
top: 10px;
left: 13px;
pointer-events: none;
width: 24px;
height: 24px;
margin-top: -1px;
z-index: 1;
}
.clear-icon {
position: absolute;
display: none;
top: 10px;
right: 13px;
cursor: pointer;
margin-top: -1px;
z-index: 1;
}
input[type=text].fnd {
display: block;
width: 100%;
box-sizing: border-box;
padding: 8px 48px 8px 48px;
margin: 5px auto 0;
text-align: left;
border-radius: 25px;
background-color: var(--c-2);
border: 1px solid var(--c-4);
}
input[type=text].fnd:focus {
background-color: var(--c-4);
}
input[type=text].fnd:not(:placeholder-shown), input[type=text].fnd:hover {
background-color: var(--c-3);
}
.h, .c {
text-align: center;
}
::-webkit-scrollbar {
width: 6px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: var(--c-sb);
opacity: .2;
border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--c-sbh);
}
@media not all and (hover: none) {
.sliderwrap:hover + output.sliderbubble {
visibility: visible;
opacity: 1;
}
}
@media all and (max-width: 335px) {
.sliderbubble {
display: none;
}
}
@media all and (max-width: 550px) and (min-width: 374px) {
#info .btn, #nodes .btn {
width: 150px;
}
#info div, #nodes div {
width: 320px;
}
}
@media all and (max-width: 540px) {
.top button {
width: 16.6%;
padding: 8px 0 4px 0;
}
}
@media all and (min-width: 541px) and (max-width: 719px) {
.top button {
width: 14.2%;
padding: 8px 0 4px 0;
}
}
@media all and (max-width: 719px) {
.hd {
display: none !important;
}
#briwrap {
margin-top: 0 !important;
float: none;
}
}

View File

@ -1,263 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<meta charset="utf-8">
<meta name="theme-color" content="#222222">
<meta content="yes" name="apple-mobile-web-app-capable">
<link rel="shortcut icon" href="data:image/x-icon;base64,AAABAAEAEBAAAAEAGACGAAAAFgAAAIlQTkcNChoKAAAADUlIRFIAAAAQAAAAEAgGAAAAH/P/YQAAAE1JREFUOI1j/P//PwOxgNGeAUMxE9G6cQCKDWAhpADZ2f8PMjBS3QW08QK20KaZC2gfC9hCnqouoNgARgY7zMxAyNlUdQHlXiAlO2MDAD63EVqNHAe0AAAAAElFTkSuQmCC"/>
<title>WLED</title>
<script>
function feedback(){}
// instead of including [script src="iro.js"][/script] and [script src="rangetouch.js"][/script]
// (which would be inlined by nodeJS inliner during minimization and compression) we need to load them dynamically
// the following is needed to load iro.js and rangetouch.js as consecutive requests to allow ESP8266
// to keep up with requests (if requests happent too fast some may not get processed)
// it will also call onLoad() after last is loaded (it was removed from [body onload="onLoad()"]).
var h = document.getElementsByTagName('head')[0];
var l = document.createElement('script');
l.type = 'application/javascript';
l.src = 'iro.js';
l.addEventListener('load', (e) => {
// after iro is loaded initialize global variable
cpick = new iro.ColorPicker("#picker", {
width: 260,
wheelLightness: false,
wheelAngle: 270,
wheelDirection: "clockwise",
layout: [{
component: iro.ui.Wheel,
options: {}
}]
});
cpick.on("input:end", () => {setColor(1);});
cpick.on("color:change", () => {updatePSliders()});
var l = document.createElement('script');
l.type = 'application/javascript';
l.src = 'rangetouch.js';
l.addEventListener('load', (e) => {
// after rangetouch is loaded initialize global variable
ranges = RangeTouch.setup('input[type="range"]', {});
let stateCheck = setInterval(() => {
if (document.readyState === 'complete') {
clearInterval(stateCheck);
// document ready, start processing UI
onLoad();
}
}, 100);
});
setTimeout(function(){h.appendChild(l)},50);
});
setTimeout(function(){h.appendChild(l)},50);
</script>
<link rel="stylesheet" href="simple.css">
</head>
<body>
<div id="cv" class="overlay">Loading WLED UI...</div>
<noscript><div class="overlay" style="opacity:1;">Sorry, WLED UI needs JavaScript!</div></noscript>
<div id="bg"></div>
<div class="wrapper" id="top">
<div class="tab top">
<div class="btnwrap">
<button id="buttonPower" onclick="togglePower()"><i class="icons">&#xe08f;</i><p class="tab-label">Power</p></button>
<button id="buttonI" onclick="toggleInfo()"><i class="icons">&#xe066;</i><p class="tab-label">Info</p></button>
<button id="buttonNodes" onclick="toggleNodes()"><i class="icons">&#xe22d;</i><p class="tab-label">Nodes</p></button></div>
<button onclick="window.location.href='/settings';"><i class="icons">&#xe0a2;</i><p class="tab-label">Config</p></button>
<button id="buttonCP" onclick="tglCP()"><i class="icons">&#xe2b3;</i><p class="tab-label">Expand</p></button>
<!--button id="buttonBri" onclick="tglBri()"><i class="icons">&#xe2a6;</i><p class="tab-label">Brightness</p></button-->
</div>
<div id="briwrap">
<p class="label hd">Global brightness</p>
<div class="il">
<i class="icons slider-icon" onclick="tglTheme()">&#xe2a6;</i>
<div class="sliderwrap il">
<input id="sliderBri" onchange="setBri()" oninput="updateTrail(this)" max="255" min="1" type="range" value="128" />
<div class="sliderdisplay"></div>
</div>
<output class="sliderbubble"></output>
</div>
</div>
</div>
</div>
<div class ="container">
<div class="tabcontent">
<div id="QuickLoad" class="center">
<p class="label h">Quick Load</p>
<div id="pql"></div>
</div>
<div id="QCS" class="center">
<p class="label h">Solid color</p>
<div id="qcs-w" class="center">
<div class="qcs" onclick="pC('#ff0000');" title="Red" style="background-color:#ff0000;"></div>
<div class="qcs" onclick="pC('#ffa000');" title="Orange" style="background-color:#ffa000;"></div>
<div class="qcs" onclick="pC('#ffc800');" title="Yellow" style="background-color:#ffc800;"></div>
<div class="qcs" onclick="pC('#ffe0a0');" title="Warm White" style="background-color:#ffe0a0;"></div>
<div class="qcs" onclick="pC('#ffffff');" title="White" style="background-color:#ffffff;"></div>
<div class="qcs qcsb" onclick="pC('#000000');" title="Black" style="background-color:#000000;"></div><br>
<div class="qcs" onclick="pC('#ff00ff');" title="Pink" style="background-color:#ff00ff;"></div>
<div class="qcs" onclick="pC('#0000ff');" title="Blue" style="background-color:#0000ff;"></div>
<div class="qcs" onclick="pC('#00ffc8');" title="Cyan" style="background-color:#00ffc8;"></div>
<div class="qcs" onclick="pC('#08ff00');" title="Green" style="background-color:#08ff00;"></div>
<div class="qcs" onclick="pC('rnd');" title="Random" style="background:linear-gradient(to right, red, orange, yellow, green, blue, purple);transform: translateY(-11px);">R</div>
</div>
</div>
<div id="picker" class="center"></div>
<div id="Colors" class="center">
<div id="vwrap">
<!--p class="label h">Value</p-->
<div class="sliderwrap il">
<input id="sliderV" class="noslide" oninput="fromV()" onchange="setColor(0)" max="100" min="0" type="range" value="100" step="any" />
<div class="sliderdisplay"></div>
</div><br>
</div>
<div id="kwrap">
<!--p class="label h">Temperature</p-->
<div class="sliderwrap il">
<input id="sliderK" class="noslide" oninput="fromK()" onchange="setColor(0)" max="10091" min="1900" type="range" value="6550" />
<div class="sliderdisplay"></div>
</div>
</div>
<div id="rgbwrap" class="center">
<p class="label h">RGB channels</p>
<div id="rwrap" class="il">
<div class="sliderwrap il">
<input id="sliderR" class="noslide" onchange="fromRgb()" max="255" min="0" type="range" value="128" />
<div class="sliderdisplay"></div>
</div>
</div><br>
<div id="gwrap" class="il">
<div class="sliderwrap il">
<input id="sliderG" class="noslide" onchange="fromRgb()" max="255" min="0" type="range" value="128" />
<div class="sliderdisplay"></div>
</div>
</div><br>
<div id="bwrap" class="il">
<div class="sliderwrap il">
<input id="sliderB" class="noslide" onchange="fromRgb()" max="255" min="0" type="range" value="128" />
<div class="sliderdisplay"></div>
</div>
</div><br>
</div>
<div id="wwrap" class="center">
<p class="label h">White channel</p>
<div class="sliderwrap il">
<input id="sliderW" class="noslide" onchange="setColor(0)" max="255" min="0" type="range" value="128" />
<div class="sliderdisplay"></div>
</div>
</div>
<div id="wbal">
<p class="label h">White balance</p>
<div class="sliderwrap il">
<input id="sliderA" class="noslide" onchange="setBalance(this.value)" max="255" min="0" type="range" value="128" />
<div class="sliderdisplay"></div>
</div>
</div>
</div>
<div id="Slots" class="center">
<p class="label h">Color slots</p>
<div id="csl" class="center" style="display: none;">
<button class="xxs btn" onclick="selectSlot(0);">1</button>
<button class="xxs btn" onclick="selectSlot(1);">2</button>
<button class="xxs btn" onclick="selectSlot(2);">3</button>
</div>
</div>
<div id="Segments" class="center">
<div id="segcont"></div>
</div>
<div id="Presets" class="center">
<p class="label h">Presets</p>
<div class="fnd">
<input type="text" class="fnd" placeholder="Search" oninput="search(this,'pcont')" onfocus="search(this)" />
<i class="icons clear-icon" onclick="clean(this);">&#xe38f;</i>
<i class="icons search-icon">&#xe0a1;</i>
</div>
<div id="pcont" class="list"></div>
</div>
<div id="Effects" class="center">
<p class="label h">Effect</p>
<div title="Effect speed">
<i class="icons slider-icon">&#xe325;</i>
<div class="sliderwrap il">
<input id="sliderSpeed" onchange="setSpeed()" oninput="updateTrail(this)" max="255" min="0" type="range" value="128" />
<div class="sliderdisplay"></div>
</div>
<output class="sliderbubble"></output>
</div>
<div title="Effect intensity">
<i class="icons slider-icon" onclick="tglLabels()">&#xe409;</i>
<div class="sliderwrap il">
<input id="sliderIntensity" onchange="setIntensity()" oninput="updateTrail(this)" max="255" min="0" type="range" value="128" />
<div class="sliderdisplay"></div>
</div>
<output class="sliderbubble"></output>
</div>
<div style="padding-bottom:20px;">
<div onclick="tglFxDropdown()" class="c btn" id="fxBtn"><i class="icons">&#xe0e8;</i> Solid</div>
<div onclick="tglPalDropdown()" class="c btn" id="palBtn"><i class="icons">&#xe2b3;</i>Default</div>
<div id="fxDropdown" class="dd-content">
<div class="fnd">
<input type="text" class="fnd" placeholder="Search" oninput="search(this,'fxlist')" onfocus="search(this)" />
<i class="icons clear-icon" onclick="clean(this);">&#xe38f;</i>
<i class="icons search-icon">&#xe0a1;</i>
</div>
<div id="fxlist" class="list">
<div class="lstI" data-id="0" onClick="setEffect(0)"><a href="#0" onClick="setEffect(0)">Solid</a></div>
</div>
</div>
<div id="palDropdown" class="dd-content">
<div class="fnd">
<input type="text" class="fnd" placeholder="Search" oninput="search(this,'pallist')" onfocus="search(this)" />
<i class="icons clear-icon" onclick="clean(this);">&#xe38f;</i>
<i class="icons search-icon">&#xe0a1;</i>
</div>
<div id="pallist" class="list">
<div class="lstI" data-id="0" onClick="setPalette(0)"><a href="#0" onClick="setPalette(0)">Default</a><div class="lstIprev"></div></div>
</div>
</div>
<br>
</div>
</div>
</div>
</div>
<div id="connind"></div>
<div id="toast"></div>
<div id="namelabel" onclick="toggleNodes()"></div>
<div id="info" class="modal">
<div id="imgw">
<img class="wi" alt="" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB0AAAAFCAYAAAC5Fuf5AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABbSURBVChTlY9bDoAwDMNW7n9nwCipytQN4Z8tbrTHmDmF4oPzyldwRqp1SSdnV/NuZuzqerAByxXznBw3igkeFEfXyUuhK/yFM0CxJfyqXZEOc6/Sr9/bf7uIC5Nwd7orMvAPAAAAAElFTkSuQmCC" />
</div><br>
<div id="kv">Loading...</div><br>
<div>
<button class="btn" onclick="requestJson()">Refresh</button>
<button class="btn" onclick="toggleInfo()">Close Info</button>
<button class="btn" onclick="toggleNodes()">Instance List</button>
<button class="btn" id="resetbtn" onclick="cnfReset()">Reboot WLED</button>
</div>
<span class="h">Made with <span id="heart">&#10084;&#xFE0E;</span> by Aircoookie and the <a href="https://wled.discourse.group/" target="_blank">WLED community</a></span>
</div>
<div id="nodes" class="modal">
<div id="ndlt">WLED instances</div>
<div id="kn">Loading...</div><br>
<div>
<button class="btn" onclick="loadNodes()">Refresh</button>
<button class="btn" onclick="toggleNodes()">Close list</button>
</div>
</div>
<i id="roverstar" class="icons huge" onclick="setLor(0)">&#xe410;</i><br>
<script src="simple.js"></script>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -650,6 +650,7 @@ void serializeInfo(JsonObject root)
root[F("name")] = serverDescription;
root[F("udpport")] = udpPort;
root[F("simplifiedui")] = simplifiedUI;
root["live"] = (bool)realtimeMode;
root[F("liveseg")] = useMainSegmentOnly ? strip.getMainSegmentId() : -1; // if using main segment only for live

View File

@ -303,13 +303,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
{
strlcpy(serverDescription, request->arg(F("DS")).c_str(), 33);
//syncToggleReceive = request->hasArg(F("ST"));
#ifdef WLED_ENABLE_SIMPLE_UI
if (simplifiedUI ^ request->hasArg(F("SU"))) {
// UI selection changed, invalidate browser cache
cacheInvalidate++;
}
simplifiedUI = request->hasArg(F("SU"));
#endif
DEBUG_PRINTLN(F("Enumerating ledmaps"));
enumerateLedmaps();
DEBUG_PRINTLN(F("Loading custom palettes"));

View File

@ -365,7 +365,7 @@ WLED_GLOBAL char serverDescription[33] _INIT(SERVERNAME); // use predefined nam
#endif
//WLED_GLOBAL bool syncToggleReceive _INIT(false); // UIs which only have a single button for sync should toggle send+receive if this is true, only send otherwise
WLED_GLOBAL bool simplifiedUI _INIT(false); // enable simplified UI
WLED_GLOBAL byte cacheInvalidate _INIT(0); // used to invalidate browser cache when switching from regular to simplified UI
WLED_GLOBAL byte cacheInvalidate _INIT(0); // used to invalidate browser cache
// Sync CONFIG
WLED_GLOBAL NodesMap Nodes;

View File

@ -1,9 +1,6 @@
#include "wled.h"
#include "html_ui.h"
#ifdef WLED_ENABLE_SIMPLE_UI
#include "html_simple.h"
#endif
#include "html_settings.h"
#include "html_other.h"
#ifdef WLED_ENABLE_PIXART
@ -253,17 +250,6 @@ void initServer()
size_t len, bool final) {handleUpload(request, filename, index, data, len, final);}
);
#ifdef WLED_ENABLE_SIMPLE_UI
server.on("/simple.htm", HTTP_GET, [](AsyncWebServerRequest *request){
if (handleFileRead(request, "/simple.htm")) return;
if (handleIfNoneMatchCacheHeader(request)) return;
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", PAGE_simple, PAGE_simple_L);
response->addHeader(FPSTR(s_content_enc),"gzip");
setStaticContentCacheHeaders(response);
request->send(response);
});
#endif
server.on("/iro.js", HTTP_GET, [](AsyncWebServerRequest *request){
AsyncWebServerResponse *response = request->beginResponse_P(200, "application/javascript", iroJs, iroJs_length);
response->addHeader(FPSTR(s_content_enc),"gzip");
@ -451,13 +437,7 @@ void serveIndex(AsyncWebServerRequest* request)
if (handleIfNoneMatchCacheHeader(request)) return;
AsyncWebServerResponse *response;
#ifdef WLED_ENABLE_SIMPLE_UI
if (simplifiedUI)
response = request->beginResponse_P(200, "text/html", PAGE_simple, PAGE_simple_L);
else
#endif
response = request->beginResponse_P(200, "text/html", PAGE_index, PAGE_index_L);
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", PAGE_index, PAGE_index_L);
response->addHeader(FPSTR(s_content_enc),"gzip");
setStaticContentCacheHeaders(response);

View File

@ -475,11 +475,7 @@ void getSettingsJS(byte subPage, char* dest)
{
sappends('s',SET_F("DS"),serverDescription);
//sappend('c',SET_F("ST"),syncToggleReceive);
#ifdef WLED_ENABLE_SIMPLE_UI
sappend('c',SET_F("SU"),simplifiedUI);
#else
oappend(SET_F("toggle('Simple');")); // hide Simplified UI settings
#endif
}
if (subPage == SUBPAGE_SYNC)