iOS-Fixes: Zoom + Overlay-Verrutschen bei Tastatur-Öffnung behoben
- Viewport-Meta: maximum-scale=1.0 + viewport-fit=cover + user-scalable=no → verhindert Zoom beim Fokussieren von Input-Feldern auf iOS - Input-Font-Size auf 16px (Chat + Submit-Formular) → iOS Safari zoomt nicht mehr rein (<16px trigger) - Backdrop: height:100dvh für lückenlose Abdeckung - visualViewport-Resize-Handler: Overlays werden bei iOS-Tastatur korrekt nach oben geschoben, kein seitliches Verrutschen mehr
This commit is contained in:
@@ -2421,7 +2421,7 @@ def _get_user_from_session(db) -> dict | None:
|
|||||||
# ── HTML-Templates (plain strings, no f-string needed) ──────────────
|
# ── HTML-Templates (plain strings, no f-string needed) ──────────────
|
||||||
|
|
||||||
_REGISTER_TPL = """<!DOCTYPE html>
|
_REGISTER_TPL = """<!DOCTYPE html>
|
||||||
<html lang="de"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<html lang="de"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, viewport-fit=cover, user-scalable=no">
|
||||||
<title>Registrieren — BSN Community</title>
|
<title>Registrieren — BSN Community</title>
|
||||||
<style>
|
<style>
|
||||||
body{font-family:-apple-system,sans-serif;background:#1a1a2e;color:#eee;display:flex;justify-content:center;align-items:center;min-height:100vh;margin:0}
|
body{font-family:-apple-system,sans-serif;background:#1a1a2e;color:#eee;display:flex;justify-content:center;align-items:center;min-height:100vh;margin:0}
|
||||||
@@ -2449,7 +2449,7 @@ input{width:100%;padding:0.8rem;margin:0.4rem 0;border-radius:8px;border:1px sol
|
|||||||
</div></body></html>"""
|
</div></body></html>"""
|
||||||
|
|
||||||
_LOGIN_TPL = """<!DOCTYPE html>
|
_LOGIN_TPL = """<!DOCTYPE html>
|
||||||
<html lang="de"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<html lang="de"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, viewport-fit=cover, user-scalable=no">
|
||||||
<title>Login — BSN Community</title>
|
<title>Login — BSN Community</title>
|
||||||
<style>
|
<style>
|
||||||
body{font-family:-apple-system,sans-serif;background:#1a1a2e;color:#eee;display:flex;justify-content:center;align-items:center;min-height:100vh;margin:0}
|
body{font-family:-apple-system,sans-serif;background:#1a1a2e;color:#eee;display:flex;justify-content:center;align-items:center;min-height:100vh;margin:0}
|
||||||
@@ -2476,7 +2476,7 @@ input{width:100%;padding:0.8rem;margin:0.4rem 0;border-radius:8px;border:1px sol
|
|||||||
</div></body></html>"""
|
</div></body></html>"""
|
||||||
|
|
||||||
_PROFILE_TPL = """<!DOCTYPE html>
|
_PROFILE_TPL = """<!DOCTYPE html>
|
||||||
<html lang="de"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<html lang="de"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, viewport-fit=cover, user-scalable=no">
|
||||||
<title>Profil — BSN Community</title>
|
<title>Profil — BSN Community</title>
|
||||||
<style>
|
<style>
|
||||||
body{font-family:-apple-system,sans-serif;background:#1a1a2e;color:#eee;display:flex;justify-content:center;align-items:center;min-height:100vh;margin:0}
|
body{font-family:-apple-system,sans-serif;background:#1a1a2e;color:#eee;display:flex;justify-content:center;align-items:center;min-height:100vh;margin:0}
|
||||||
@@ -2666,7 +2666,7 @@ def public_frontend():
|
|||||||
|
|
||||||
empty_state = """<!DOCTYPE html>
|
empty_state = """<!DOCTYPE html>
|
||||||
<html lang="de">
|
<html lang="de">
|
||||||
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, viewport-fit=cover, user-scalable=no">
|
||||||
<title>BSN Community — Stimmen aus der Szene</title>
|
<title>BSN Community — Stimmen aus der Szene</title>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
@@ -2885,7 +2885,7 @@ def public_frontend():
|
|||||||
return ("""<!DOCTYPE html>
|
return ("""<!DOCTYPE html>
|
||||||
<html lang="de">
|
<html lang="de">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, viewport-fit=cover, user-scalable=no">
|
||||||
<title>BSN Community — Stimmen aus der Szene</title>
|
<title>BSN Community — Stimmen aus der Szene</title>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
@@ -3047,7 +3047,7 @@ def public_frontend():
|
|||||||
background:#fff; border-radius:18px; box-shadow:0 12px 48px rgba(0,0,0,0.22);
|
background:#fff; border-radius:18px; box-shadow:0 12px 48px rgba(0,0,0,0.22);
|
||||||
display:none; flex-direction:column; overflow:hidden; }
|
display:none; flex-direction:column; overflow:hidden; }
|
||||||
.chat-overlay.open { display:flex; }
|
.chat-overlay.open { display:flex; }
|
||||||
.chat-backdrop { position:fixed; inset:0; z-index:10000; background:rgba(0,0,0,0.25); backdrop-filter:blur(4px); -webkit-backdrop-filter:blur(4px); display:none; }
|
.chat-backdrop { position:fixed; inset:0; z-index:10000; background:rgba(0,0,0,0.25); backdrop-filter:blur(4px); -webkit-backdrop-filter:blur(4px); display:none; height:100dvh; }
|
||||||
.chat-backdrop.open { display:block; }
|
.chat-backdrop.open { display:block; }
|
||||||
.chat-header { background:#20228a; color:#fff; padding:0.9rem 1.2rem;
|
.chat-header { background:#20228a; color:#fff; padding:0.9rem 1.2rem;
|
||||||
font-weight:700; font-size:0.9rem; display:flex; align-items:center; justify-content:space-between; }
|
font-weight:700; font-size:0.9rem; display:flex; align-items:center; justify-content:space-between; }
|
||||||
@@ -3066,7 +3066,7 @@ def public_frontend():
|
|||||||
@keyframes fadeUp { from{opacity:0;transform:translateY(8px);} to{opacity:1;transform:translateY(0);} }
|
@keyframes fadeUp { from{opacity:0;transform:translateY(8px);} to{opacity:1;transform:translateY(0);} }
|
||||||
.chat-footer { padding:0.7rem 0.9rem; border-top:1px solid #eee; display:flex; gap:0.5rem; }
|
.chat-footer { padding:0.7rem 0.9rem; border-top:1px solid #eee; display:flex; gap:0.5rem; }
|
||||||
.chat-footer input { flex:1; border:1.5px solid #ddd; border-radius:999px;
|
.chat-footer input { flex:1; border:1.5px solid #ddd; border-radius:999px;
|
||||||
padding:0.55rem 1rem; font-size:0.82rem; font-family:inherit; outline:none;
|
padding:0.55rem 1rem; font-size:16px; font-family:inherit; outline:none;
|
||||||
transition:border-color 0.15s; }
|
transition:border-color 0.15s; }
|
||||||
.chat-footer input:focus { border-color:#20228a; }
|
.chat-footer input:focus { border-color:#20228a; }
|
||||||
.chat-footer button { background:#20228a; color:#fff; border:none; border-radius:999px;
|
.chat-footer button { background:#20228a; color:#fff; border:none; border-radius:999px;
|
||||||
@@ -3101,7 +3101,7 @@ def public_frontend():
|
|||||||
text-transform:uppercase; letter-spacing:0.03em; margin-bottom:0.2rem; margin-top:0.8rem; }
|
text-transform:uppercase; letter-spacing:0.03em; margin-bottom:0.2rem; margin-top:0.8rem; }
|
||||||
.submit-body label:first-of-type { margin-top:0; }
|
.submit-body label:first-of-type { margin-top:0; }
|
||||||
.submit-body input, .submit-body textarea { width:100%; border:1.5px solid #ddd;
|
.submit-body input, .submit-body textarea { width:100%; border:1.5px solid #ddd;
|
||||||
border-radius:10px; padding:0.55rem 0.8rem; font-size:0.82rem; font-family:inherit;
|
border-radius:10px; padding:0.55rem 0.8rem; font-size:16px; font-family:inherit;
|
||||||
outline:none; transition:border-color 0.15s; }
|
outline:none; transition:border-color 0.15s; }
|
||||||
.submit-body textarea { resize:vertical; min-height:70px; }
|
.submit-body textarea { resize:vertical; min-height:70px; }
|
||||||
.submit-body input:focus, .submit-body textarea:focus { border-color:#20228a; }
|
.submit-body input:focus, .submit-body textarea:focus { border-color:#20228a; }
|
||||||
@@ -3656,6 +3656,40 @@ def public_frontend():
|
|||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// iOS: Verhindert dass Overlays bei Tastatur-Öffnung aus dem Bild rutschen
|
||||||
|
// visualViewport API gleicht den Offset aus
|
||||||
|
(function() {
|
||||||
|
if (!window.visualViewport) return;
|
||||||
|
var chatO = document.getElementById('chatOverlay');
|
||||||
|
var submitO = document.getElementById('submitOverlay');
|
||||||
|
var backdrop = document.getElementById('chatBackdrop');
|
||||||
|
|
||||||
|
window.visualViewport.addEventListener('resize', function() {
|
||||||
|
var offsetTop = window.visualViewport.offsetTop || 0;
|
||||||
|
// Overlays und Backdrop nach oben schieben wenn Tastatur offen
|
||||||
|
if (chatO && chatO.classList.contains('open')) {
|
||||||
|
chatO.style.transform = 'translateY(-' + offsetTop + 'px)';
|
||||||
|
}
|
||||||
|
if (submitO && submitO.classList.contains('open')) {
|
||||||
|
submitO.style.transform = 'translateY(-' + offsetTop + 'px)';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Reset transform wenn Overlay geschlossen wird
|
||||||
|
var obs = new MutationObserver(function() {
|
||||||
|
if (chatO && !chatO.classList.contains('open')) {
|
||||||
|
chatO.style.transform = '';
|
||||||
|
}
|
||||||
|
if (submitO && !submitO.classList.contains('open')) {
|
||||||
|
submitO.style.transform = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (chatO) obs.observe(chatO, {attributes: true, attributeFilter: ['class']});
|
||||||
|
if (submitO) obs.observe(submitO, {attributes: true, attributeFilter: ['class']});
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>""").replace("{LOGO_B64}", LOGO_B64)
|
</html>""").replace("{LOGO_B64}", LOGO_B64)
|
||||||
|
|
||||||
@@ -3686,7 +3720,7 @@ def _legal_page(title, content_html):
|
|||||||
return f"""<!DOCTYPE html>
|
return f"""<!DOCTYPE html>
|
||||||
<html lang="de">
|
<html lang="de">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, viewport-fit=cover, user-scalable=no">
|
||||||
<title>{title} — BSN Community</title>
|
<title>{title} — BSN Community</title>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
@@ -4475,7 +4509,7 @@ def public_detail(sub_id: int):
|
|||||||
return f"""<!DOCTYPE html>
|
return f"""<!DOCTYPE html>
|
||||||
<html lang="de">
|
<html lang="de">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, viewport-fit=cover, user-scalable=no">
|
||||||
<title>Beitrag — BSN Community</title>
|
<title>Beitrag — BSN Community</title>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
|||||||
Reference in New Issue
Block a user