Compare commits

..

2 commits

5 changed files with 32 additions and 27 deletions

View file

@ -327,7 +327,7 @@ MEDIA_DIR = os.getenv("MEDIA_DIR", "/data/media")
os.makedirs(MEDIA_DIR, exist_ok=True) os.makedirs(MEDIA_DIR, exist_ok=True)
app.mount("/media", StaticFiles(directory=MEDIA_DIR), name="media") app.mount("/media", StaticFiles(directory=MEDIA_DIR), name="media")
APP_VER = "781" # muss mit APP_VER in app.js übereinstimmen APP_VER = "783" # muss mit APP_VER in app.js übereinstimmen
@app.get("/.well-known/assetlinks.json") @app.get("/.well-known/assetlinks.json")
async def assetlinks(): async def assetlinks():

View file

@ -575,10 +575,10 @@
<div id="modal-container"></div> <div id="modal-container"></div>
<!-- JS: Reihenfolge ist wichtig — erst Basis, dann Features --> <!-- JS: Reihenfolge ist wichtig — erst Basis, dann Features -->
<script src="/js/api.js?v=781"></script> <script src="/js/api.js?v=783"></script>
<script src="/js/ui.js?v=781"></script> <script src="/js/ui.js?v=783"></script>
<script src="/js/app.js?v=781"></script> <script src="/js/app.js?v=783"></script>
<script src="/js/worlds.js?v=781"></script> <script src="/js/worlds.js?v=783"></script>
<!-- Feature-Seiten werden lazy geladen --> <!-- Feature-Seiten werden lazy geladen -->

View file

@ -3,7 +3,7 @@
Router, State-Management, Navigation, Initialisierung. Router, State-Management, Navigation, Initialisierung.
============================================================ */ ============================================================ */
const APP_VER = '781'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VER = '783'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const APP_VERSION = '1.5.0'; // ← semantische Version, wird bei make release gesetzt const APP_VERSION = '1.5.0'; // ← semantische Version, wird bei make release gesetzt
const IS_STAGING = location.hostname === 'staging.banyaro.app'; const IS_STAGING = location.hostname === 'staging.banyaro.app';
// Cache-Bust-Parameter nach Update-Reload sofort entfernen // Cache-Bust-Parameter nach Update-Reload sofort entfernen

View file

