fix: fixed an issue where the controls were not working with opera

This commit is contained in:
Tronax 2026-06-01 21:47:20 +02:00
parent 4f1e373c4f
commit 8fc36b94aa

View file

@ -266,6 +266,58 @@
return bar; return bar;
} }
// ----------------------------------------------------------
// Globale Positionierung
//
// Wichtig (Opera!): Wir hängen die Steuerleiste NICHT in den
// Video-Container, sondern als oberste Ebene an den <body> und
// legen sie per fixed-Positionierung über das jeweilige Video.
//
// Grund: Opera ("Video Popout") legt über JEDES <video> eine
// eigene unsichtbare Overlay-Ebene, um Hover zu erkennen und
// den Popout-Button einzublenden. Diese Ebene schluckt alle
// Maus-Events. Eine Leiste, die im Video-Container liegt, sitzt
// darunter -> weder Hover noch Klicks kommen an. Als body-Kind
// mit maximalem z-index sitzt unsere Leiste darüber.
// ----------------------------------------------------------
const placements = []; // { video, wrapper }
function placeAll() {
const vh = window.innerHeight || document.documentElement.clientHeight;
for (let i = placements.length - 1; i >= 0; i--) {
const { video, wrapper } = placements[i];
if (!document.contains(video)) {
wrapper.remove();
placements.splice(i, 1);
continue;
}
const r = video.getBoundingClientRect();
// Nur über sichtbare, ausreichend große Reels einblenden.
const offscreen =
r.width < 150 || r.height < 200 || r.bottom <= 0 || r.top >= vh;
if (offscreen) {
if (wrapper.style.display !== "none") wrapper.style.display = "none";
continue;
}
wrapper.style.display = "flex";
wrapper.style.left = r.left + "px";
wrapper.style.top = r.top + "px";
wrapper.style.width = r.width + "px";
wrapper.style.height = r.height + "px";
}
}
let rafStarted = false;
function ensureLoop() {
if (rafStarted) return;
rafStarted = true;
const tick = () => {
placeAll();
requestAnimationFrame(tick);
};
requestAnimationFrame(tick);
}
// ---------------------------------------------------------- // ----------------------------------------------------------
// Steuerung an ein Video anheften. // Steuerung an ein Video anheften.
// ---------------------------------------------------------- // ----------------------------------------------------------
@ -275,23 +327,29 @@
video.setAttribute(ATTACHED, "1"); video.setAttribute(ATTACHED, "1");
// Wir hängen die Leiste an den nächstgelegenen positionierten
// Vorfahren, damit sie über dem Video sitzt.
let host = video.parentElement;
if (!host) return;
// Sicherstellen, dass der Host positioniert ist.
const pos = getComputedStyle(host).position;
if (pos === "static") host.style.position = "relative";
const wrapper = document.createElement("div"); const wrapper = document.createElement("div");
wrapper.className = "rc-wrapper"; wrapper.className = "rc-wrapper";
// Oberste Ebene am <body>, per fixed über das Video gelegt.
wrapper.style.position = "fixed";
wrapper.style.left = "0";
wrapper.style.top = "0";
wrapper.style.right = "auto";
wrapper.style.bottom = "auto";
wrapper.style.alignItems = "flex-end"; // Leiste am unteren Rand
wrapper.style.zIndex = "2147483647";
wrapper.style.display = "none";
wrapper.appendChild(buildControls(video)); wrapper.appendChild(buildControls(video));
host.appendChild(wrapper); document.body.appendChild(wrapper);
placements.push({ video, wrapper });
ensureLoop();
// Falls Instagram das Video entfernt, räumen wir mit auf. // Falls Instagram das Video entfernt, räumen wir mit auf.
const cleanup = new MutationObserver(() => { const cleanup = new MutationObserver(() => {
if (!document.contains(video)) { if (!document.contains(video)) {
wrapper.remove(); wrapper.remove();
const idx = placements.findIndex((p) => p.video === video);
if (idx >= 0) placements.splice(idx, 1);
cleanup.disconnect(); cleanup.disconnect();
} }
}); });