mirror of
https://github.com/Shik3i/KoalaSync.git
synced 2026-08-27 11:07:07 +00:00
feat:local-blacklist-and-audio-boost
This commit is contained in:
+90
-54
@@ -250,6 +250,11 @@
|
||||
!!window.koalaFindPageApiSeekProvider(window.location.hostname);
|
||||
}
|
||||
|
||||
function seekVideo(video, targetTime) {
|
||||
// Prefer a precise page-level seek API when available (Netflix, Disney+);
|
||||
// for those players the DOM/button seek path is imprecise or impossible.
|
||||
if (shouldUsePageApiSeek()) {
|
||||
expectedSeekTime = targetTime;
|
||||
window.postMessage({ __koalaPageApiSeek: PAGE_API_SEEK_BRIDGE, kind: 'seek', time: targetTime }, '*');
|
||||
return;
|
||||
}
|
||||
@@ -605,24 +610,32 @@
|
||||
|
||||
if (ready || Date.now() >= deadline) {
|
||||
|
||||
hcmDeferredSnapPending = false;
|
||||
|
||||
hcmRequestHostSyncWithRetry(); // fresh host position + snap once
|
||||
hcmDeferredSnapPending = false;
|
||||
|
||||
hcmRequestHostSyncWithRetry(); // fresh host position + snap once
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
scheduleLifecycleTimeout(poll, 300);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
poll();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Entry point: background told us our local action was blocked in host-only.
|
||||
|
||||
function hcmHandleBlocked(action, target) {
|
||||
|
||||
|
||||
|
||||
|
||||
// Entry point: background told us our local action was blocked in host-only.
|
||||
// HOST_BLOCKED is only ever sent to a gated guest (background verifies
|
||||
|
||||
// host-only + !host before sending), so it's authoritative. Adopt the
|
||||
|
||||
// role/mode from it in case our CONTROL_MODE broadcast hasn't landed yet
|
||||
|
||||
// (join race, EC-5) — otherwise we'd miss the dialog/snap-back.
|
||||
|
||||
@@ -665,21 +678,31 @@
|
||||
// deferred and "Stay in sync" paths).
|
||||
|
||||
if (target && Number.isFinite(target.targetTime)) hcmSnapBackToHost(target);
|
||||
|
||||
// usable, otherwise re-query+retry (host state may not be known yet)
|
||||
|
||||
// so we never leave the guest silently stuck (consistent with the
|
||||
|
||||
// deferred and "Stay in sync" paths).
|
||||
|
||||
if (target && Number.isFinite(target.targetTime)) hcmSnapBackToHost(target);
|
||||
|
||||
else hcmRequestHostSyncWithRetry();
|
||||
|
||||
} else {
|
||||
|
||||
hcmDeferredSnapBack(); // buffering → wait for ready, then snap once (#3)
|
||||
|
||||
|
||||
else hcmRequestHostSyncWithRetry();
|
||||
|
||||
} else {
|
||||
|
||||
hcmDeferredSnapBack(); // buffering → wait for ready, then snap once (#3)
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Deliberate: offer the choice (Teleparty-style), default = snap back.
|
||||
|
||||
hcmShowDesyncDialog(action, target);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// --- In-page UI (dialog + persistent desync badge) ---
|
||||
|
||||
// Built with the DOM API (CSSOM .style is CSP-safe; inline style="" in innerHTML
|
||||
|
||||
// is stripped by strict style-src on Netflix/YouTube/Disney+). Hosted in a
|
||||
|
||||
// Shadow DOM so the page's CSS can't restyle or hide our controls.
|
||||
@@ -699,46 +722,59 @@
|
||||
if (css) el.style.cssText = css; // CSSOM assignment — not gated by CSP
|
||||
|
||||
if (text != null) el.textContent = text;
|
||||
|
||||
// Shadow DOM so the page's CSS can't restyle or hide our controls.
|
||||
|
||||
let hcmDialogHost = null; // shadow host element for the dialog
|
||||
|
||||
|
||||
return el;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function hcmRemoveDialog() {
|
||||
|
||||
// Cancel any pending auto-stay timer so a replaced dialog's stale closure
|
||||
|
||||
// can't later remove its successor / snap to an outdated target (H-4).
|
||||
|
||||
if (hcmDialogTimer) { clearTimeout(hcmDialogTimer); hcmDialogTimer = null; }
|
||||
function hcmEl(tag, css, text) {
|
||||
|
||||
const el = document.createElement(tag);
|
||||
|
||||
if (css) el.style.cssText = css; // CSSOM assignment — not gated by CSP
|
||||
|
||||
|
||||
if (hcmDialogHost) { hcmDialogHost.remove(); hcmDialogHost = null; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function hcmShowDesyncDialog(action, target) {
|
||||
|
||||
if (!document.body) { hcmSnapBackToHost(target); return; }
|
||||
|
||||
hcmRemoveDialog();
|
||||
}
|
||||
|
||||
|
||||
|
||||
function hcmRemoveDialog() {
|
||||
|
||||
// Cancel any pending auto-stay timer so a replaced dialog's stale closure
|
||||
|
||||
// can't later remove its successor / snap to an outdated target (H-4).
|
||||
|
||||
if (hcmDialogTimer) { clearTimeout(hcmDialogTimer); hcmDialogTimer = null; }
|
||||
|
||||
if (hcmDialogHost) { hcmDialogHost.remove(); hcmDialogHost = null; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function hcmShowDesyncDialog(action, target) {
|
||||
|
||||
const host = hcmEl('div', 'all:initial');
|
||||
|
||||
const root = host.attachShadow({ mode: 'open' });
|
||||
|
||||
|
||||
|
||||
const wrap = hcmEl('div', 'position:fixed;z-index:2147483647;left:50%;bottom:32px;transform:translateX(-50%);background:#212a17;color:#f4f2ea;font:14px/1.4 system-ui,sans-serif;padding:16px 18px;border-radius:12px;box-shadow:0 8px 30px rgba(0,0,0,.45);max-width:360px;border:1px solid #2f3625');
|
||||
|
||||
wrap.setAttribute('role', 'dialog');
|
||||
|
||||
const title = hcmEl('div', 'font-weight:600;margin-bottom:6px', hcmStrings.title);
|
||||
|
||||
const body = hcmEl('div', 'margin-bottom:12px;color:#bcb7a9', hcmStrings.body);
|
||||
|
||||
const btnRow = hcmEl('div', 'display:flex;gap:8px;justify-content:flex-end');
|
||||
|
||||
const soloBtn = hcmEl('button', 'background:#2f3625;color:#f4f2ea;border:0;padding:8px 12px;border-radius:8px;cursor:pointer', hcmStrings.solo);
|
||||
|
||||
const stayBtn = hcmEl('button', 'background:#56ae6c;color:#0a1a0d;border:0;padding:8px 12px;border-radius:8px;cursor:pointer;font-weight:600', hcmStrings.stay);
|
||||
|
||||
btnRow.append(soloBtn, stayBtn);
|
||||
|
||||
wrap.append(title, body, btnRow);
|
||||
|
||||
root.appendChild(wrap);
|
||||
|
||||
document.body.appendChild(host);
|
||||
|
||||
hcmDialogHost = host;
|
||||
|
||||
Reference in New Issue
Block a user