feat: VideoKonverter v5.8 - AVPlay-Overlay Fix, Debug-Stats, Focus-Ring Fix
- Tizen: Parent-Frame Transparenz + iframe z-index Fix fuer sichtbare Player-Controls ueber AVPlay - Tizen: Farbtasten (Rot/Gruen/Gelb/Blau) werden bei aktivem AVPlay an iframe weitergeleitet - Tizen: AVPlay Debug-Stats (State, Stream-Info, Codec, Bitrate) per postMessage abrufbar - VKNative Bridge: requestStats() + vknative_stats Handler fuer AVPlay-Monitoring - Player: Debug-Overlay zeigt AVPlay-spezifische Infos (Blaue Taste auf Fernbedienung) - CSS: Episoden-Karten Focus-Ring von outline auf box-shadow umgestellt (kein Clipping mehr) - CSS: Episode-Grid padding fuer Scale-Transform Platz - SW Cache v16 -> v17 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
dc9ee15ec3
commit
95df4d7a90
6 changed files with 100 additions and 12 deletions
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets"
|
||||
id="http://data-it-solution.de/videokonverter" version="5.7.0" viewmodes="maximized">
|
||||
id="http://data-it-solution.de/videokonverter" version="5.8.0" viewmodes="maximized">
|
||||
|
||||
<name>VideoKonverter</name>
|
||||
<description>VideoKonverter TV-App - Serien und Filme streamen mit AVPlay Direct-Play</description>
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@
|
|||
<button id="connectBtn" data-focusable>Verbinden</button>
|
||||
<p class="hint">Nur IP:Port eingeben (z.B. 192.168.155.12:8080).<br>
|
||||
http:// und /tv/ werden automatisch ergaenzt.</p>
|
||||
<p class="hint" style="margin-top:2rem;color:#555">v5.7.0 | Gruene Taste = Debug-Log</p>
|
||||
<p class="hint" style="margin-top:2rem;color:#555">v5.8.0 | Gruene Taste = Debug-Log</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -127,7 +127,7 @@
|
|||
|
||||
<script>
|
||||
/**
|
||||
* VideoKonverter Tizen App v5.7
|
||||
* VideoKonverter Tizen App v5.8
|
||||
* Architektur: iframe (Server-UI) + AVPlay (Direct-Play im Parent-Frame)
|
||||
* Kommunikation: postMessage zwischen iframe <-> Parent
|
||||
* Debug: Gruene Taste = Log-Panel, Remote-Logging an /api/tizen-log
|
||||
|
|
@ -199,7 +199,7 @@
|
|||
_remoteQueue.push({l: level, m: String(msg).substr(0, 2000), t: new Date().toTimeString().substr(0,8)});
|
||||
};
|
||||
|
||||
console.info("[TizenApp] v5.7.0 gestartet. Gruene Taste = Debug-Log. Remote-Logging aktiv.");
|
||||
console.info("[TizenApp] v5.8.0 gestartet. Gruene Taste = Debug-Log. Remote-Logging aktiv.");
|
||||
console.info("[TizenApp] localStorage=" + JSON.stringify(localStorage));
|
||||
console.info("[TizenApp] userAgent=" + navigator.userAgent);
|
||||
|
||||
|
|
@ -453,6 +453,24 @@
|
|||
// Server fordert Reset an (z.B. bei Logout)
|
||||
resetToSetup();
|
||||
break;
|
||||
|
||||
case "vknative_get_stats":
|
||||
// Debug-Overlay fragt AVPlay-Stats ab
|
||||
var stats = { active: _avplayActive, playing: _playing };
|
||||
if (_avplayActive) {
|
||||
try { stats.state = webapis.avplay.getState(); } catch (ex) { stats.state = "?"; }
|
||||
try { stats.time_ms = webapis.avplay.getCurrentTime(); } catch (ex) {}
|
||||
stats.duration_ms = _duration || 0;
|
||||
try {
|
||||
var si = webapis.avplay.getCurrentStreamInfo();
|
||||
stats.streams = [];
|
||||
for (var s = 0; s < si.length; s++) {
|
||||
stats.streams.push({ type: si[s].type, extra: si[s].extra_info });
|
||||
}
|
||||
} catch (ex) {}
|
||||
}
|
||||
_sendToIframe({ type: "vknative_stats", stats: stats });
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -525,10 +543,15 @@
|
|||
if (avEl) avEl.style.display = "block";
|
||||
|
||||
// iframe: Pointer deaktivieren (D-Pad kommt per postMessage)
|
||||
// Opacity bleibt 1 → transparenter Hintergrund im iframe zeigt AVPlay-Video durch
|
||||
// Hintergruende transparent machen damit AVPlay-Hardware-Layer durchscheint
|
||||
// iframe z-index ueber avplayer (10) setzen damit Controls sichtbar bleiben
|
||||
if (_iframe) {
|
||||
_iframe.style.pointerEvents = "none";
|
||||
_iframe.style.background = "transparent";
|
||||
_iframe.style.zIndex = "20";
|
||||
}
|
||||
document.body.style.background = "transparent";
|
||||
document.documentElement.style.background = "transparent";
|
||||
|
||||
// AVPlay oeffnen
|
||||
console.info("[TizenApp] AVPlay oeffne: " + fullUrl);
|
||||
|
|
@ -655,10 +678,15 @@
|
|||
var avEl = document.getElementById("avplayer");
|
||||
if (avEl) avEl.style.display = "block";
|
||||
|
||||
// iframe: Pointer deaktivieren (D-Pad kommt per postMessage)
|
||||
// iframe: Pointer deaktivieren + Hintergruende transparent
|
||||
// iframe z-index ueber avplayer (10) setzen damit Controls sichtbar bleiben
|
||||
if (_iframe) {
|
||||
_iframe.style.pointerEvents = "none";
|
||||
_iframe.style.background = "transparent";
|
||||
_iframe.style.zIndex = "20";
|
||||
}
|
||||
document.body.style.background = "transparent";
|
||||
document.documentElement.style.background = "transparent";
|
||||
|
||||
// AVPlay mit HLS-URL oeffnen
|
||||
console.info("[TizenApp] AVPlay HLS oeffne: " + fullUrl);
|
||||
|
|
@ -754,10 +782,14 @@
|
|||
var avEl = document.getElementById("avplayer");
|
||||
if (avEl) avEl.style.display = "none";
|
||||
|
||||
// iframe wieder aktivieren
|
||||
// iframe wieder aktivieren + Hintergrund/z-index wiederherstellen
|
||||
if (_iframe) {
|
||||
_iframe.style.pointerEvents = "auto";
|
||||
_iframe.style.background = "";
|
||||
_iframe.style.zIndex = "1";
|
||||
}
|
||||
document.body.style.background = "#0f0f0f";
|
||||
document.documentElement.style.background = "";
|
||||
}
|
||||
|
||||
function _avplay_togglePlay() {
|
||||
|
|
@ -920,6 +952,14 @@
|
|||
var cur2 = webapis.avplay.getCurrentTime();
|
||||
_avplay_seek(Math.max(0, cur2 - 10000));
|
||||
} catch (ex) {}
|
||||
} else if (action.indexOf("color") === 0) {
|
||||
// Farbtasten an iframe weiterleiten (Audio/Subs/Quality/Debug)
|
||||
if (_iframe && _iframe.contentWindow) {
|
||||
_sendToIframe({
|
||||
type: "vknative_keyevent",
|
||||
keyCode: e.keyCode
|
||||
});
|
||||
}
|
||||
}
|
||||
e.preventDefault();
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1818,6 +1818,7 @@ textarea.input-editing {
|
|||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
||||
gap: 0.8rem;
|
||||
padding: 6px; /* Platz fuer Focus-Ring + Scale-Transform */
|
||||
}
|
||||
.tv-episode-tile {
|
||||
position: relative;
|
||||
|
|
@ -1839,12 +1840,11 @@ textarea.input-editing {
|
|||
outline: none;
|
||||
}
|
||||
.tv-ep-tile-link:focus .tv-ep-thumb {
|
||||
outline: 2px solid var(--accent);
|
||||
outline-offset: -2px;
|
||||
outline: none;
|
||||
}
|
||||
.tv-episode-tile:focus-within {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 6px 20px rgba(0,0,0,0.5);
|
||||
box-shadow: 0 0 0 3px var(--accent), 0 6px 20px rgba(0,0,0,0.5);
|
||||
}
|
||||
.tv-ep-tile-label {
|
||||
padding: 0.4rem 0.5rem;
|
||||
|
|
|
|||
|
|
@ -1907,6 +1907,41 @@ function _updateDebugInfo() {
|
|||
} catch (e) {}
|
||||
}
|
||||
|
||||
// AVPlay-Stats (Tizen: Stream-Info vom Parent-Frame)
|
||||
if (useNativePlayer && window.VKNative && window.VKNative.requestStats) {
|
||||
window.VKNative.requestStats(); // Async Abfrage, Ergebnis in _lastStats
|
||||
var avStats = window.VKNative._lastStats;
|
||||
if (avStats) {
|
||||
lines.push('<hr class="dbg-sep">');
|
||||
var stateClass = avStats.state === "PLAYING" ? "dbg-ok" :
|
||||
avStats.state === "PAUSED" ? "dbg-val" : "dbg-warn";
|
||||
lines.push(_dbgRow("AVPlay-Status", avStats.state || "?", stateClass));
|
||||
if (avStats.streams && avStats.streams.length) {
|
||||
for (var si = 0; si < avStats.streams.length; si++) {
|
||||
var stream = avStats.streams[si];
|
||||
var sType = stream.type || "?";
|
||||
var sExtra = "";
|
||||
if (stream.extra) {
|
||||
try {
|
||||
// extra_info ist JSON-String mit Codec-Details
|
||||
var ex = typeof stream.extra === "string" ? JSON.parse(stream.extra) : stream.extra;
|
||||
if (ex.fourCC) sExtra += ex.fourCC;
|
||||
else if (ex.mimeType) sExtra += ex.mimeType;
|
||||
if (ex.Width && ex.Height) sExtra += " " + ex.Width + "x" + ex.Height;
|
||||
if (ex.Bit_rate) sExtra += " " + _formatBitrate(parseInt(ex.Bit_rate));
|
||||
if (ex.channels) sExtra += " " + ex.channels + "ch";
|
||||
if (ex.sample_rate) sExtra += " " + (parseInt(ex.sample_rate) / 1000).toFixed(1) + "kHz";
|
||||
} catch (e) {
|
||||
sExtra = String(stream.extra).substring(0, 60);
|
||||
}
|
||||
}
|
||||
var sLabel = sType === "VIDEO" ? "AVP-Video" : sType === "AUDIO" ? "AVP-Audio" : "AVP-" + sType;
|
||||
lines.push(_dbgRow(sLabel, sExtra || "-"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Client-Codecs
|
||||
if (clientCodecs && clientCodecs.length) {
|
||||
lines.push('<hr class="dbg-sep">');
|
||||
|
|
@ -1926,7 +1961,9 @@ function _updateDebugInfo() {
|
|||
} catch (e) {}
|
||||
}
|
||||
|
||||
el.innerHTML = "<b>Debug-Info</b> <small>(i = schliessen)</small><hr class='dbg-sep'>" + lines.join("");
|
||||
// Tasten-Hilfe
|
||||
var helpText = window.VKNative ? "Blau = Debug" : "i = schliessen";
|
||||
el.innerHTML = "<b>Debug-Info</b> <small>(" + helpText + ")</small><hr class='dbg-sep'>" + lines.join("");
|
||||
}
|
||||
|
||||
function _dbgRow(label, value, cls) {
|
||||
|
|
|
|||
|
|
@ -82,6 +82,11 @@
|
|||
_handleParentEvent(data.event, data.detail || {});
|
||||
break;
|
||||
|
||||
case "vknative_stats":
|
||||
// AVPlay-Stats vom Parent (Antwort auf requestStats)
|
||||
if (data.stats) window.VKNative._lastStats = data.stats;
|
||||
break;
|
||||
|
||||
case "vknative_keyevent":
|
||||
// Key-Event vom Parent weitergeleitet -> als KeyboardEvent dispatchen
|
||||
if (data.keyCode) {
|
||||
|
|
@ -296,6 +301,12 @@
|
|||
_callParent("setPlaybackSpeed", [speed]);
|
||||
return true;
|
||||
},
|
||||
|
||||
/** AVPlay-Stats vom Parent abfragen (async, Ergebnis in _lastStats) */
|
||||
requestStats: function() {
|
||||
window.parent.postMessage({ type: "vknative_get_stats" }, "*");
|
||||
},
|
||||
_lastStats: null,
|
||||
};
|
||||
|
||||
// Parent proben (wiederholt, falls Parent noch nicht bereit)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
* Kein Offline-Caching noetig (Streaming braucht Netzwerk)
|
||||
*/
|
||||
|
||||
const CACHE_NAME = "vk-tv-v16";
|
||||
const CACHE_NAME = "vk-tv-v17";
|
||||
const STATIC_ASSETS = [
|
||||
"/static/tv/css/tv.css",
|
||||
"/static/tv/js/tv.js",
|
||||
|
|
|
|||
Loading…
Reference in a new issue