@ -918,24 +918,24 @@ window.Worlds = (() => {
} }
function _applyBgImage(url) { function _applyBgImage(url) {
const track = document.getElementById('worlds-track'); const ov = document.getElementById('worlds-overlay');
if (!track) return; if (!ov) return;
if (url) { if (url) {
const toLoad = new Image(); const toLoad = new Image();
toLoad.onload = () => { toLoad.onload = () => {
_hasBgPhoto = true; _hasBgPhoto = true;
track.style.backgroundImage = `url('${url}')`; ov.style.backgroundImage = `url('${url}')`;
track.style.backgroundSize = '100% auto'; ov.style.backgroundSize = 'cover';
track.style.backgroundPosition = '0 40%'; ov.style.backgroundPosition = 'center 40%';
track.style.backgroundRepeat = 'no-repeat'; ov.style.backgroundRepeat = 'no-repeat';
document.getElementById('wh-photo-hint')?.remove(); document.getElementById('wh-photo-hint')?.remove();
}; };
toLoad.onerror = () => _applyBgImage(null); toLoad.onerror = () => _applyBgImage(null);
toLoad.src = url; toLoad.src = url;
} else { } else {
_hasBgPhoto = false; _hasBgPhoto = false;
track.style.backgroundImage = 'linear-gradient(160deg,#1a1f35 0%,#16213e 33%,#1a2535 67%,#0f1921 100%)'; ov.style.backgroundImage = 'linear-gradient(160deg,#1a1f35 0%,#16213e 33%,#1a2535 67%,#0f1921 100%)';
track.style.backgroundSize = '100% 100%'; ov.style.backgroundSize = '100% 100%';
} }
} }
@ -979,8 +979,8 @@ window.Worlds = (() => {
const staleMin = Math.max(weatherObj.ageMin || 0, dogsObj.ageMin || 0); const staleMin = Math.max(weatherObj.ageMin || 0, dogsObj.ageMin || 0);
// Panorama-Bild setzen (nur wenn noch kein Bild vorhanden) // Panorama-Bild setzen (nur wenn noch kein Bild vorhanden)
const track = document.getElementById('worlds-track'); const ov = document.getElementById('worlds-overlay');
if (dog && !track?.style.backgroundImage?.startsWith('url')) { if (dog && !ov?.style.backgroundImage?.startsWith('url')) {
_loadDailyImage(dog).then(_applyBgImage); _loadDailyImage(dog).then(_applyBgImage);
} else if (!dog) { _applyBgImage(null); } } else if (!dog) { _applyBgImage(null); }
@ -1325,24 +1325,29 @@ window.Worlds = (() => {
<div class="world-reminder bday-pop" id="wh-bday-banner" style="flex-direction:column;align-items:center; <div class="world-reminder bday-pop" id="wh-bday-banner" style="flex-direction:column;align-items:center;
text-align:center;gap:6px;padding:14px 16px;cursor:pointer; text-align:center;gap:6px;padding:14px 16px;cursor:pointer;
background:rgba(0,0,0,0.42);border-color:rgba(196,132,58,0.6)"> background:rgba(0,0,0,0.42);border-color:rgba(196,132,58,0.6)">
<div style="display:flex;gap:6px;font-size:1.5rem;line-height:1"> <div style="display:flex;gap:10px;align-items:center;justify-content:center">
<span class="bday-fw1">🎆</span> <svg class="ph-icon bday-fw1" style="width:1.6rem;height:1.6rem;color:#f59e0b"><use href="/icons/phosphor.svg#confetti"></use></svg>
<span style="font-size:2rem">${bday === 'today' ? '🎂' : '🎁'}</span> <svg class="ph-icon bday-pop" style="width:2.2rem;height:2.2rem;color:#fff"><use href="/icons/phosphor.svg#${bday === 'today' ? 'cake' : 'gift'}"></use></svg>
<span class="bday-fw2">🎇</span> <svg class="ph-icon bday-fw2" style="width:1.6rem;height:1.6rem;color:#f59e0b"><use href="/icons/phosphor.svg#confetti"></use></svg>
</div> </div>
<div style="font-weight:800;font-size:var(--text-sm);color:#fff;letter-spacing:0.01em"> <div style="font-weight:800;font-size:var(--text-sm);color:#fff;letter-spacing:0.01em">
${bday === 'today' ${bday === 'today'
? `Alles Gute zum ${bdayYear}. Geburtstag, ${_esc(dog.name)}!` ? `Alles Gute zum ${bdayYear}. Geburtstag, ${_esc(dog.name)}!`
: `Morgen hat ${_esc(dog.name)} Geburtstag! 🥳`} : `Morgen hat ${_esc(dog.name)} Geburtstag!`}
</div> </div>
<div style="display:flex;gap:4px;font-size:1.1rem"> <div style="display:flex;gap:8px;align-items:center">
<span class="bday-fw3">🎉</span><span class="bday-fw1"></span><span class="bday-fw2">🎊</span><span class="bday-fw3"></span><span class="bday-fw1">🎉</span> <svg class="ph-icon bday-fw3" style="width:1rem;height:1rem;color:#e8c96e"><use href="/icons/phosphor.svg#sparkle"></use></svg>
<svg class="ph-icon bday-fw1" style="width:1rem;height:1rem;color:#f59e0b"><use href="/icons/phosphor.svg#star"></use></svg>
<svg class="ph-icon bday-fw2" style="width:1.1rem;height:1.1rem;color:#e8c96e"><use href="/icons/phosphor.svg#balloon"></use></svg>
<svg class="ph-icon bday-fw3" style="width:1rem;height:1rem;color:#f59e0b"><use href="/icons/phosphor.svg#star"></use></svg>
<svg class="ph-icon bday-fw1" style="width:1rem;height:1rem;color:#e8c96e"><use href="/icons/phosphor.svg#sparkle"></use></svg>
</div> </div>
${bdayYear ? `<div style="font-size:10px;color:rgba(255,255,255,0.55)"> ${bdayYear ? `<div style="font-size:10px;color:rgba(255,255,255,0.55)">
${bday === 'today' ? `${bdayYear} Jahr${bdayYear !== 1 ? 'e' : ''} gemeinsam 🐾` : `Wird ${bdayYear} Jahr${bdayYear !== 1 ? 'e' : ''} alt`} ${bday === 'today' ? `${bdayYear} Jahr${bdayYear !== 1 ? 'e' : ''} gemeinsam` : `Wird ${bdayYear} Jahr${bdayYear !== 1 ? 'e' : ''} alt`}
</div>` : ''} </div>` : ''}
<div style="font-size:10px;color:rgba(196,132,58,0.9);font-weight:700;margin-top:2px"> <div style="display:flex;align-items:center;gap:4px;font-size:10px;color:rgba(196,132,58,0.9);font-weight:700;margin-top:2px">
${bday === 'today' ? '🐾 Was hat sich Ban Yaro gewünscht? →' : '✨ KI-Überraschungsideen →'} <svg class="ph-icon" style="width:11px;height:11px"><use href="/icons/phosphor.svg#magic-wand"></use></svg>
${bday === 'today' ? 'Was hat sich Ban Yaro gewünscht?' : 'KI-Überraschungsideen'}
</div> </div>
</div> </div>
${bday === 'today' && new Date().getHours() >= 18 ? ` ${bday === 'today' && new Date().getHours() >= 18 ? `

View file

@ -3,7 +3,7 @@
Offline-Cache + Push Notifications + Tile-Cache Offline-Cache + Push Notifications + Tile-Cache
============================================================ */ ============================================================ */
const CACHE_VERSION = 'by-v781'; const CACHE_VERSION = 'by-v783';
const CACHE_STATIC = `${CACHE_VERSION}-static`; const CACHE_STATIC = `${CACHE_VERSION}-static`;
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten
const CACHE_API = 'ban-yaro-api-v1'; // API-Response-Cache const CACHE_API = 'ban-yaro-api-v1'; // API-Response-Cache