refactor(settings): split the settings page into per-section facades (#1274)

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.
This commit is contained in:
4gray authored and GitHub committed 2026-07-26 22:57:16 +02:00
1 parent 08b868d6c1
commit f9ea3070ee
12 files changed
+931 -751

No files matched your search

@@ -38,8 +38,8 @@
[themeOptions]="themeOptions"
[coverSizeOptions]="coverSizeOptions"
[startupBehaviorOptions]="startupBehaviorOptions"
(selectTheme)="selectTheme($event)"
(selectCoverSize)="selectCoverSize($event)"
(selectTheme)="form.selectTheme($event)"
(selectCoverSize)="form.selectCoverSize($event)"
/>
<app-settings-playback-section
@@ -50,8 +50,8 @@
[isDesktop]="isDesktop"
[supportsManagedExternalPlayers]="supportsManagedExternalPlayers"
[supportsExternalPlayerPathSettings]="supportsExternalPlayerPathSettings"
[frameCopyAvailable]="frameCopyAvailable()"
[frameCopyActive]="frameCopyActive()"
[frameCopyAvailable]="embeddedMpv.frameCopyAvailable()"
[frameCopyActive]="embeddedMpv.frameCopyActive()"
(selectRecordingFolder)="selectRecordingFolder()"
/>
@@ -59,15 +59,15 @@
<app-settings-epg-section
[form]="settingsForm"
[activeSection]="activeSection()"
[epgUrl]="epgUrl"
[isClearingEpgData]="isClearingEpgData()"
[epgUrl]="form.epgUrl"
[isClearingEpgData]="epg.isClearing()"
[epgViewModeOptions]="epgViewModeOptions"
(refreshEpg)="refreshEpg($event)"
(removeEpgSource)="removeEpgSource($event)"
(addEpgSource)="addEpgSource()"
(refreshAllEpg)="refreshAllEpg()"
(clearEpgData)="clearEpgData()"
(selectEpgViewMode)="selectEpgViewMode($event)"
(refreshEpg)="epg.refresh($event)"
(removeEpgSource)="form.removeEpgSource($event)"
(addEpgSource)="form.addEpgSource()"
(refreshAllEpg)="epg.refreshAll()"
(clearEpgData)="epg.clear()"
(selectEpgViewMode)="form.selectEpgViewMode($event)"
/>
}
@@ -80,9 +80,9 @@
<app-settings-remote-control-section
[form]="settingsForm"
[activeSection]="activeSection()"
[localIpAddresses]="localIpAddresses()"
[visibleQrCodeIp]="visibleQrCodeIp()"
(toggleQrCode)="toggleQrCode($event)"
[localIpAddresses]="remoteControl.localIpAddresses()"
[visibleQrCodeIp]="remoteControl.visibleQrCodeIp()"
(toggleQrCode)="remoteControl.toggleQrCode($event)"
/>
}
@@ -94,33 +94,33 @@
<app-settings-backup-section
[activeSection]="activeSection()"
[isPwa]="isPwa"
[isRemovingAllPlaylists]="isRemovingAllPlaylists()"
[isExportingData]="isExportingData()"
[isRemovingAllPlaylists]="playlistReset.isRemovingAllPlaylists()"
[isExportingData]="backup.isExportingData()"
(importData)="importData()"
(exportData)="exportData()"
/>
<app-settings-reset-section
[activeSection]="activeSection()"
[isRemovingAllPlaylists]="isRemovingAllPlaylists()"
[canRemoveAllPlaylists]="canRemoveAllPlaylists()"
[playlistDeleteSummary]="playlistDeleteSummary()"
[removeAllProgressLabel]="removeAllProgressLabel()"
[isRemovingAllPlaylists]="playlistReset.isRemovingAllPlaylists()"
[canRemoveAllPlaylists]="playlistReset.canRemoveAll()"
[playlistDeleteSummary]="playlistReset.deleteSummary()"
[removeAllProgressLabel]="playlistReset.removeAllProgressLabel()"
(removeAll)="removeAll()"
/>
<app-settings-about-section
[activeSection]="activeSection()"
[isDesktop]="isDesktop"
[version]="version"
[version]="appUpdate.version()"
[buildCommit]="buildCommit"
[updateMessage]="updateMessage"
[appUpdateStatus]="appUpdateStatus()"
(checkForAppUpdate)="checkForAppUpdate()"
(downloadAppUpdate)="downloadAppUpdate()"
(installAppUpdate)="installAppUpdate()"
(openManualAppUpdate)="openManualAppUpdate()"
(openAppUpdateReleaseNotes)="openAppUpdateReleaseNotes()"
[updateMessage]="appUpdate.updateMessage()"
[appUpdateStatus]="appUpdate.status()"
(checkForAppUpdate)="appUpdate.checkForAppUpdate()"
(downloadAppUpdate)="appUpdate.downloadAppUpdate()"
(installAppUpdate)="appUpdate.installAppUpdate()"
(openManualAppUpdate)="appUpdate.openManualAppUpdate()"
(openAppUpdateReleaseNotes)="appUpdate.openReleaseNotes()"
/>
<footer class="action-bar" data-test-id="settings-action-bar">