import { Component, input, output, ViewEncapsulation, ChangeDetectionStrategy, } from '@angular/core'; import { AbstractControl, FormArray, FormGroup, ReactiveFormsModule, } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatIconModule } from '@angular/material/icon'; import { MatInputModule } from '@angular/material/input'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatSlideToggleModule } from '@angular/material/slide-toggle'; import { MatTooltipModule } from '@angular/material/tooltip'; import { EpgViewMode } from '@iptvnator/shared/interfaces'; import { EpgSourceStatusComponent } from '@iptvnator/ui/epg'; import { TranslateModule } from '@ngx-translate/core'; import { EpgViewModeOption } from './settings.models'; import { markSectionForCheckOnFormEvents } from './settings-section-form-render'; @Component({ selector: 'app-settings-epg-section', imports: [ EpgSourceStatusComponent, MatButtonModule, MatFormFieldModule, MatIconModule, MatInputModule, MatProgressSpinnerModule, MatSlideToggleModule, MatTooltipModule, ReactiveFormsModule, TranslateModule, ], templateUrl: './settings-epg-section.component.html', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styleUrls: ['./settings-epg-section.component.scss'], }) export class SettingsEpgSectionComponent { readonly form = input.required(); constructor() { // Parent patches (Discard, backup import) change the form outside // this OnPush section's events. markSectionForCheckOnFormEvents(this.form); } readonly epgUrl = input.required(); readonly isClearingEpgData = input(false); readonly canBrowseFiles = input(false); readonly epgViewModeOptions = input.required(); readonly refreshEpg = output(); readonly browseEpgSource = output(); readonly removeEpgSource = output(); readonly addEpgSource = output(); readonly refreshAllEpg = output(); readonly clearEpgData = output(); readonly selectEpgViewMode = output(); /** Minutes one stepper click shifts the displayed times by */ readonly offsetStep = 30; get offsetControl(): AbstractControl | null { return this.form().get('epgOffsetMinutes'); } /** * Moves the offset by one step within the accepted range. Typed values * keep going through the control's own validation; only the buttons * clamp, so an out-of-range typed value snaps back into range. */ stepOffset(delta: number): void { const control = this.offsetControl; if (!control) return; const current = Number(control.value); const next = Math.max( EPG_OFFSET_MIN, Math.min( EPG_OFFSET_MAX, (Number.isFinite(current) ? current : 0) + delta ) ); control.setValue(next); control.markAsDirty(); this.form().markAsDirty(); } } const EPG_OFFSET_MIN = -720; const EPG_OFFSET_MAX = 720;