mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
fix: hide embedded MPV view while modal overlays are open
The embedded MPV player is a native NSView that sits above the WebContents layer, so DOM dialogs (command palette, MatDialog, etc.) always paint behind it regardless of z-index. Track CDK overlay backdrops via OverlayContainer + MutationObserver and send off-screen bounds to the native view while any backdrop is present, restoring real bounds on close. Playback continues uninterrupted. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Entire-Checkpoint: f957cd9849e0
This commit is contained in:
1 parent
e192cba776
commit
1c499856ab
2 files changed
+54
-4
No files matched your search
+29
@@ -0,0 +1,29 @@
|
||||
import { Injectable, inject, signal } from '@angular/core';
|
||||
import { OverlayContainer } from '@angular/cdk/overlay';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class EmbeddedMpvOverlayVisibilityService {
|
||||
readonly overlayActive = signal(false);
|
||||
|
||||
private readonly overlayContainer = inject(OverlayContainer);
|
||||
private observer: MutationObserver | null = null;
|
||||
|
||||
constructor() {
|
||||
if (typeof MutationObserver === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
const container = this.overlayContainer.getContainerElement();
|
||||
this.observer = new MutationObserver(() => this.recompute(container));
|
||||
this.observer.observe(container, { childList: true, subtree: true });
|
||||
this.recompute(container);
|
||||
}
|
||||
|
||||
private recompute(container: HTMLElement): void {
|
||||
const hasBackdrop =
|
||||
container.querySelector('.cdk-overlay-backdrop') !== null;
|
||||
if (this.overlayActive() !== hasBackdrop) {
|
||||
this.overlayActive.set(hasBackdrop);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,11 +7,20 @@ import {
|
||||
Output,
|
||||
computed,
|
||||
effect,
|
||||
inject,
|
||||
input,
|
||||
signal,
|
||||
untracked,
|
||||
viewChild,
|
||||
} from '@angular/core';
|
||||
import { EmbeddedMpvOverlayVisibilityService } from './embedded-mpv-overlay-visibility.service';
|
||||
|
||||
const HIDDEN_BOUNDS = Object.freeze({
|
||||
x: -100000,
|
||||
y: -100000,
|
||||
width: 1,
|
||||
height: 1,
|
||||
});
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
@@ -42,6 +51,10 @@ export class EmbeddedMpvPlayerComponent implements OnDestroy {
|
||||
duration: number;
|
||||
}>();
|
||||
|
||||
private readonly overlayVisibility = inject(
|
||||
EmbeddedMpvOverlayVisibilityService
|
||||
);
|
||||
|
||||
readonly viewport = viewChild<ElementRef<HTMLDivElement>>('viewport');
|
||||
readonly playerRoot = viewChild<ElementRef<HTMLDivElement>>('playerRoot');
|
||||
readonly support = signal<EmbeddedMpvSupport | null>(null);
|
||||
@@ -242,11 +255,14 @@ export class EmbeddedMpvPlayerComponent implements OnDestroy {
|
||||
return;
|
||||
}
|
||||
|
||||
const bounds = untracked(() =>
|
||||
this.overlayVisibility.overlayActive()
|
||||
)
|
||||
? HIDDEN_BOUNDS
|
||||
: this.measureBounds(host);
|
||||
|
||||
void window.electron
|
||||
.setEmbeddedMpvBounds(
|
||||
activeSessionId,
|
||||
this.measureBounds(host)
|
||||
)
|
||||
.setEmbeddedMpvBounds(activeSessionId, bounds)
|
||||
.catch(() => undefined);
|
||||
};
|
||||
|
||||
@@ -364,6 +380,11 @@ export class EmbeddedMpvPlayerComponent implements OnDestroy {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
effect(() => {
|
||||
this.overlayVisibility.overlayActive();
|
||||
untracked(() => this.activeBoundsSync?.());
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
|
||||
Reference in new issue
Block a user