Handle alternate enclosures in all possible paths#4688
Open
leandroalonso wants to merge 6 commits into
Open
Conversation
Collaborator
Generated by 🚫 Danger |
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR ensures an episode’s hlsUrl is populated across all relevant server → DB ingestion paths (incremental refresh, Up Next sync, and episode-update flows), enabling HLS video playback without waiting for a full feed refresh.
Changes:
- Decode/store HLS URLs from refresh-server JSON (
alternate_enclosures) and protobuf sync (Api_AlternateEnclosure), and thread them through Up Next syncing and DB insertion. - Update server-side episode refresh/update logic to carry
hlsUrlinto existing episodes. - Add unit tests for HLS decoding (JSON + protobuf) and for
hlsUrlpersistence.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| Modules/Tests/PocketCastsServerTests/RefreshEpisodeHLSTests.swift | Adds tests for decoding refresh-server alternate_enclosures into RefreshEpisode.hlsUrl and Episode.populate(fromEpisode:). |
| Modules/Tests/PocketCastsServerTests/AlternateEnclosureHLSTests.swift | Adds tests for extracting HLS URLs from protobuf Api_AlternateEnclosure arrays. |
| Modules/Tests/PocketCastsDataModelTests/EpisodeHLSUrlPersistenceTests.swift | Verifies hlsUrl persists and can be updated via DB save/load. |
| Modules/Sources/PocketCastsServer/Public/Sync/UpNextSyncTask.swift | Populates hlsUrl during Up Next sync for both existing local episodes and server-fetched ones. |
| Modules/Sources/PocketCastsServer/Public/Sync/Api_AlternateEnclosure+HLS.swift | Adds helper to extract HLS URL from protobuf alternate enclosures. |
| Modules/Sources/PocketCastsServer/Public/Sharing/Structs/UpNextItem.swift | Extends UpNextItem to carry an optional hlsUrl through the add-to-DB flow. |
| Modules/Sources/PocketCastsServer/Public/Sharing/Structs/ServerStructs.swift | Decodes refresh-server alternate_enclosures and exposes RefreshEpisode.hlsUrl. |
| Modules/Sources/PocketCastsServer/Public/ServerPodcastManager.swift | Persists hlsUrl when adding episodes from Up Next and when updating an existing episode. |
| Modules/Sources/PocketCastsServer/Private/Protobuffer/api.pb.swift | Regenerates SwiftProtobuf models to include alternate enclosures and other new API fields. |
| Modules/Sources/PocketCastsServer/Private/Episode+Populate.swift | Sets Episode.hlsUrl when populating from RefreshEpisode (incremental refresh path). |
| Modules/Sources/PocketCastsDataModel/Public/Model/Episode+fromDictionary.swift | Makes Episode.hlsEnclosureType public so the Server module can reuse the canonical MIME type. |
The protobuf Source.uri defaults to "" and a refresh payload could carry an empty uri; the app treats an empty hlsUrl as "missing" (isStreamingHLS), so normalise "" to nil at the source rather than persisting a bogus present-but-empty value. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The server can omit alternate enclosures on an episode-update response, so only overwrite hlsUrl when a non-empty value is present — otherwise we'd wipe a url a feed refresh already stored and regress HLS playback. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Member
Author
Review feedback addressed
|
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.
Fixes POC-709
Populates an episode's
hlsUrlon every server → DB path that carries it, so episodes can stream HLS without having to wait for a full podcast refresh. Previously only the feed-refresh (full podcast) path set it, leaving several common paths — most importantly the incremental refresh that delivers new episodes — with no HLS url.Changes
api.pb.swiftfromsync-api. New definitions includeApi_AlternateEnclosure(type+sources[].uri, onEpisodeResponseandUpNextResponse.EpisodeResponse), a stats heatmap (Api_StatsHeatmapRequest/Response,Api_HeatmapDay), and anupNextSortTooltipSeensetting./user/update) —RefreshEpisodenow decodesalternate_enclosuresandEpisode.populate(fromEpisode:)setshlsUrl. This is the highest-traffic path (new episodes for subscribed podcasts, delivered on foreground / background / push / pull-to-refresh). Pairs with refresh-server #596 (merged), which adds the field to that response.hlsUrlfromalternateEnclosureswhether it's already local (UpNextSyncTask) or fetched fresh (threaded throughUpNextItem→addToDatabase).ServerPodcastManager.addEpisodenow carrieshlsUrlwhen refreshing an existing episode (previously omitted).Api_AlternateEnclosure+HLS.swift/RefreshEpisode.hlsUrl— helpers that mirrorEpisode.hlsUrl(fromEpisodeJson:)(matchapplication/x-mpegURL, case-insensitive, first source URI).Episode.hlsEnclosureTypepublicso the Server module can reuse it.Notes
hlsUrlwrites are not gated behindFeatureFlag.hls— like the existing feed-refresh path, we always store the url; the flag only gates whether it's used for streaming (EpisodeManager.isStreamingHLS).Api_EpisodeResponse.alternate_enclosures(field 21) still isn't read anywhere in the app, so any future protobuf episode endpoint would need wiring — but every path that exists today is now covered.To test
Checklist
CHANGELOG.mdif necessary.