Keep the video info carousel aligned across window resizes

The carousel's lazy stack kept the old widths of cards it had laid out
off-screen, so after a resize (tab bar to split view sidebar on iPad,
rotation) every later card sat at a stale offset and the current card
landed beside the viewport. The stack now takes a new identity per
card width, and the existing re-snap aligns the current card.

Swapping between the tab bar and the sidebar also rebuilds the page,
which reset the carousel to the video it was opened on. The page's
position and continuation-loaded videos now live on its queue context,
fresh for every push, so a rebuilt page resumes where it was.
This commit is contained in:
Arkadiusz Fal
2026-10-14 08:22:58 +02:00
parent 97288b4497
commit fd6a97ce5c
3 changed files with 33 additions and 2 deletions

View File

@@ -19,6 +19,16 @@ struct MediaBrowserPlaybackInfo: Equatable, Hashable {
let allFilesInFolder: [MediaFile]
}
/// Where a video info page has got to in its queue. A layout swap (tab bar ↔
/// split view sidebar) rebuilds the page from its path entry, so this lives on
/// the entry's context rather than in the page's view state.
/// `NavigationRouter.push` gives every pushed page its own instance.
final class VideoInfoPageState {
var currentVideoIndex: Int?
/// Videos appended through continuation loading, past the original list.
var extendedVideoList: [Video] = []
}
/// Context information for playing a video with queue support.
/// Used when navigating from list views (subscriptions, search, etc.) to video info pages.
struct VideoQueueContext {
@@ -51,6 +61,9 @@ struct VideoQueueContext {
/// Position requested by an opened timed link (`?t=`). Unlike `startTime`
/// (a resume position), it is honored as-is and skips the resume prompt.
var linkStartTime: TimeInterval? = nil
/// Page position kept across rebuilds; ignored by equality and hashing.
var pageState = VideoInfoPageState()
/// Whether this context has valid queue information
var hasQueueInfo: Bool {