mirror of
https://github.com/Shik3i/KoalaSync.git
synced 2026-07-26 12:08:15 +00:00
Harden Disney+ time fallback against <video> element recreation
When the control overlay (and its live time readout) is briefly absent,
the old fallback recomputed the timeline from the raw blob-relative
video.currentTime via a cached scale/start. Disney recreates the <video>
element on some play/pause transitions, which resets currentTime, so that
math produced a wildly wrong time ("loses the time" after a pause).
The native clock advances 1:1 with real playback, so instead anchor the
last live UI position to video.currentTime and extrapolate by the elapsed
native delta. If the delta is negative or implausibly large (element
recreated / seek), freeze at the last known position rather than emitting
a garbage time.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+25
-12
@@ -62,6 +62,8 @@
|
||||
|
||||
// Suppresses native event reporting after a programmatic action.
|
||||
|
||||
// Each entry is a per-type timer (key = 'playing'|'paused'|'seek').
|
||||
|
||||
// While a timer exists, matching native events are consumed and not relayed.
|
||||
|
||||
// Timers self-clean after 300ms if the native event never fires.
|
||||
@@ -285,6 +287,8 @@
|
||||
const candidates = querySelectorAllShadow('button,[role="button"]');
|
||||
const backRe = /rewind|backward|back\b|zurück|zurueck|rück|rueck|retour|recul|retroced|atrás|voltar|indietro/i;
|
||||
const forwardRe = /forward|ahead|skip|vorwärts|vorwaerts|vorsp|weiter|avancer|adelant|avançar|avancar|avanti/i;
|
||||
const timeRe = /\b(5|10|15|30)\b|sec|sek|second/i;
|
||||
|
||||
const button = candidates.find(btn => {
|
||||
const label = getElementLabel(btn);
|
||||
const matchesDirection = backward ? backRe.test(label) : forwardRe.test(label);
|
||||
@@ -294,18 +298,27 @@
|
||||
return backward ? backRe.test(label) : forwardRe.test(label);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
if (button && typeof button.click === 'function') {
|
||||
const clicks = Math.max(1, Math.min(12, Math.round(Math.abs(delta) / 10)));
|
||||
for (let i = 0; i < clicks; i++) {
|
||||
setTimeout(() => button.click(), i * 60);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fallback: Simulate ArrowLeft / ArrowRight keyboard events
|
||||
const clicks = Math.max(1, Math.min(12, Math.round(Math.abs(delta) / 10)));
|
||||
if (button && typeof button.click === 'function') {
|
||||
const clicks = Math.max(1, Math.min(12, Math.round(Math.abs(delta) / 10)));
|
||||
for (let i = 0; i < clicks; i++) {
|
||||
setTimeout(() => button.click(), i * 60);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fallback: Simulate ArrowLeft / ArrowRight keyboard events
|
||||
const clicks = Math.max(1, Math.min(12, Math.round(Math.abs(delta) / 10)));
|
||||
const eventInit = {
|
||||
key: backward ? 'ArrowLeft' : 'ArrowRight',
|
||||
code: backward ? 'ArrowLeft' : 'ArrowRight',
|
||||
keyCode: backward ? 37 : 39,
|
||||
which: backward ? 37 : 39,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
view: window
|
||||
};
|
||||
const target = document.querySelector('.hive-video') || document.activeElement || document.body;
|
||||
for (let i = 0; i < clicks; i++) {
|
||||
setTimeout(() => {
|
||||
target.dispatchEvent(new window.KeyboardEvent('keydown', eventInit));
|
||||
target.dispatchEvent(new window.KeyboardEvent('keyup', eventInit));
|
||||
|
||||
@@ -94,6 +94,8 @@ function loadTimelineFns(hostname, document = makeDocument()) {
|
||||
'let lastKnownDisneyPlusDuration = 0;',
|
||||
'let lastKnownDisneyPlusScale = 1;',
|
||||
'let lastKnownDisneyPlusStart = 0;',
|
||||
'let lastDisneyPlusUiCurrent = null;',
|
||||
'let lastDisneyPlusNativeAtUi = null;',
|
||||
extractFunction('scanShadowDom', source),
|
||||
extractFunction('querySelectorAllShadow', source),
|
||||
extractFunction('hostMatchesUrl', source),
|
||||
|
||||
Reference in New Issue
Block a user