Tizen-App v5.5.0: - Remote-Logging: Console-Override + XHR an /api/tizen-log alle 3s - Debug-Panel: Gruene Taste toggled scrollbares Log-Panel (unten) - window.onerror Handler fuer uncaught Errors - Alle v5.4.2 Features erhalten (Connecting-Overlay, Timeout, IME-Fixes) Server (tv_api.py): - POST/GET /api/tizen-log Endpunkte (DB-Tabelle tizen_logs) - Cookie SameSite-Fix: Tizen iframe bekommt kein SameSite (Lax blockiert) Login (login.html): - D-Pad Navigation per postMessage (vknative_keyevent) - ArrowUp/Down zwischen Feldern, Enter auf Button Sonstiges: - base.html: vk_app_loaded postMessage Signal - sw.js: Cache v14 -> v15 - Altes Docker-Export entfernt Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
111 lines
4.6 KiB
HTML
111 lines
4.6 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
<meta name="theme-color" content="#0f0f0f">
|
|
<link rel="stylesheet" href="/static/tv/css/tv.css?v={{ v }}">
|
|
<title>Login - VideoKonverter TV</title>
|
|
</head>
|
|
<body class="login-body">
|
|
<!-- Lade-Spinner (verhindert Flash des Login-Formulars) -->
|
|
<div class="login-loader" id="login-loader">
|
|
<div class="login-spinner"></div>
|
|
</div>
|
|
|
|
<div class="login-container" id="login-container" style="display:none">
|
|
<div class="login-card">
|
|
<h1 class="login-title">VideoKonverter</h1>
|
|
<p class="login-subtitle">TV-Streaming</p>
|
|
|
|
{% if error %}
|
|
<div class="login-error">{{ error }}</div>
|
|
{% endif %}
|
|
|
|
<form method="POST" action="/tv/login" class="login-form">
|
|
<div class="login-field">
|
|
<label for="username">Benutzername</label>
|
|
<input type="text" id="username" name="username"
|
|
autocomplete="username"
|
|
data-focusable required>
|
|
</div>
|
|
<div class="login-field">
|
|
<label for="password">Passwort</label>
|
|
<input type="password" id="password" name="password"
|
|
autocomplete="current-password"
|
|
data-focusable required>
|
|
</div>
|
|
<div class="login-field login-remember">
|
|
<label class="settings-check">
|
|
<input type="checkbox" name="remember" data-focusable>
|
|
Angemeldet bleiben
|
|
</label>
|
|
</div>
|
|
<button type="submit" class="login-btn" data-focusable>
|
|
Anmelden
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Tizen iframe: Parent signalisieren dass die App geladen hat
|
|
if (window.parent !== window) {
|
|
try { window.parent.postMessage({type: "vk_app_loaded"}, "*"); } catch(e) {}
|
|
}
|
|
|
|
// === D-Pad Navigation fuer Login-Formular (Tizen/Samsung Fernbedienung) ===
|
|
(function() {
|
|
// postMessage-Events vom Tizen-Parent empfangen und als KeyboardEvent dispatchen
|
|
window.addEventListener("message", function(evt) {
|
|
var d = evt.data;
|
|
if (!d || d.type !== "vknative_keyevent" || !d.keyCode) return;
|
|
var keyMap = {13:"Enter",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",27:"Escape",8:"Backspace",10009:"Escape"};
|
|
var ke = new KeyboardEvent("keydown", {keyCode:d.keyCode, which:d.keyCode, key:keyMap[d.keyCode]||"", bubbles:true});
|
|
document.dispatchEvent(ke);
|
|
});
|
|
|
|
// Focusable Elemente sammeln und D-Pad-Navigation
|
|
function getFocusables() {
|
|
return Array.prototype.slice.call(document.querySelectorAll("[data-focusable]"));
|
|
}
|
|
document.addEventListener("keydown", function(e) {
|
|
var els = getFocusables();
|
|
if (!els.length) return;
|
|
var idx = els.indexOf(document.activeElement);
|
|
if (e.key === "ArrowDown" || e.keyCode === 40) {
|
|
e.preventDefault();
|
|
els[idx < els.length - 1 ? idx + 1 : 0].focus();
|
|
} else if (e.key === "ArrowUp" || e.keyCode === 38) {
|
|
e.preventDefault();
|
|
els[idx > 0 ? idx - 1 : els.length - 1].focus();
|
|
} else if ((e.key === "Enter" || e.keyCode === 13) && document.activeElement.tagName === "BUTTON") {
|
|
document.activeElement.click();
|
|
}
|
|
});
|
|
})();
|
|
|
|
// Pruefen ob Browser Felder vorausgefuellt hat -> automatisch absenden
|
|
var _autoAttempts = 0;
|
|
var _autoInterval = setInterval(function() {
|
|
_autoAttempts++;
|
|
var u = document.getElementById('username');
|
|
var p = document.getElementById('password');
|
|
if (u && p && u.value && p.value) {
|
|
clearInterval(_autoInterval);
|
|
document.querySelector('.login-form').submit();
|
|
return;
|
|
}
|
|
if (_autoAttempts >= 5) {
|
|
clearInterval(_autoInterval);
|
|
// Kein Auto-Fill -> Formular anzeigen
|
|
document.getElementById('login-loader').style.display = 'none';
|
|
var container = document.getElementById('login-container');
|
|
container.style.display = '';
|
|
container.style.animation = 'fadeIn 0.3s ease';
|
|
if (u) u.focus();
|
|
}
|
|
}, 200);
|
|
</script>
|
|
</body>
|
|
</html>
|