diff --git a/libs/ui/playback/src/lib/embedded-mpv-player/embedded-mpv-overlay-visibility.service.ts b/libs/ui/playback/src/lib/embedded-mpv-player/embedded-mpv-overlay-visibility.service.ts new file mode 100644 index 000000000..6467706e8 --- /dev/null +++ b/libs/ui/playback/src/lib/embedded-mpv-player/embedded-mpv-overlay-visibility.service.ts @@ -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); + } + } +} diff --git a/libs/ui/playback/src/lib/embedded-mpv-player/embedded-mpv-player.component.ts b/libs/ui/playback/src/lib/embedded-mpv-player/embedded-mpv-player.component.ts index 84eca7385..b839ba6a0 100644 --- a/libs/ui/playback/src/lib/embedded-mpv-player/embedded-mpv-player.component.ts +++ b/libs/ui/playback/src/lib/embedded-mpv-player/embedded-mpv-player.component.ts @@ -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>('viewport'); readonly playerRoot = viewChild>('playerRoot'); readonly support = signal(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 {