Download - Extramovies.foundation - -18 - Sala... [LATEST]

func cancel(downloadID: UUID) activeTasks[downloadID]?.cancel() activeTasks.removeValue(forKey: downloadID)

The Android counterpart would use WorkManager + OkHttp with Range headers. | Platform | Library | Typical Call‑Flow | |----------|---------|-------------------| | Android | ExoPlayer + Widevine | DrmSessionManager receives the license token, negotiates with the license server, then streams the decrypted file from local storage. | | iOS | AVFoundation + FairPlay | AVContentKeySession obtains the offline content key using the token, then AVAssetDownloadURLSession stores the encrypted file. | 4.4. Storage Layout (Example) /AppSandbox/Offline/ ├─ <titleId>_<deviceId>.mp4.enc ← encrypted video file ├─ <titleId>_metadata.json ← expiryDate, drmInfo, size └─ manifest.db ← SQLite DB tracking all assets Encryption can be performed with AES‑256‑GCM using a per‑device key derived from the user’s secure keystore. 5. UI Mock‑up (Text Description) | Screen | Elements | |--------|----------| | Title Detail | - Poster / trailer - “Download” button (enabled only if eligible) - Age‑check dialog (if needed) | | Download Queue | - List of pending/active downloads - Each row: thumbnail, title, progress bar, ETA, “Pause/Resume”, “Cancel” | | Offline Library | - Grid of downloaded titles - Expiry badge (e.g., “Expires in 5 days”) - “Delete” icon on each tile | | Settings | - “Maximum offline storage” slider - “Download speed limit” selector (Off / Low / Medium / High) |

All endpoints must be served over and enforce OAuth2/JWT authentication. 4.2. Mobile Client (iOS / Android) – Pseudocode Sketch // Swift (iOS) – DownloadManager skeleton class DownloadManager static let shared = DownloadManager() private var activeTasks: [UUID: URLSessionDownloadTask] = [:] Download - ExtraMovies.foundation - -18 - Sala...

func startDownload(titleID: String, deviceID: String) async throws // 1️⃣ Verify eligibility via API let eligibility = try await API.checkEligibility(titleID: titleID) guard eligibility.eligible else throw DownloadError.notEligible

// 4️⃣ Create a resumable download task let task = URLSession.shared.downloadTask(with: url) localURL, response, error in // Handle completion: move file, encrypt, store metadata task.resume() activeTasks[UUID()] = task func cancel(downloadID: UUID) activeTasks[downloadID]

func pause(downloadID: UUID) activeTasks[downloadID]?.suspend()

// 3️⃣ Build download URL (includes token as query param) let url = URL(string: "https://cdn.extramovies.foundation/content/\(titleID)?token=\(license.licenseToken)")! UI Mock‑up (Text Description) | Screen | Elements

// 2️⃣ Request DRM license token let license = try await API.requestLicense(titleID: titleID, deviceID: deviceID)