mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
fix(playback): re-sync embedded MPV bounds on position-only layout shifts (#1476)
An ancestor re-layout can translate the player host without resizing it (sidebar content settling, EPG panel loading below the player). ResizeObserver reports size changes only and no DOM event observes "position changed", so the native child window silently kept its stale coordinates and rendered offset from the DOM stage. The session controller now polls the host bounds every 500 ms while a session is active, compares them against the last synced bounds with a half-pixel tolerance, and re-syncs only on drift — idle cost is one getBoundingClientRect per tick with no IPC. The interval is registered via NgZone.runOutsideAngular and never re-enters the zone, so zone change detection does not run every tick for the whole stream. Frame-copy sessions skip the measurement entirely: the canvas is laid out by the DOM and moves with the layout, so only the native-view child window can go stale on a position-only shift. Fixes #1428 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
069b8b3cc9
commit
7a3d5eae56
5 files changed
+346
-5
No files matched your search
@@ -667,6 +667,22 @@ re-armed `matchMedia('(resolution: …dppx)')` query and re-syncs bounds when
|
||||
it changes; page zoom changes are covered by the same watch plus the ordinary
|
||||
resize-driven syncs.
|
||||
|
||||
An ancestor re-layout can also translate the host **without resizing it** —
|
||||
the channel sidebar's content settling, panels loading below the player.
|
||||
`ResizeObserver` reports size changes only and no DOM event observes
|
||||
"position changed", so before #1428 the native child window silently kept its
|
||||
stale coordinates and rendered offset from the DOM stage. The session
|
||||
controller therefore polls the host bounds every 500 ms while a session is
|
||||
active, compares them against the last synced bounds with a half-pixel
|
||||
tolerance, and schedules a re-sync only on drift — idle cost is one
|
||||
`getBoundingClientRect` per tick with no IPC. The interval is registered
|
||||
outside Angular's zone (a zone timer would run app-wide change detection
|
||||
every tick for the whole stream) and never re-enters it, because the drift
|
||||
path is rAF → `setEmbeddedMpvBounds` IPC and touches no Angular state.
|
||||
Frame-copy skips the measurement entirely: its canvas is laid out by the
|
||||
DOM and moves with the layout, so only the native-view child window can go
|
||||
stale on a position-only shift.
|
||||
|
||||
### Controls ownership by engine
|
||||
|
||||
`EmbeddedMpvPlayerComponent` selects one control owner from
|
||||
|
||||
Reference in new issue
Block a user