Skip to content

Fix tvOS episode focus (#1640)#1819

Open
3aa49ec6bfc910647fa1c5a013e48eef wants to merge 6 commits intojellyfin:mainfrom
3aa49ec6bfc910647fa1c5a013e48eef:feature/1640-tvos-focus
Open

Fix tvOS episode focus (#1640)#1819
3aa49ec6bfc910647fa1c5a013e48eef wants to merge 6 commits intojellyfin:mainfrom
3aa49ec6bfc910647fa1c5a013e48eef:feature/1640-tvos-focus

Conversation

@3aa49ec6bfc910647fa1c5a013e48eef

Summary

  • stabilize SeriesEpisodeSelector.EpisodeHStack by introducing an EpisodeFocusCoordinator that queues pending IDs,
    defers FocusState writes via withTransaction + DispatchQueue.main.async, and ensures placeholders/episodes share a
    single focus path.
  • add UIDevice.platformGeneration (tvOS only) so EpisodeHStack can give older Apple TV hardware a slightly longer
    scroll delay when jumping to the play-button item.
  • keep focus logging scoped to seriesEpisodeFocus so we can trace season switches, pending focus consumption, and
    guard rails in Console.

Addresses #1640.

Testing

  • carthage update --use-xcframeworks
  • swiftformat .
  • swiftgen config run
  • bundle exec fastlane buildLane scheme:"Swiftfin tvOS" (DEVELOPER_DIR=/Applications/Xcode-16.4.0.app)

Pending steps (have not yet done any hardware testing)

  • tvOS 26 hardware (Apple TV 4K gen3): season hopping, empty/error/loading states, “Next Up” mid-season
  • tvOS 18.5 hardware: reproduce prior focus loss and verify fix with same scenarios
  • tvOS simulators (18.4, 26): smoke focus tests (no regressions/crashes)

@JPKribs
Copy link
Member

JPKribs commented Nov 25, 2025

I don't believe this is the correct approach. The ideal route for this would be to handle the scroll based on viewModel.state but track it so it doesn't scroll after the first scroll.

Just increasing the delay will still result in issues if there is a delay loading or low/poor network conditions.


Edit: Please see the changes I have made to this and please confirm that this works for you. I've moved this logic to confirm that viewModel.state == .content to ensure that the content is loaded prior to scrolling. I also changed this to load based on the first appearance of the EpisodeCard instead of the HStack. Since, the HStack loads in prior to the cards and we cannot scroll the cards if they don't exist. Loading on the appearance of the cards ensures that content we are loading exists prior to scrolling. Ensuring we are on .content prevents us from scrolling during the loadingCard.

This should now always trigger in order regardless of OS/Jellyfin delays but I would appreciate you validating this from your end as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working tvOS Impacts tvOS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants