Replace Kochmodus slider with direct toggle button in recipe header & fix Apple keep-awake
This commit is contained in:
+144
-126
@@ -2342,48 +2342,160 @@ body.cook-mode-on .recipe-page {
|
||||
transition: border 0.25s ease, box-shadow 0.25s ease;
|
||||
}
|
||||
|
||||
body.cook-mode-on .recipe-page::before {
|
||||
content: "👨🍳 Kochmodus aktiv 💡";
|
||||
/* Kochmodus Toggle Button oben rechts im Rezept */
|
||||
.cookmode-toggle-btn {
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
right: 18px;
|
||||
background: var(--tannengruen);
|
||||
color: var(--creme);
|
||||
font-family: var(--font-hand);
|
||||
font-size: 1.15rem;
|
||||
font-weight: 700;
|
||||
padding: 3px 14px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
padding: 5px 14px;
|
||||
border-radius: 20px;
|
||||
border: 2px solid var(--creme);
|
||||
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.25);
|
||||
z-index: 15;
|
||||
pointer-events: none;
|
||||
animation: cookmode-badge-pop 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border: 1.5px solid rgba(30, 77, 59, 0.35);
|
||||
color: var(--tannengruen);
|
||||
font-family: var(--font-hand);
|
||||
font-size: 1.05rem;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
z-index: 25;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
|
||||
transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
user-select: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
@keyframes cookmode-badge-pop {
|
||||
0% { transform: scale(0.85); opacity: 0; }
|
||||
100% { transform: scale(1); opacity: 1; }
|
||||
.cookmode-toggle-btn:hover {
|
||||
background: #FFFFFF;
|
||||
border-color: var(--tannengruen);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.cookmode-toggle-btn:active {
|
||||
transform: translateY(1px);
|
||||
}
|
||||
|
||||
.cookmode-btn-icon {
|
||||
font-size: 1.2rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.cookmode-btn-title {
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
|
||||
.cookmode-btn-badge {
|
||||
font-size: 0.72rem;
|
||||
font-weight: 700;
|
||||
padding: 2px 7px;
|
||||
border-radius: 10px;
|
||||
background: rgba(30, 77, 59, 0.08);
|
||||
color: #555;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.cookmode-btn-bulb {
|
||||
font-size: 1.05rem;
|
||||
filter: grayscale(100%);
|
||||
opacity: 0.45;
|
||||
transition: all 0.25s ease;
|
||||
}
|
||||
|
||||
/* Active State des Toggle Buttons */
|
||||
.cookmode-toggle-btn.is-active,
|
||||
body.cook-mode-on .cookmode-toggle-btn {
|
||||
background: var(--tannengruen);
|
||||
color: var(--creme);
|
||||
border: 2px solid var(--gold);
|
||||
box-shadow: 0 4px 14px rgba(30, 77, 59, 0.4), 0 0 10px rgba(212, 160, 23, 0.4);
|
||||
}
|
||||
|
||||
.cookmode-toggle-btn.is-active .cookmode-btn-badge,
|
||||
body.cook-mode-on .cookmode-toggle-btn .cookmode-btn-badge {
|
||||
background: rgba(255, 255, 255, 0.22);
|
||||
color: var(--creme);
|
||||
}
|
||||
|
||||
.cookmode-toggle-btn.is-active .cookmode-btn-bulb,
|
||||
body.cook-mode-on .cookmode-toggle-btn .cookmode-btn-bulb {
|
||||
filter: grayscale(0%);
|
||||
opacity: 1;
|
||||
animation: cookmode-bulb-pulse 1.4s ease-in-out infinite alternate;
|
||||
}
|
||||
|
||||
@keyframes cookmode-bulb-pulse {
|
||||
0% { transform: scale(1); filter: drop-shadow(0 0 1px #FFD700); }
|
||||
100% { transform: scale(1.2); filter: drop-shadow(0 0 6px #FFA500); }
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
body.cook-mode-on .recipe-page::before {
|
||||
.cookmode-toggle-btn {
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
font-size: 0.95rem;
|
||||
padding: 2px 10px;
|
||||
font-size: 0.92rem;
|
||||
padding: 4px 10px;
|
||||
gap: 5px;
|
||||
}
|
||||
.cookmode-btn-icon {
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
.cookmode-btn-title {
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Badge Pill für Desktop & Mobile Menü */
|
||||
.cb-badge-pill {
|
||||
font-size: 0.72rem;
|
||||
font-weight: 700;
|
||||
padding: 2px 7px;
|
||||
border-radius: 10px;
|
||||
background: rgba(0, 0, 0, 0.08);
|
||||
color: #555;
|
||||
transition: all 0.2s ease;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Desktop Navigation Button */
|
||||
.cb-nav-cookmode-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.cb-nav-cookmode-btn.is-active,
|
||||
body.cook-mode-on .cb-nav-cookmode-btn {
|
||||
background: var(--tannengruen);
|
||||
color: var(--creme);
|
||||
border-color: var(--gold);
|
||||
box-shadow: 0 0 8px rgba(212, 160, 23, 0.4);
|
||||
}
|
||||
|
||||
.cb-nav-cookmode-btn.is-active .cb-badge-pill,
|
||||
body.cook-mode-on .cb-nav-cookmode-btn .cb-badge-pill {
|
||||
background: var(--gold);
|
||||
color: var(--schwarz);
|
||||
}
|
||||
|
||||
/* Mobile Kebab Kochmodus Row */
|
||||
.cb-mobile-cookmode-item {
|
||||
width: 100%;
|
||||
border: none;
|
||||
background: rgba(30, 77, 59, 0.05);
|
||||
border-bottom: 1.5px solid rgba(0, 0, 0, 0.08);
|
||||
display: flex !important;
|
||||
justify-content: space-between !important;
|
||||
align-items: center !important;
|
||||
padding: 10px 16px !important;
|
||||
background: rgba(30, 77, 59, 0.05);
|
||||
border-bottom: 1.5px solid rgba(0, 0, 0, 0.08);
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
user-select: none;
|
||||
transition: background 0.15s ease;
|
||||
}
|
||||
@@ -2393,11 +2505,18 @@ body.cook-mode-on .recipe-page::before {
|
||||
background: rgba(30, 77, 59, 0.12);
|
||||
}
|
||||
|
||||
.cb-mobile-cookmode-item.is-active,
|
||||
body.cook-mode-on .cb-mobile-cookmode-item {
|
||||
background: #FFFDF0;
|
||||
border-bottom-color: #d4c165;
|
||||
}
|
||||
|
||||
.cb-mobile-cookmode-item.is-active .cb-badge-pill,
|
||||
body.cook-mode-on .cb-mobile-cookmode-item .cb-badge-pill {
|
||||
background: var(--tannengruen);
|
||||
color: var(--creme);
|
||||
}
|
||||
|
||||
.cookmode-item-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -2416,7 +2535,7 @@ body.cook-mode-on .cb-mobile-cookmode-item {
|
||||
|
||||
.cookmode-text-box .cookmode-title {
|
||||
font-family: var(--font-hand);
|
||||
font-size: 1.2rem;
|
||||
font-size: 1.15rem;
|
||||
font-weight: 700;
|
||||
color: var(--tannengruen);
|
||||
line-height: 1.1;
|
||||
@@ -2432,106 +2551,6 @@ body.cook-mode-on .cookmode-text-box .cookmode-status-text {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Custom Schieberegler (Slider Switch) */
|
||||
.cb-switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 52px;
|
||||
height: 28px;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cb-switch input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.cb-slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
inset: 0;
|
||||
background-color: #d0c9be;
|
||||
transition: .25s ease;
|
||||
border-radius: 28px;
|
||||
box-shadow: inset 0 1px 3px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.cb-slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
left: 3px;
|
||||
bottom: 3px;
|
||||
background-color: white;
|
||||
transition: .25s ease;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.25);
|
||||
}
|
||||
|
||||
.cb-switch input:checked + .cb-slider {
|
||||
background-color: var(--tannengruen);
|
||||
}
|
||||
|
||||
.cb-switch input:checked + .cb-slider:before {
|
||||
transform: translateX(24px);
|
||||
}
|
||||
|
||||
.cb-switch:focus-within .cb-slider {
|
||||
outline: 2px solid var(--tannengruen);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.cb-switch-sm {
|
||||
width: 44px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.cb-switch-sm .cb-slider:before {
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
left: 3px;
|
||||
bottom: 3px;
|
||||
}
|
||||
|
||||
.cb-switch-sm input:checked + .cb-slider:before {
|
||||
transform: translateX(20px);
|
||||
}
|
||||
|
||||
.cookmode-badge {
|
||||
font-size: 0.8rem;
|
||||
font-weight: 700;
|
||||
padding: 3px 9px;
|
||||
border-radius: 12px;
|
||||
background: rgba(34, 34, 34, 0.08);
|
||||
color: #666;
|
||||
transition: all 0.25s ease;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
body.cook-mode-on .cookmode-badge {
|
||||
background: var(--tannengruen);
|
||||
color: #FFFFFF;
|
||||
box-shadow: 0 0 10px rgba(30, 77, 59, 0.35);
|
||||
}
|
||||
|
||||
/* Compact switch for desktop nav */
|
||||
.cb-nav-cookmode-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
padding: 4px 10px;
|
||||
border-radius: 20px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
color: var(--creme);
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Interactive ingredient checkoffs */
|
||||
.ingredients-list li.ingredient-item {
|
||||
cursor: pointer;
|
||||
@@ -2718,11 +2737,10 @@ body.cook-mode-on .cookmode-badge {
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
body.cook-mode-on .recipe-page::before {
|
||||
display: none !important;
|
||||
}
|
||||
.cookmode-toggle-btn,
|
||||
.cb-nav-cookmode-btn,
|
||||
.cb-mobile-cookmode-item,
|
||||
.recipe-cookmode-banner,
|
||||
.cb-nav-cookmode-toggle,
|
||||
.step-done-check,
|
||||
.no-print {
|
||||
display: none !important;
|
||||
|
||||
Binary file not shown.
@@ -18,13 +18,11 @@
|
||||
|
||||
<!-- Desktop Navigation -->
|
||||
<div class="cb-nav-actions desktop-nav-actions">
|
||||
<div class="cb-nav-cookmode-toggle no-print" onclick="toggleCookingModeClick(event)" title="Kochmodus: Verhindert automatisches Sperren des Bildschirms" style="cursor: pointer;">
|
||||
<span>👨🍳 Kochmodus</span>
|
||||
<label class="cb-switch cb-switch-sm" onclick="event.stopPropagation()">
|
||||
<input type="checkbox" id="cook-mode-toggle-nav" class="cook-mode-switch-input" onchange="toggleCookingMode(this.checked)">
|
||||
<span class="cb-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<button type="button" id="cookmode-nav-btn" class="cb-btn cb-btn-outline cb-nav-cookmode-btn no-print" onclick="toggleCookingMode()" title="Kochmodus: Hält das Display beim Kochen aktiv">
|
||||
<span class="cookmode-nav-icon">👨🍳</span>
|
||||
<span>Kochmodus</span>
|
||||
<span id="cookmode-nav-badge" class="cb-badge-pill">Aus</span>
|
||||
</button>
|
||||
{% if not is_shared %}
|
||||
<a href="/cookbook" class="cb-btn cb-btn-outline">
|
||||
<span>📖</span> <span>Alle Rezepte</span>
|
||||
@@ -52,19 +50,16 @@
|
||||
<span>⋮</span>
|
||||
</button>
|
||||
<div id="cb-mobile-menu" class="cb-mobile-dropdown">
|
||||
<div class="cb-mobile-item cb-mobile-cookmode-item" onclick="toggleCookingModeClick(event)" title="Kochmodus: Verhindert automatisches Sperren des Bildschirms">
|
||||
<button type="button" id="cookmode-mobile-btn" class="cb-mobile-item cb-mobile-cookmode-item" onclick="toggleCookingMode()" title="Kochmodus: Hält das Display beim Kochen aktiv">
|
||||
<div class="cookmode-item-left">
|
||||
<span class="cookmode-icon">👨🍳</span>
|
||||
<div class="cookmode-text-box">
|
||||
<span class="cookmode-title">Kochmodus</span>
|
||||
<span class="cookmode-title">Kochmodus (Display bleibt an)</span>
|
||||
<span class="cookmode-status-text" id="cookmode-status-mobile">Display bleibt an</span>
|
||||
</div>
|
||||
</div>
|
||||
<label class="cb-switch cb-switch-sm" onclick="event.stopPropagation()">
|
||||
<input type="checkbox" id="cook-mode-toggle-mobile" class="cook-mode-switch-input" onchange="toggleCookingMode(this.checked)">
|
||||
<span class="cb-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<span id="cookmode-mobile-badge" class="cb-badge-pill">Aus</span>
|
||||
</button>
|
||||
<hr class="cb-mobile-divider">
|
||||
{% if not is_shared %}
|
||||
<button type="button" onclick="openShareModal()" class="cb-mobile-item">
|
||||
@@ -117,14 +112,17 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="recipe-cookmode-right">
|
||||
<label class="cb-switch" for="cook-mode-toggle" title="Kochmodus umschalten">
|
||||
<input type="checkbox" id="cook-mode-toggle" class="cook-mode-switch-input" onchange="toggleCookingMode(this.checked)">
|
||||
<span class="cb-slider"></span>
|
||||
</label>
|
||||
<span id="cook-mode-badge" class="cookmode-badge">Aus</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- KOCHMODUS TOGGLE BUTTON (Oben rechts auf der Rezeptseite) -->
|
||||
<button type="button"
|
||||
id="cookmode-recipe-btn"
|
||||
class="cookmode-toggle-btn no-print"
|
||||
onclick="toggleCookingMode()"
|
||||
title="Kochmodus umschalten: Hält das Display beim Kochen aktiv">
|
||||
<span class="cookmode-btn-icon">👨🍳</span>
|
||||
<span class="cookmode-btn-title">Kochmodus</span>
|
||||
<span id="cookmode-recipe-badge" class="cookmode-btn-badge">Aus</span>
|
||||
<span class="cookmode-btn-bulb">💡</span>
|
||||
</button>
|
||||
|
||||
<!-- Header (Ohne Kapitelangabe & ohne Quelle im Titel) -->
|
||||
<header class="recipe-header">
|
||||
@@ -534,7 +532,19 @@
|
||||
|
||||
|
||||
|
||||
</main>
|
||||
<!-- Apple/iOS Safari & PWA Keep-Awake Video Element -->
|
||||
<video id="cookmode-keepawake-video"
|
||||
playsinline
|
||||
webkit-playsinline
|
||||
loop
|
||||
muted
|
||||
preload="auto"
|
||||
aria-hidden="true"
|
||||
style="position: fixed; right: 0; bottom: 0; width: 1px; height: 1px; opacity: 0.01; pointer-events: none; z-index: -9999;"
|
||||
src="/static/media/cookmode_nosleep.mp4">
|
||||
</video>
|
||||
|
||||
</main>
|
||||
|
||||
<script>
|
||||
// ==========================================
|
||||
@@ -554,130 +564,166 @@
|
||||
});
|
||||
|
||||
// ==========================================
|
||||
// KOCHMODUS: SCREEN WAKE LOCK & NOSLEEP VIDEO FALLBACK
|
||||
// KOCHMODUS: SCREEN WAKE LOCK & iOS VIDEO KEEP-AWAKE
|
||||
// ==========================================
|
||||
let wakeLockSentinel = null;
|
||||
let isCookModeActive = false;
|
||||
|
||||
// 765-Byte stummes H.264 MP4 als universeller Fallback für iOS Safari / Stromsparmodus
|
||||
const NO_SLEEP_MP4 = "data:video/mp4;base64,AAAAHGZ0eXBtcDQyAAAAAG1wNDJpc29tYXZjMQAAADd2bW92AAAAcG12aGQAAAAA1nEwANZxMADAAMAAA+gAAAEAAAEAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAABidHJhawAAAFx0a2hkAAAAAdZxMADWcTAAAAABAAAAAAAAB+gAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAACbWRpYQAAACRtaGRyAAAAAAAAAAAAAAAAAAB+gAAA+gB4AAAAAAA1aGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAF8bWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADGR1cmwAAAABAAAARXN0YmwAAABTc3RzZAAAAAAAAAABAAAAR2F2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAHgAeAEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//+AAAAAMmF2Y0MBQsAP/v/4AAQcK9AAACWAAAEAAAA8AAAeJAAAAABhdmMxAAAAAAAAAAEAACAAHgAeAEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//+AAAAAFHN0dHMAAAAAAAAAAQAAAAEAAAAAAACAAAAAc3RzYwAAAAAAAAABAAAAAQAAAAEAAAABAAAAJHN0c3oAAAAAAAAAAAAAAAEAAABkAAAAAAAQc3RjbwAAAAAAAAABAAAAMAAAADBtZGF0AAAAGBAPAAABuQA1AP/wCAAAAGAAAAAAAAAA==";
|
||||
// Video Keep-Awake für iOS Safari / Stromsparmodus / PWA
|
||||
function getKeepAwakeVideo() {
|
||||
return document.getElementById('cookmode-keepawake-video');
|
||||
}
|
||||
|
||||
function getNoSleepVideo() {
|
||||
let v = document.getElementById('cookmode-nosleep-video');
|
||||
if (!v) {
|
||||
v = document.createElement('video');
|
||||
v.id = 'cookmode-nosleep-video';
|
||||
v.setAttribute('playsinline', '');
|
||||
v.setAttribute('webkit-playsinline', '');
|
||||
v.setAttribute('loop', '');
|
||||
v.setAttribute('muted', '');
|
||||
v.muted = true;
|
||||
v.style.cssText = 'position:fixed;width:1px;height:1px;top:-100px;left:-100px;opacity:0.001;pointer-events:none;';
|
||||
v.src = NO_SLEEP_MP4;
|
||||
document.body.appendChild(v);
|
||||
}
|
||||
return v;
|
||||
// Video-Loop Handler gegen AVPlayer Sleep-Suspension
|
||||
function setupVideoLoop(v) {
|
||||
if (!v || v._hasLoopListener) return;
|
||||
v._hasLoopListener = true;
|
||||
v.addEventListener('timeupdate', () => {
|
||||
if (v.currentTime > 0.5) {
|
||||
v.currentTime = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function acquireKeepAwake() {
|
||||
let success = false;
|
||||
// 1. Wake Lock API (Standard für moderne Browser)
|
||||
if ('wakeLock' in navigator) {
|
||||
let wakeLockSuccess = false;
|
||||
|
||||
// 1. Native Screen Wake Lock API (Safari iOS 16.4+, Chrome, Edge)
|
||||
if ('wakeLock' in navigator && navigator.wakeLock && typeof navigator.wakeLock.request === 'function') {
|
||||
try {
|
||||
wakeLockSentinel = await navigator.wakeLock.request('screen');
|
||||
wakeLockSentinel.addEventListener('release', () => {
|
||||
wakeLockSentinel = null;
|
||||
if (isCookModeActive && document.visibilityState === 'visible') {
|
||||
acquireKeepAwake();
|
||||
}
|
||||
});
|
||||
success = true;
|
||||
wakeLockSuccess = true;
|
||||
} catch (err) {
|
||||
console.warn('Wake Lock API abgelehnt oder im Stromsparmodus:', err);
|
||||
console.warn('Screen WakeLock nicht verfügbar oder im Stromsparmodus:', err);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. NoSleep Video Fallback (Garantie für iOS Safari / Stromsparmodus)
|
||||
// 2. Video Keep-Awake Fallback (speziell für iOS Safari, iPadOS & Stromsparmodus)
|
||||
try {
|
||||
const v = getNoSleepVideo();
|
||||
if (v.paused) {
|
||||
const p = v.play();
|
||||
if (p && typeof p.then === 'function') {
|
||||
await p.catch(() => {});
|
||||
const v = getKeepAwakeVideo();
|
||||
if (v) {
|
||||
setupVideoLoop(v);
|
||||
v.muted = true;
|
||||
const playPromise = v.play();
|
||||
if (playPromise !== undefined && typeof playPromise.then === 'function') {
|
||||
await playPromise.catch(e => {
|
||||
console.warn('Video keep-awake play Fehler:', e);
|
||||
});
|
||||
}
|
||||
}
|
||||
success = true;
|
||||
} catch (e) {
|
||||
console.warn('NoSleep Video Fallback Fehler:', e);
|
||||
console.warn('Video Keep-Awake Fehler:', e);
|
||||
}
|
||||
|
||||
return success;
|
||||
return wakeLockSuccess;
|
||||
}
|
||||
|
||||
function releaseKeepAwake() {
|
||||
// 1. Release Wake Lock
|
||||
if (wakeLockSentinel !== null) {
|
||||
try { wakeLockSentinel.release(); } catch (e) {}
|
||||
wakeLockSentinel = null;
|
||||
}
|
||||
|
||||
// 2. Pause Video Keep-Awake
|
||||
try {
|
||||
const v = document.getElementById('cookmode-nosleep-video');
|
||||
const v = getKeepAwakeVideo();
|
||||
if (v && !v.paused) {
|
||||
v.pause();
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
async function toggleCookingMode(active) {
|
||||
isCookModeActive = active;
|
||||
function updateCookModeUI(active) {
|
||||
// Body-Klasse für aktiven Rahmen um das Rezept
|
||||
if (active) {
|
||||
document.body.classList.add('cook-mode-on');
|
||||
} else {
|
||||
document.body.classList.remove('cook-mode-on');
|
||||
}
|
||||
|
||||
// 1. Toggle Button oben rechts im Rezept
|
||||
const recipeBtn = document.getElementById('cookmode-recipe-btn');
|
||||
const recipeBadge = document.getElementById('cookmode-recipe-badge');
|
||||
if (recipeBtn) {
|
||||
if (active) {
|
||||
recipeBtn.classList.add('is-active');
|
||||
if (recipeBadge) recipeBadge.textContent = 'An';
|
||||
} else {
|
||||
recipeBtn.classList.remove('is-active');
|
||||
if (recipeBadge) recipeBadge.textContent = 'Aus';
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Desktop Nav Button
|
||||
const navBtn = document.getElementById('cookmode-nav-btn');
|
||||
const navBadge = document.getElementById('cookmode-nav-badge');
|
||||
if (navBtn) {
|
||||
if (active) {
|
||||
navBtn.classList.add('is-active');
|
||||
if (navBadge) navBadge.textContent = 'An 💡';
|
||||
} else {
|
||||
navBtn.classList.remove('is-active');
|
||||
if (navBadge) navBadge.textContent = 'Aus';
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Mobile Kebab Menü Item
|
||||
const mobileBtn = document.getElementById('cookmode-mobile-btn');
|
||||
const mobileBadge = document.getElementById('cookmode-mobile-badge');
|
||||
const mobileStatus = document.getElementById('cookmode-status-mobile');
|
||||
if (mobileBtn) {
|
||||
if (active) {
|
||||
mobileBtn.classList.add('is-active');
|
||||
if (mobileBadge) mobileBadge.textContent = 'An 💡';
|
||||
if (mobileStatus) mobileStatus.textContent = 'Aktiv 💡 (Display bleibt an)';
|
||||
} else {
|
||||
mobileBtn.classList.remove('is-active');
|
||||
if (mobileBadge) mobileBadge.textContent = 'Aus';
|
||||
if (mobileStatus) mobileStatus.textContent = 'Display bleibt an';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleCookingMode() {
|
||||
isCookModeActive = !isCookModeActive;
|
||||
try {
|
||||
localStorage.setItem('wtc_cookmode_active', active ? 'true' : 'false');
|
||||
localStorage.setItem('wtc_cookmode_active', isCookModeActive ? 'true' : 'false');
|
||||
} catch (e) {}
|
||||
|
||||
// Synchronisiere alle Schalter
|
||||
const switches = document.querySelectorAll('.cook-mode-switch-input');
|
||||
switches.forEach(sw => { sw.checked = active; });
|
||||
updateCookModeUI(isCookModeActive);
|
||||
|
||||
const statusText = document.getElementById('cookmode-status-mobile');
|
||||
|
||||
if (active) {
|
||||
if (isCookModeActive) {
|
||||
await acquireKeepAwake();
|
||||
document.body.classList.add('cook-mode-on');
|
||||
if (statusText) statusText.textContent = 'Aktiv 💡 (Display bleibt an)';
|
||||
showToast('✓ Kochmodus an: Display bleibt an 💡');
|
||||
showToast('✓ Kochmodus aktiv: Display bleibt an 💡');
|
||||
} else {
|
||||
releaseKeepAwake();
|
||||
document.body.classList.remove('cook-mode-on');
|
||||
if (statusText) statusText.textContent = 'Display bleibt an';
|
||||
showToast('Kochmodus ausgeschaltet');
|
||||
}
|
||||
}
|
||||
|
||||
function toggleCookingModeClick(e) {
|
||||
if (e) {
|
||||
e.stopPropagation();
|
||||
if (e.target && (e.target.tagName === 'INPUT' || e.target.closest('.cb-switch'))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
toggleCookingMode(!isCookModeActive);
|
||||
}
|
||||
|
||||
// Wenn der Nutzer die App/den Tab wechselt und zurückkommt: Wake Lock & Video reaktivieren
|
||||
// Wenn der Nutzer den Tab wechselt und zurückkehrt
|
||||
document.addEventListener('visibilitychange', async () => {
|
||||
if (isCookModeActive && document.visibilityState === 'visible') {
|
||||
await acquireKeepAwake();
|
||||
}
|
||||
});
|
||||
|
||||
// Gespeicherten Zustand beim Laden wiederherstellen
|
||||
// Gespeicherten Zustand beim Laden prüfen
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
try {
|
||||
const saved = localStorage.getItem('wtc_cookmode_active') === 'true';
|
||||
if (saved) {
|
||||
const switches = document.querySelectorAll('.cook-mode-switch-input');
|
||||
switches.forEach(sw => { sw.checked = true; });
|
||||
document.body.classList.add('cook-mode-on');
|
||||
isCookModeActive = true;
|
||||
const statusText = document.getElementById('cookmode-status-mobile');
|
||||
if (statusText) statusText.textContent = 'Aktiv 💡 (Display bleibt an)';
|
||||
updateCookModeUI(true);
|
||||
|
||||
// User Gesture Listener für automatische Reaktivierung nach Reload
|
||||
const unlockOnGesture = () => {
|
||||
if (isCookModeActive) acquireKeepAwake();
|
||||
document.removeEventListener('touchstart', unlockOnGesture);
|
||||
|
||||
Reference in New Issue
Block a user