import { ChangeDetectionStrategy, Component, computed, inject, input, } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { Store } from '@ngrx/store'; import { TranslatePipe } from '@ngx-translate/core'; import { PlaylistActions, selectPlaylistsLoadFailed, selectPlaylistsLoadingFlag, } from '@iptvnator/m3u-state'; /** The first route also waits for settings and XMLTV source reconciliation. */ @Component({ selector: 'app-startup-status', changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatButtonModule, MatProgressSpinnerModule, TranslatePipe], template: ` @if (!complete()) {
@if (!failed()) {
} `, styles: ` :host { display: contents; } section { app-region: drag; position: relative; isolation: isolate; overflow: clip; min-height: 100dvh; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; padding: 48px 24px; box-sizing: border-box; background: var(--app-content-bg); color: var(--app-heading-color); text-align: center; } .startup-watermark { position: absolute; right: -14%; bottom: -34%; width: clamp(420px, 76vw, 960px); height: auto; opacity: 0.07; transform: rotate(-14deg); mask-image: linear-gradient(135deg, transparent 15%, #000 78%); pointer-events: none; z-index: 0; } section > :not(svg) { position: relative; z-index: 1; } h1 { margin: 0; font-size: 18px; font-weight: 500; } p { margin: 0; max-width: 420px; color: var(--app-body-color); line-height: 1.5; } button { margin-top: 8px; app-region: no-drag; } `, }) export class AppStartupStatusComponent { private readonly store = inject(Store); readonly routeReady = input(false); private readonly sourcesReady = this.store.selectSignal( selectPlaylistsLoadingFlag ); readonly failed = this.store.selectSignal(selectPlaylistsLoadFailed); readonly complete = computed( () => this.routeReady() && this.sourcesReady() ); retry(): void { this.store.dispatch(PlaylistActions.loadPlaylists()); } }