Fix: Drag-and-Drop in Welten-Konfig für Desktop (Pointer Events)

touchstart/touchmove/touchend → pointerdown/pointermove/pointerup:
- Pointer Events funktionieren auf Mouse (Desktop) + Touch (Mobile) gleich
- setPointerCapture() für sauberes Drag auch wenn Maus das Element verlässt
- e.touches[0] → e.clientX/clientY direkt aus dem Pointer Event
- Nur linke Maustaste (e.button === 0) startet Drag
SW by-v1011, APP_VER 1011
This commit is contained in:
rene 2026-05-16 09:24:08 +02:00
parent 1b3b150b50
commit 82869e3f12
4 changed files with 25 additions and 29 deletions

View file

@ -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():

View file

@ -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

View file

@ -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;
});

View file

@ -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