diff --git a/backend/main.py b/backend/main.py index 00e2a14..3e6e5db 100644 --- a/backend/main.py +++ b/backend/main.py @@ -410,7 +410,7 @@ async def serve_media(path: str, request: _Request): raise _HE(404, "Nicht gefunden.") return _media_response(filepath) -APP_VER = "1010" # muss mit APP_VER in app.js übereinstimmen +APP_VER = "1011" # muss mit APP_VER in app.js übereinstimmen @app.get("/.well-known/assetlinks.json") async def assetlinks(): diff --git a/backend/static/js/app.js b/backend/static/js/app.js index b573384..d121211 100644 --- a/backend/static/js/app.js +++ b/backend/static/js/app.js @@ -3,7 +3,7 @@ Router, State-Management, Navigation, Initialisierung. ============================================================ */ -const APP_VER = '1010'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '1011'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VERSION = '1.6.0'; // ← semantische Version, wird bei make release gesetzt const IS_STAGING = location.hostname === 'staging.banyaro.app'; // Cache-Bust-Parameter nach Update-Reload sofort entfernen diff --git a/backend/static/js/worlds.js b/backend/static/js/worlds.js index 82dbac2..8e8100c 100644 --- a/backend/static/js/worlds.js +++ b/backend/static/js/worlds.js @@ -732,9 +732,9 @@ window.Worlds = (() => { document.body.appendChild(ov); const _removeDragListeners = () => { - document.removeEventListener('touchmove', _onDragMove); - document.removeEventListener('touchend', _onDragEnd); - document.removeEventListener('touchcancel', _onDragEnd); + document.removeEventListener('pointermove', _onDragMove); + document.removeEventListener('pointerup', _onDragEnd); + document.removeEventListener('pointercancel', _onDragEnd); }; const _cancelDrag = () => { if (!_drag) return; @@ -874,29 +874,27 @@ window.Worlds = (() => { }); }); - // Touch-Drag + // Pointer-Drag (funktioniert auf Mouse + Touch) ov.querySelectorAll('.wc-chip').forEach(chip => { - chip.addEventListener('touchstart', e => _onDragStart(e, chip), { passive: true }); + chip.addEventListener('pointerdown', e => _onDragStart(e, chip)); }); - document.addEventListener('touchmove', _onDragMove, { passive: false }); - document.addEventListener('touchend', _onDragEnd); } function _onDragStart(e, chipEl) { + if (e.button !== undefined && e.button !== 0) return; // nur linke Maustaste if (_drag) _cancelDrag(); - const touch = e.touches[0]; - // Drag erst nach Bewegungs-Threshold aktivieren (verhindert Scroll-Konflikte) + chipEl.setPointerCapture(e.pointerId); _drag = { page: chipEl.dataset.page, zone: chipEl.dataset.zone, chipEl, ghost: null, dropZone: null, active: false, - startX: touch.clientX, startY: touch.clientY, ox: 0, oy: 0, + startX: e.clientX, startY: e.clientY, ox: 0, oy: 0, }; - document.addEventListener('touchmove', _onDragMove, { passive: false }); - document.addEventListener('touchend', _onDragEnd); - document.addEventListener('touchcancel', _onDragEnd); + document.addEventListener('pointermove', _onDragMove); + document.addEventListener('pointerup', _onDragEnd); + document.addEventListener('pointercancel', _onDragEnd); } - function _activateDrag(touch) { + function _activateDrag(e) { const rect = _drag.chipEl.getBoundingClientRect(); _drag.ox = _drag.startX - rect.left; _drag.oy = _drag.startY - rect.top; @@ -910,8 +908,8 @@ window.Worlds = (() => { ghost.style.transform = 'scale(1.08) rotate(-2deg)'; ghost.style.width = rect.width + 'px'; ghost.style.height = rect.height + 'px'; - ghost.style.left = (touch.clientX - _drag.ox) + 'px'; - ghost.style.top = (touch.clientY - _drag.oy) + 'px'; + ghost.style.left = (e.clientX - _drag.ox) + 'px'; + ghost.style.top = (e.clientY - _drag.oy) + 'px'; ghost.style.transition = 'none'; ghost.style.boxShadow = '0 8px 24px rgba(0,0,0,0.5)'; document.body.appendChild(ghost); @@ -921,24 +919,22 @@ window.Worlds = (() => { function _onDragMove(e) { if (!_drag) return; - const touch = e.touches[0]; if (!_drag.active) { - const dx = Math.abs(touch.clientX - _drag.startX); - const dy = Math.abs(touch.clientY - _drag.startY); - if (dx < 8 && dy < 8) return; // Threshold noch nicht erreicht - _activateDrag(touch); + const dx = Math.abs(e.clientX - _drag.startX); + const dy = Math.abs(e.clientY - _drag.startY); + if (dx < 8 && dy < 8) return; + _activateDrag(e); } - e.preventDefault(); // Scroll erst NACH Threshold blockieren - _drag.ghost.style.left = (touch.clientX - _drag.ox) + 'px'; - _drag.ghost.style.top = (touch.clientY - _drag.oy) + 'px'; + _drag.ghost.style.left = (e.clientX - _drag.ox) + 'px'; + _drag.ghost.style.top = (e.clientY - _drag.oy) + 'px'; let foundZone = null; ov.querySelectorAll('.wc-zone').forEach(z => { const r = z.getBoundingClientRect(); - const over = touch.clientX >= r.left && touch.clientX <= r.right - && touch.clientY >= r.top && touch.clientY <= r.bottom; + const over = e.clientX >= r.left && e.clientX <= r.right + && e.clientY >= r.top && e.clientY <= r.bottom; z.style.borderColor = over ? (worldColors[z.dataset.zone] || 'rgba(196,132,58,0.8)') : 'transparent'; if (over) foundZone = z.dataset.zone; }); diff --git a/backend/static/sw.js b/backend/static/sw.js index e38509a..f4f7fc1 100644 --- a/backend/static/sw.js +++ b/backend/static/sw.js @@ -3,7 +3,7 @@ Offline-Cache + Push Notifications + Tile-Cache ============================================================ */ -const CACHE_VERSION = 'by-v1010'; +const CACHE_VERSION = 'by-v1011'; const CACHE_STATIC = `${CACHE_VERSION}-static`; const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten const CACHE_API = 'ban-yaro-api-v1'; // API-Response-Cache