Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | 3x 3x 3x 3x 3x 3x 3x 3x 3x 41x 41x 41x 41x 41x 41x 3x 1x 2x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 41x | import { PictureLightboxService } from '../../services/pictures/picture-lightbox.service';
import { DOCUMENT } from '@angular/common';
import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, HostListener, inject, viewChild } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { RouterLink } from '@angular/router';
import { LoggerService } from '@drevo-web/core';
import { IconButtonComponent, SpinnerComponent } from '@drevo-web/ui';
import { filter, fromEvent } from 'rxjs';
@Component({
selector: 'app-picture-lightbox',
imports: [IconButtonComponent, RouterLink, SpinnerComponent],
templateUrl: './picture-lightbox.component.html',
styleUrl: './picture-lightbox.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PictureLightboxComponent {
protected readonly lightboxService = inject(PictureLightboxService);
private readonly document = inject(DOCUMENT);
private readonly destroyRef = inject(DestroyRef);
private readonly logger = inject(LoggerService).withContext('PictureLightbox');
private readonly backdropEl = viewChild<ElementRef<HTMLElement>>('backdropEl');
constructor() {
this.listenFullscreenChange();
}
@HostListener('document:keydown.escape')
onEscape(): void {
if (!this.lightboxService.isOpen()) {
return;
}
if (this.lightboxService.isZoomed() && !this.document.fullscreenElement) {
this.lightboxService.toggleZoom();
} else Eif (!this.lightboxService.isZoomed()) {
this.lightboxService.close();
}
}
onBackdropClick(event: MouseEvent): void {
Eif ((event.target as HTMLElement).classList.contains('lightbox__backdrop')) {
this.lightboxService.close();
}
}
onImageClick(): void {
const willZoom = !this.lightboxService.isZoomed();
this.lightboxService.toggleZoom();
if (willZoom) {
this.enterFullscreen();
} else E{
this.exitFullscreen();
}
}
onDetailLinkClick(): void {
this.logger.info('Navigating to picture detail', { id: this.lightboxService.currentPicture()?.id });
this.exitFullscreen();
this.lightboxService.closeWithoutNavigation();
}
private enterFullscreen(): void {
const el = this.backdropEl()?.nativeElement;
Iif (el?.requestFullscreen && !this.document.fullscreenElement) {
el.requestFullscreen().catch(() => {
// Fullscreen may be blocked by browser policy — zoom still works without it
});
}
}
private exitFullscreen(): void {
Iif (this.document.fullscreenElement) {
this.document.exitFullscreen().catch(() => {
// Fullscreen exit may fail if already exited
});
}
}
private listenFullscreenChange(): void {
fromEvent(this.document, 'fullscreenchange')
.pipe(
filter(() => !this.document.fullscreenElement && this.lightboxService.isZoomed()),
takeUntilDestroyed(this.destroyRef)
)
.subscribe(() => {
this.lightboxService.toggleZoom();
});
}
}
|