Skip to content

Remember the last-picked audio/subtitle track per item - #74

Merged
imbenjamin merged 2 commits into
developfrom
feature/player-track-preference-memory
Aug 15, 2026
Merged

Remember the last-picked audio/subtitle track per item#74
imbenjamin merged 2 commits into
developfrom
feature/player-track-preference-memory

Conversation

@imbenjamin

Copy link
Copy Markdown
Owner

What

Adds a small QOL feature: the player now remembers the audio/subtitle track a user last explicitly picked for an item, and restores it the next time they play that same item — instead of always falling back through the default/forced-subtitle selection.

  • Fresh item / no playback history → unchanged: default selection (including forced-subtitle auto-select) applies exactly as before.
  • User changes audio and/or subtitle track during playback → both choices are persisted independently.
  • Subtitles explicitly turned off is itself a real remembered choice, distinct from "never touched."

How

  • New TrackPreferenceStore (Core/Persistence/), modeled directly on MediaVersionPreferenceStore — plain per-user UserDefaults, keyed by item id.
  • PlayerViewModel.selectAudioTrack(id:)/selectSubtitleTrack(id:) now persist the track's {id, title} (or .off) alongside delegating to the engine.
  • PlayerViewModel.start() restores the stored choice right after engine.load(...) returns, overriding whatever default AetherPlaybackEngine (including its forced-subtitle auto-select) already settled on.

Why title, not just id

Track ids are physical container positions, not stable identifiers — the same id can point at a different track next time if the layout reorders (a different version resolved, a re-mux) even with the track count unchanged. Each stored choice carries the track's own title, and a restore only applies when both the id and title still match the freshly loaded track list — otherwise it's skipped, same "fall back gracefully" treatment as elsewhere in this codebase (requestedMediaSourceID).

Testing

  • TrackPreferenceStoreTests.swift (new) + 7 new/updated cases in PlayerViewModelTests.swift, including the id-matches-but-title-doesn't scenario.
  • Full suite: 432/432 passing.
  • Manually verified in the Simulator.

🤖 Generated with Claude Code

Adds TrackPreferenceStore, a per-user/per-item UserDefaults store
(modeled on MediaVersionPreferenceStore) that records the audio
track and subtitle track (or explicit "Off") a user last picked
during playback.

PlayerViewModel.start() restores that choice right after
engine.load() returns, overriding whatever default/forced-subtitle
selection the engine just settled on. A fresh item with no history
falls through to that existing default behavior unchanged.

Track ids are physical container positions, not stable identifiers,
so a stored choice also carries the track's title and is only
restored when a track with the same id *and* title still exists in
the freshly loaded list — guards against both a track disappearing
entirely and a reordered layout silently reassigning an id to a
different track.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@imbenjamin imbenjamin linked an issue Aug 15, 2026 that may be closed by this pull request
@imbenjamin
imbenjamin merged commit 92fa646 into develop Aug 15, 2026
2 checks passed
@imbenjamin
imbenjamin deleted the feature/player-track-preference-memory branch August 15, 2026 19:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Subtitles and audio switching

1 participant