From 32779f99a44a026267535d5a6a82a49d89495f1a Mon Sep 17 00:00:00 2001 From: 4gray Date: Tue, 5 May 2026 09:23:32 +0200 Subject: [PATCH] fix(embedded-mpv): detect MatDialog overlays, not just CDK backdrops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The command palette is a MatDialog with a transparent backdrop, and the prior MutationObserver-only detector did not reliably catch it across overlay-container instantiation timing — the player kept rendering at full bounds while the palette was open and continued occluding it. Subscribe directly to MatDialog.afterOpened / afterAllClosed for the authoritative "any modal dialog open" signal, and keep the OverlayContainer mutation observer as a fallback for non-dialog CDK overlays. Either signal flips overlayActive, hiding the embedded MPV view as before. Co-Authored-By: Claude Opus 4.7 (1M context) Entire-Checkpoint: f957cd9849e0 --- ...embedded-mpv-overlay-visibility.service.ts | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) 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 index 6467706e8..e5d5b3e40 100644 --- 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 @@ -1,29 +1,40 @@ import { Injectable, inject, signal } from '@angular/core'; import { OverlayContainer } from '@angular/cdk/overlay'; +import { MatDialog } from '@angular/material/dialog'; @Injectable({ providedIn: 'root' }) export class EmbeddedMpvOverlayVisibilityService { readonly overlayActive = signal(false); private readonly overlayContainer = inject(OverlayContainer); + private readonly dialog = inject(MatDialog); private observer: MutationObserver | null = null; constructor() { - if (typeof MutationObserver === 'undefined') { - return; + this.dialog.afterOpened.subscribe(() => this.recompute()); + this.dialog.afterAllClosed.subscribe(() => this.recompute()); + + if (typeof MutationObserver !== 'undefined') { + const container = this.overlayContainer.getContainerElement(); + this.observer = new MutationObserver(() => this.recompute()); + this.observer.observe(container, { + childList: true, + subtree: true, + }); } - const container = this.overlayContainer.getContainerElement(); - this.observer = new MutationObserver(() => this.recompute(container)); - this.observer.observe(container, { childList: true, subtree: true }); - this.recompute(container); + this.recompute(); } - private recompute(container: HTMLElement): void { - const hasBackdrop = - container.querySelector('.cdk-overlay-backdrop') !== null; - if (this.overlayActive() !== hasBackdrop) { - this.overlayActive.set(hasBackdrop); + private recompute(): void { + const dialogOpen = this.dialog.openDialogs.length > 0; + const backdropPresent = + this.overlayContainer + .getContainerElement() + .querySelector('.cdk-overlay-backdrop') !== null; + const next = dialogOpen || backdropPresent; + if (this.overlayActive() !== next) { + this.overlayActive.set(next); } } }