Skip to content

iOS offline downloads with background sessions and position sync #135

Description

@altaywtf

Parent

#123

What this delivers

Offline downloads on the new iOS app: background video and audio downloads, a managed queue, offline playback, and server-synced watch positions. Existing downloads in the current app are not migrated.

Ownership

This feature owns its simultaneous-download limit, queue persistence, storage accounting, and local completion-notification permission. Settings #138 assembles links to those controls but does not reimplement them.

Scope

  • Download HLS assets through AVAssetDownloadURLSession with background-session restoration after relaunch or reboot, alongside audio-file downloads.
  • Manage a persisted queue with the configurable concurrency limit, numeric per-item progress, pause, cancel, multi-select delete, retry, and partial-failure reporting.
  • Request local completion-notification permission within the download flow and surface storage accounting in the downloads screen.
  • From one explicit action, hand a single unsupported file through conversion completion into download without losing its queue identity, while showing conversion and download as distinct stages.
  • Inventory available audio languages before download and let the user select one or more tracks within a disclosed, bounded storage budget.
  • Preserve every selected audio track in downloaded media, select the preferred language when present with a predictable fallback, and allow switching among all downloaded tracks offline.
  • Disclose the stored audio and subtitle tracks in download details, while keeping existing single-audio downloads working.
  • Play through the shared player slices while offline, record positions locally, and sync them when connectivity returns.
  • Choose the queue/state persistence mechanism in this slice and record it as a repository pattern; the current app's Realm choice is not a constraint.

Acceptance criteria

  • A download started before the app is killed and the device relocks completes and survives relaunch
  • The concurrency limit is respected across mixed video and audio queues
  • One explicit action moves a single unsupported file from conversion to download under one queue identity and retains selectable audio tracks
  • Before download, a multi-audio asset lists its language tracks and accepts a bounded one-or-more-track selection with visible storage impact
  • Offline playback can switch among every downloaded audio track, selects the preferred language when present, and uses a predictable fallback otherwise
  • Download details disclose stored audio and subtitle tracks, and existing single-audio downloads remain regression-free
  • Offline playback works in airplane mode and positions sync after reconnect
  • Removing offline items reclaims storage and updates accounting
  • Completion permission, notification, retry, and partial-failure states are recoverable

Verification

Unit tests cover queue persistence, limits, conversion handoff, pre-download track inventory, bounded multi-audio selection, preferred-language fallback, stored-track disclosure, single-audio regression, relaunch, offline track switching, accounting, and sync. Physical-device proof covers background completion and airplane-mode playback; simulator proof alone is insufficient.

Blocked by

Boundaries

No migration of existing downloads. Batch and folder offline UX beyond current-app parity remains post-v1 #92.

Verified checkpoint — 2026-09-10

#219 merged as 9276e88. A Downloads tab backed by a JSON-persisted queue and AVAssetDownloadURLSession: multi-audio inventory and bounded selection with a storage estimate, conversion-then-download under one identity, configurable concurrency, pause/resume/retry/multi-select remove, details disclosing stored tracks, offline playback with preferred-language selection, local position recording with sync on foreground and across relaunch, storage accounting, completion notifications, per-account queues, and account-keyed background tasks with a relay journal so a finished download survives a background relaunch. The queue document under Application Support is the recorded persistence pattern.

Simulator proof: the downloads preflight in the files-browser journey covers inventory, bounded selection, completion, details, offline playback selecting Turkish, pending position across relaunch, sync, and removal.

Remaining on a physical device: background completion after the device relocks, and airplane-mode playback.

Verified checkpoint — 2026-09-13

#229 (0e07df3), #230 (cf602a0), and #234 (d8111fd) closed #106: removing a download can also ask put.io for the original through a separately worded destructive choice. The local copy goes first; remote failures report per file with a retry; owed originals persist across relaunch, sign-out, and purge; the Trash setting is confirmed from the server before each request and a changed setting refuses instead of deleting permanently; loaded folders reconcile. #223 (070b0f9) purges packages a quarantined queue no longer lists.

Real-account proof on the devs-auto profile: download from the live harness folder, remove with move-to-Trash, folder reconciled, original confirmed in Trash through the CLI.

Follow-ups: #232 (completed row reads Zero kB), #233 (store swallows write failures), #235 (refresh loaded folders after a lost-response failure).

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions