mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-14 21:26:15 -08:00
settings.component.ts had grown to 819 lines — past the CLAUDE.md target (<300) and hard maximum, passing lint only because it sat in the max-lines baseline. The behaviour moves into facades the template binds to directly, following the precedent already in this folder: new app-update (218), form (197), epg (123), embedded-mpv (74) and remote-control (37) facades, with playlist-reset extended to 143 and settings-options to 200. The component is now a 259-line coordinator holding capability flags, section nav, players() and the cross-facade flows. settings.component.ts is removed from the max-lines baseline. No behaviour change. One ordering detail: applyChangedSettings now applies language/theme before kicking off the EPG re-fetch; changeTheme only touches DOM theme sync and translate.use does not touch the form, so the two are independent.
75 lines
2.3 KiB
TypeScript
75 lines
2.3 KiB
TypeScript
import { computed, inject, Injectable, signal } from '@angular/core';
|
|
import { RuntimeCapabilitiesService } from '@iptvnator/services';
|
|
import { EmbeddedMpvSupport } from '@iptvnator/shared/interfaces';
|
|
|
|
/**
|
|
* Probes the desktop backend for embedded MPV support so the playback
|
|
* section can hide options the current build cannot deliver.
|
|
*/
|
|
@Injectable()
|
|
export class SettingsEmbeddedMpvFacade {
|
|
private readonly runtime = inject(RuntimeCapabilitiesService);
|
|
|
|
readonly support = signal<EmbeddedMpvSupport | null>(null);
|
|
|
|
readonly supported = computed(
|
|
() => this.runtime.isElectron && !!this.support()?.supported
|
|
);
|
|
|
|
readonly frameCopyAvailable = computed(
|
|
() => this.runtime.isElectron && !!this.support()?.frameCopyAvailable
|
|
);
|
|
|
|
readonly frameCopyActive = computed(
|
|
() => this.support()?.engine === 'frame-copy'
|
|
);
|
|
|
|
async load(): Promise<void> {
|
|
if (!this.runtime.isElectron) {
|
|
this.support.set({
|
|
supported: false,
|
|
platform: 'web',
|
|
reason: 'Embedded MPV requires the Electron desktop build.',
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (!window.electron?.getEmbeddedMpvSupport) {
|
|
this.support.set({
|
|
supported: false,
|
|
platform: window.electron.platform,
|
|
reason: 'Embedded MPV support is not available in this build.',
|
|
});
|
|
return;
|
|
}
|
|
|
|
try {
|
|
this.support.set(await window.electron.getEmbeddedMpvSupport());
|
|
} catch (error) {
|
|
this.support.set({
|
|
supported: false,
|
|
platform: window.electron.platform,
|
|
reason: error instanceof Error ? error.message : String(error),
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Opens the native folder picker for MPV recordings.
|
|
* @returns the selected folder, or null when the user cancelled or the
|
|
* desktop bridge cannot show the dialog
|
|
*/
|
|
async selectRecordingFolder(): Promise<string | null> {
|
|
if (
|
|
!this.runtime.isElectron ||
|
|
!window.electron?.selectEmbeddedMpvRecordingFolder
|
|
) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
(await window.electron.selectEmbeddedMpvRecordingFolder()) ?? null
|
|
);
|
|
}
|
|
}
|