Repository navigation
feat(playlists): switch movies, series and live TV off per playlist - #381
Open
TheDutchSmoke wants to merge 1 commit into
Open
TheDutchSmoke wants to merge 1 commit into
TheDutchSmoke wants to merge 1 commit into
Conversation
A playlist always fetched all three kinds. Each playlist now has three Content switches (Settings › Playlists › playlist): a kind that is off is skipped by the sync, what earlier syncs brought in is removed, and its tab leaves the tab bar. Storage follows hiddenTabsRaw: one comma-separated PlaylistTab set, Playlist.disabledContentRaw, defaulting to "" so existing stores migrate without a plan. It rides the playlist config through iCloud (SyncedPlaylist, PlaylistConfigValues with a decodeIfPresent fallback) and Lume Cloud (optional on the wire; a record an older client wrote still opens as "fetch everything"). Every pipeline guards its phases on Playlist.syncs(_:): Xtream and Stalker skip the kind's categories and content, Jellyfin/Emby/Silo and Plex walk no library of that kind, and the m3u/WebDAV import drops the kind's entries from each classified batch before the upsert. The removal is one place, ContentSyncManager.removeDisabledContent, run by performSync after any source so a switch flipped on another device applies here too. It uses PlaylistDeletion's per-kind deletes (factored out of removeOrphanedContent: paged movies and series so cast and episodes cascade, bulk live streams with the orphaned guide listings), prunes the kind's categories and drops its Xtream digest. The m3u prune skips the guarded sweeps of a disabled kind: its empty seen set would read as a truncated payload and hold the file fingerprint back forever. The switch in Settings saves, clears the m3u/WebDAV fingerprints (an unchanged file would otherwise skip the very import that applies it), reconciles cloud sync and starts a sync. The progress sheet lists only the steps that will run (SyncStep.steps(for:full:disabled:)). Sources without live channels don't offer the live switch. CloudSyncEngine's playlist apply helpers move to CloudSyncEngine+Playlists and the codec compatibility test to its own suite, both for the lint length limits. Paired with bilipp/LumeCloud: spec vectors and PROTOCOL.md gain the field. Tested on Xcode 27.2, iPhone 17 (iOS 27.2) simulator: LumeTests passes (the 15 new tests, every sync/cloud suite, and the full suite apart from failures that reproduce on main in this environment: missing ExampleData fixtures and a Dutch locale).
TheDutchSmoke
force-pushed
the
feat/per-playlist-content-sync
branch
from
November 7, 2026 11:05
4392807 to
6b4d735
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Each playlist gets three Content switches (Settings › Playlists › playlist, iOS/macOS and tvOS): Movies, Series and Live TV. A kind that is off is skipped by the sync, what earlier syncs brought in is removed from the library, and its tab leaves the tab bar. Sources without live channels (WebDAV, Jellyfin/Emby/Silo, Plex) don't offer the live switch.
Closes the request to fetch movies and series (and, for parity, live TV) selectively per provider.
How
hiddenTabsRaw: one comma-separatedPlaylistTabset,Playlist.disabledContentRaw, default""so existing stores migrate without a plan. Typed accessorsdisabledContent/syncs(_:);Playlist?.showsTabhides the tab of a disabled kind too.SyncedPlaylist,PlaylistConfigValueswith adecodeIfPresentfallback for shadow baselines written before the field) and Lume Cloud (optional on the wire: a record an older client wrote still opens as "fetch everything"). Paired spec change: spec: playlist payload carries disabledContentRaw LumeCloud#2.playlist.syncs(_:): Xtream and Stalker skip the kind's categories and content, Jellyfin/Emby/Silo and Plex walk no library of that kind, the m3u/WebDAV import drops the kind's entries from each classified batch (M3UClassifiedBatch.dropping) before the upsert.ContentSyncManager.removeDisabledContent, run byperformSyncafter any source, so a switch flipped on another device applies here as well. It usesPlaylistDeletion's per-kind deletes (factored out ofremoveOrphanedContent: paged movies and series so cast and episodes cascade, bulk live streams plus the orphaned guide listings), prunes the kind's categories and drops its Xtream digest. The m3u prune skips the guarded sweeps of a disabled kind: its empty seen set would read as a truncated payload and hold the file fingerprint back forever.SyncStep.steps(for:full:disabled:)).CloudSyncEngine's playlist apply helpers move toCloudSyncEngine+Playlists.swiftand the codec compatibility test to its own suite, both for the lint length limits. Footer string added to the catalog in all 10 languages.Tested
Xcode 27.2 (27B52), iPhone 17 simulator, iOS 27.2; LumeEngine v0.4.0, LumeRecorder v0.1.1, LumeCloud main + #2.
PlaylistTabTests(encode/decode, tab hiding, selectable kinds, translations),ContentSyncDisabledContentTests(m3u end to end: movies off, series+live off, off→on round trip, everything-on removes nothing;removeDisabledContentleaves other kinds and other playlists alone, cascades episodes, drops the kind's digest; progress steps; batch filter),CloudSyncPlaylistTabsTests(legacy baseline, both directions),LumeCloudPayloadCodecTests+LumeCloudPayloadCodecCompatTests(round trip, older record without the field).M3USyncTests,XtreamDigestSkipTests,ContentSyncPruneTests,LumeCloudIntegrationTests,LumeCloudVectorExportTests(against the regenerated vectors) all pass.LumeTestsrun: everything passes except failures that reproduce identically onmainin this environment (ungeneratedExampleData/fixtures, a Dutch system locale forSportsLabelsTests, andSportsResolveCacheTests), plus two wall-clockLumeEngineShutdownWaitTeststhat pass when run without the rest of the suite loading the machine.CODE_SIGNING_ALLOWED=NO). SwiftFormat and SwiftLint--strictclean on every changed file; xcstrings normalised.tvSyncSectionand usesTVOptionToggleRow.Notes for review
BinaryDependencies/FFmpeg.xcframeworkcopy with the map nested, as that script now does.MainTabView). Shout if you'd rather keep the two independent.