Fix: iOS Tastatur — modal-body maxHeight begrenzen + manueller scroll statt scrollIntoView (SW by-v978)

This commit is contained in:
rene 2026-05-15 13:43:17 +02:00
parent ed6dd8da13
commit f0f767e466
4 changed files with 24 additions and 10 deletions

View file

@ -408,7 +408,7 @@ async def serve_media(path: str, request: _Request):
raise _HE(404, "Nicht gefunden.") raise _HE(404, "Nicht gefunden.")
return _media_response(filepath) return _media_response(filepath)
APP_VER = "977" # muss mit APP_VER in app.js übereinstimmen APP_VER = "978" # 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

@ -3,7 +3,7 @@
Router, State-Management, Navigation, Initialisierung. Router, State-Management, Navigation, Initialisierung.
============================================================ */ ============================================================ */
const APP_VER = '977'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VER = '978'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
const APP_VERSION = '1.6.0'; // ← semantische Version, wird bei make release gesetzt const APP_VERSION = '1.6.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

@ -83,13 +83,19 @@ const UI = (() => {
document.getElementById('modal-container').appendChild(overlay); document.getElementById('modal-container').appendChild(overlay);
document.documentElement.classList.add('modal-open'); document.documentElement.classList.add('modal-open');
// Tastatur auf Mobilgeräten: Modal nach oben schieben + fokussiertes Feld einblenden // Tastatur auf Mobilgeräten: Modal-Höhe begrenzen + fokussiertes Feld scrollen
let _vvCleanup = null; let _vvCleanup = null;
const vv = window.visualViewport; const vv = window.visualViewport;
const modal = overlay.querySelector('.modal');
if (vv) { if (vv) {
const adjust = () => { const adjust = () => {
const kb = Math.max(0, window.innerHeight - vv.height - vv.offsetTop); const visible = vv.height;
overlay.style.paddingBottom = (kb + 16) + 'px'; const offset = vv.offsetTop;
const kb = Math.max(0, window.innerHeight - visible - offset);
// Overlay-Padding damit Modal nach oben rückt
overlay.style.paddingBottom = (kb + 8) + 'px';
// Modal-Höhe hart begrenzen damit modal-body scrollbar bleibt
if (modal) modal.style.maxHeight = (visible - 24) + 'px';
}; };
vv.addEventListener('resize', adjust); vv.addEventListener('resize', adjust);
vv.addEventListener('scroll', adjust); vv.addEventListener('scroll', adjust);
@ -97,15 +103,23 @@ const UI = (() => {
vv.removeEventListener('resize', adjust); vv.removeEventListener('resize', adjust);
vv.removeEventListener('scroll', adjust); vv.removeEventListener('scroll', adjust);
overlay.style.paddingBottom = ''; overlay.style.paddingBottom = '';
if (modal) modal.style.maxHeight = '';
}; };
} }
// Fokussiertes Feld in den sichtbaren Bereich scrollen (iOS) // Fokussiertes Feld innerhalb modal-body scrollen (iOS scrollIntoView
// arbeitet nicht zuverlässig in overflow-Containern)
const _onFocusin = e => { const _onFocusin = e => {
const el = e.target; const el = e.target;
if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.tagName === 'SELECT') { if (el.tagName !== 'INPUT' && el.tagName !== 'TEXTAREA' && el.tagName !== 'SELECT') return;
setTimeout(() => el.scrollIntoView({ block: 'nearest', behavior: 'smooth' }), 320); setTimeout(() => {
} const body = el.closest('.modal-body');
if (!body) { el.scrollIntoView({ block: 'nearest', behavior: 'smooth' }); return; }
const elBottom = el.getBoundingClientRect().bottom;
const vvBottom = vv ? (vv.offsetTop + vv.height) : window.innerHeight;
const gap = elBottom - vvBottom + 56; // 56px Puffer über Tastatur
if (gap > 0) body.scrollTop += gap;
}, 380);
}; };
overlay.addEventListener('focusin', _onFocusin); overlay.addEventListener('focusin', _onFocusin);

View file

@ -3,7 +3,7 @@
Offline-Cache + Push Notifications + Tile-Cache Offline-Cache + Push Notifications + Tile-Cache
============================================================ */ ============================================================ */
const CACHE_VERSION = 'by-v977'; const CACHE_VERSION = 'by-v978';
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