fix(ui): header power switch shows the available action, not both states

Replaces the segmented An/Aus toggle with a single button that always
shows the action a click would perform: printer on -> button offers
"Aus" (red), printer off -> button offers "An" (green). Matches how
the physical switch actually works (only one direction is ever
possible at a time) instead of presenting two options where one is
always a no-op.

_headerPowerState tracks the last known actual state so
toggleHeaderPower() knows which action to send; unrelated printer-tab
button/other UI untouched.
This commit is contained in:
2026-08-24 19:09:24 +02:00
parent 13f84979fe
commit 0a23d4bd1c
3 changed files with 45 additions and 29 deletions

View File

@ -339,39 +339,54 @@ function initPrinters(){
// active printer via the dropdown re-evaluates has_power_control for the
// newly active one instead of a fixed dashboard card tied to whichever
// printer happened to be active on page load) ──
// Single button showing the action a click would perform (not the current
// state): printer on → button offers "Aus", printer off → button offers
// "An". _headerPowerState holds the last known actual state ('on'/'off'/
// null=unknown) so toggleHeaderPower() knows which action to send.
var _headerPowerState=null;
function _initHeaderPower(){
var wrap=document.getElementById('h-power-wrap');
if(!wrap)return;
if(!_activePrinter||!_activePrinter.has_power_control){wrap.style.display='none';return;}
wrap.style.display='flex';
var btn=document.getElementById('h-power-btn');
if(!btn)return;
if(!_activePrinter||!_activePrinter.has_power_control){btn.style.display='none';return;}
btn.style.display='';
_refreshHeaderPower();
}
function _applyHeaderPowerState(state){
_headerPowerState=state;
var btn=document.getElementById('h-power-btn'), lbl=document.getElementById('h-power-lbl');
if(!btn||!lbl)return;
if(state==='on'){
btn.classList.remove('h-power-can-on');btn.classList.add('h-power-can-off');
lbl.textContent=T.printers_power_off_short||'Aus';
}else if(state==='off'){
btn.classList.remove('h-power-can-off');btn.classList.add('h-power-can-on');
lbl.textContent=T.printers_power_on_short||'An';
}else{
btn.classList.remove('h-power-can-on','h-power-can-off');
lbl.textContent=T.printers_power_on_short||'An';
}
}
function _refreshHeaderPower(){
if(!_activePrinter||!_activePrinter.has_power_control)return;
var bridgeUrl=(_activePrinter.bridge_url||'').replace(/\/+$/,'');
fetch(bridgeUrl+'/kx/printers/'+encodeURIComponent(_activePrinter.id)+'/power-status',{signal:AbortSignal.timeout(5000)})
.then(function(r){return r.json()})
.then(function(d){
var onBtn=document.getElementById('h-power-on'), offBtn=document.getElementById('h-power-off');
if(!onBtn||!offBtn)return;
onBtn.classList.toggle('spd-active',d.state==='on');
offBtn.classList.toggle('spd-active',d.state==='off');
})
.catch(function(){/* status endpoint optional - toggle just stays neutral */});
.then(function(d){_applyHeaderPowerState(d.state==='on'||d.state==='off'?d.state:null);})
.catch(function(){/* status endpoint optional - button just stays neutral */});
}
function setHeaderPower(action){
function toggleHeaderPower(){
if(!_activePrinter)return;
// Unknown current state: default to "on" - turning an already-off switch
// on is harmless, whereas guessing "off" on a printer mid-print is not.
var action=_headerPowerState==='on'?'off':'on';
if(action==='off'&&!confirm(T.printers_power_off_confirm||'Turn printer power off? Make sure no print is running.'))return;
var onBtn=document.getElementById('h-power-on'), offBtn=document.getElementById('h-power-off');
if(onBtn)onBtn.style.opacity='0.5';
if(offBtn)offBtn.style.opacity='0.5';
var btn=document.getElementById('h-power-btn');
if(btn)btn.style.opacity='0.5';
post('/kx/printers/'+encodeURIComponent(_activePrinter.id)+'/power',{action:action}).then(function(){
if(onBtn)onBtn.style.opacity='1';
if(offBtn)offBtn.style.opacity='1';
if(btn)btn.style.opacity='1';
setTimeout(_refreshHeaderPower,1500);
}).catch(function(e){
if(onBtn)onBtn.style.opacity='1';
if(offBtn)offBtn.style.opacity='1';
if(btn)btn.style.opacity='1';
clog('Power-Fehler: '+e,'msg-err');
});
}
@ -464,8 +479,6 @@ function applyLang(){
setText('d-card-temps',T.card_temps);
setText('d-card-lightfan',T.card_light_fan);
setText('d-card-speed',T.card_speed);
setText('h-power-lbl-on',T.printers_power_on_short||'An');
setText('h-power-lbl-off',T.printers_power_off_short||'Aus');
setText('d-card-cam',T.card_cam);
setText('d-card-ams',T.panel_ams_title);
setText('d-lbl-elapsed',T.lbl_elapsed);

View File

@ -35,10 +35,9 @@
</div>
<div id="h-pname-single" class="hname">Anycubic Kobra X</div>
<span id="h-version" style="font-size:11px;opacity:.5;margin-left:6px"></span>
<div id="h-power-wrap" style="display:none;margin-left:10px;gap:2px;background:var(--raised);border:1px solid var(--border);border-radius:6px;padding:2px" title="Steckdose">
<button id="h-power-on" class="h-power-btn" onclick="setHeaderPower('on')">🟢 <span id="h-power-lbl-on">An</span></button>
<button id="h-power-off" class="h-power-btn" onclick="setHeaderPower('off')">🔴 <span id="h-power-lbl-off">Aus</span></button>
</div>
<button id="h-power-btn" class="h-power-btn" style="display:none;margin-left:10px" onclick="toggleHeaderPower()" title="Steckdose">
🔌 <span id="h-power-lbl">An</span>
</button>
<div class="hbadge" id="h-badge"><span class="dot"></span><span id="h-state">Standby</span></div>
<button class="theme-btn" onclick="toggleTheme()">☀ / ☾</button>
<button class="theme-btn" onclick="showPanel('settings')" id="settings-btn" title="Einstellungen"></button>

View File

@ -202,10 +202,14 @@ main{flex:1;overflow-y:auto;padding:20px}
.spd-btn .spd-icon{font-size:22px}
.spd-bar{height:4px;border-radius:2px;background:var(--border);margin-top:10px;overflow:hidden}
.spd-bar-fill{height:100%;border-radius:2px;background:linear-gradient(90deg,var(--accent2),var(--accent));transition:width .3s}
.h-power-btn{border:1.5px solid transparent;background:none;color:var(--txt2);
border-radius:5px;padding:3px 8px;font-size:12px;font-weight:600;cursor:pointer;transition:all .15s}
.h-power-btn:hover{color:var(--txt)}
.h-power-btn.spd-active{border-color:var(--accent);background:rgba(0,200,255,.12);color:var(--accent)}
.h-power-btn{border:1.5px solid var(--border);background:var(--raised);color:var(--txt2);
border-radius:6px;padding:4px 10px;font-size:12px;font-weight:600;cursor:pointer;transition:all .15s}
.h-power-btn:hover{opacity:.85}
/* Shows the action a click would perform, not the current state - green
"An" while the printer is off (click turns it on), red "Aus" while it's
on (click turns it off). */
.h-power-btn.h-power-can-on{border-color:var(--ok);background:rgba(76,222,128,.12);color:var(--ok)}
.h-power-btn.h-power-can-off{border-color:var(--err);background:rgba(255,77,109,.12);color:var(--err)}
/* ── TIME CARDS ── */
.time-grid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px;margin-top:8px}