# Download Manager Implementation Plan

## Overview
Add a full-featured download manager with multi-connection segmented downloading (16 segments), a Share Extension to receive URLs from Safari, and a new "Downloads" tab in the app.

## Architecture

### New Files to Create

```
FMHY X IOS/
├── Services/
│   └── FMDownloadManager.swift        # Core download engine (multi-connection, segmented)
├── Views/
│   ├── DownloadsView.swift             # New tab: list of all downloads with progress
│   └── DownloadRowView.swift           # Single download row (name, progress, speed, actions)
├── FMHY Share Extension/               # NEW TARGET: Share Extension
│   ├── ShareViewController.swift       # Receives URL from Safari share sheet
│   └── Info.plist                      # NSExtension config
```

### Existing Files to Modify

| File | Change |
|------|--------|
| `FMHY X IOS.xcodeproj/project.pbxproj` | Add Share Extension target, add new Swift files to main target |
| `FMHY_X_IOSApp.swift` | Register for URL opens from Share Extension |
| `MainTabView.swift` | Add 5th "Downloads" tab, inject `FMDownloadManager` as environmentObject |
| `FMHY X IOS.entitlements` | Add App Groups entitlement (required for Share Extension → main app data sharing) |

---

## Step 1: Git Backup Commit

Before any code changes, create a git commit preserving the current working state.

```bash
git add -A && git commit -m "Pre-download-manager backup"
```

---

## Step 2: FMDownloadManager Service

**File: `Services/FMDownloadManager.swift`**

Core download engine. Responsibilities:
- Accept a URL, perform HEAD request to detect file size + Range support
- If server supports Range: split into N segments (default 16, fallback to 1 if no Range support)
- Open up to 16 parallel `URLSession.dataTask` connections, each requesting a byte range
- Track per-segment progress, combine into a single file in the destination directory
- Publish `@Published var downloads: [DownloadItem]` for UI binding
- Support pause (cancel unfinished segments, save byte offsets), resume (re-request remaining ranges), cancel (delete partial file)

**DownloadItem model** (nested in the service or a separate model file):
```swift
struct DownloadItem: Identifiable, Codable {
    let id: UUID
    let url: URL
    let fileName: String
    var totalBytes: Int64
    var downloadedBytes: Int64
    var status: DownloadStatus  // waiting, downloading, paused, completed, failed
    var speed: Double           // bytes per second (rolling average)
    var segments: [SegmentInfo]
    var destinationURL: URL?
    var createdAt: Date
    var completedAt: Date?
}

struct SegmentInfo: Codable {
    let startIndex: Int64
    var downloadedBytes: Int64
    var isComplete: Bool
}
```

**Key implementation details:**
- Use a single `URLSession` with a custom `OperationQueue` limited to 16 concurrent operations
- Rolling speed calculation: track bytes downloaded per second over a 2-second window
- Segment data written to temp files in a `segments/` subdirectory under the download destination
- On completion: concatenate segment files in order, then delete temp segment files
- Persist `DownloadItem` array to disk (JSON in caches directory) so downloads survive app restarts
- On app launch: check for incomplete downloads and offer to resume

---

## Step 3: Share Extension Target

**New Xcode Target: `FMHY Share Extension`**

A Share Extension that appears in Safari's share sheet. When the user taps "FMHY" from the share sheet, it captures the shared URL and passes it to the main app's download manager.

**How it works:**
1. Share Extension receives an `NSExtensionContext` with the shared URL
2. Writes the URL to a shared `UserDefaults` suite (App Groups)
3. Opens the main app via `openURL` scheme
4. Main app reads the pending URL from shared UserDefaults and starts the download

**Info.plist configuration:**
```xml
<key>NSExtension</key>
<dict>
    <key>NSExtensionAttributes</key>
    <dict>
        <key>NSExtensionActivationRule</key>
        <string>SUBQUERY (
            extensionItems,
            $extensionItem,
            SUBQUERY (
                $extensionItem.attachments,
                $attachment,
                ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.url"
            ).@count == $extensionItem.attachments.@count
        ).@count == 1</string>
    </dict>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.share-services</string>
</dict>
```

**ShareViewController.swift** (minimal — just captures URL and redirects):
```swift
class ShareViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        guard let extensionItem = extensionContext?.inputItems.first as? NSExtensionItem,
              let attachment = extensionItem.attachments?.first,
              attachment.hasItemConformingToTypeIdentifier("public.url") else {
            extensionContext?.completeRequest(returningItems: nil)
            return
        }
        attachment.loadItem(forTypeIdentifier: "public.url") { url, _ in
            guard let url = url as? URL else { return }
            let shared = UserDefaults(suiteName: "group.com.zenith.FMHY-X-IOS")
            shared?.set(url.absoluteString, forKey: "pendingDownloadURL")
            shared?.synchronize()
            let fmhyURL = URL(string: "fmhy://download?url=\(url.absoluteString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "")")!
            DispatchQueue.main.async {
                self.extensionContext?.completeRequest(returningItems: nil)
                UIApplication.shared.open(fmhyURL)
            }
        }
    }
}
```

**App Groups entitlement** (required for both targets):
```
com.apple.security.application-groups: group.com.zenith.FMHY-X-IOS
```

---

## Step 4: URL Scheme Handling

**Modify `FMHY_X_IOSApp.swift`:**
- Register `fmhy` as a custom URL scheme in Info.plist (`CFBundleURLTypes`)
- Add `.onOpenURL { url in ... }` to handle incoming URLs from the Share Extension
- Extract the download URL from the query parameter and pass it to `FMDownloadManager`

---

## Step 5: Downloads Tab UI

**File: `Views/DownloadsView.swift`**

A new tab with:
- List of all downloads sorted by creation date (newest first)
- Each row shows: file name, progress bar, download speed, file size, status icon
- Swipe actions: Pause/Resume, Cancel, Share (when completed)
- Toolbar: "Add Download" button (paste URL manually) + filter (All / Active / Completed)
- Empty state: "No downloads yet. Share a link from Safari to start."

**File: `Views/DownloadRowView.swift`**

Reusable row view:
- File name (truncated with ellipsis)
- Progress bar (SwiftUI `ProgressView` with custom styling)
- Speed + downloaded/total size (e.g., "2.3 MB/s — 45.2 / 128.0 MB")
- Status indicator: spinner (downloading), pause icon (paused), checkmark (completed), exclamation (failed)
- Tap: if completed → open in Files/share sheet; if active → pause/resume

---

## Step 6: MainTabView Update

Add the 5th tab:
```swift
Tab {
    DownloadsView()
        .tabItem {
            Label("Downloads", systemImage: "arrow.down.circle")
        }
}
```

Inject `FMDownloadManager` as `@StateObject` + `.environmentObject()`.

---

## Step 7: User Chooses Storage Per Download

When a download starts (from Share Extension or manual paste):
1. Show a `FilePicker` / document directory selector
2. Default to app's Documents directory
3. User can navigate to any accessible directory
4. Store chosen `destinationURL` in `DownloadItem`

Implementation: Use `UIDocumentPickerViewController` presented modally when a new download is initiated.

---

## Implementation Order

1. Git backup commit
2. Create `FMDownloadManager.swift` (model + engine)
3. Create `DownloadRowView.swift` and `DownloadsView.swift`
4. Update `MainTabView.swift` (add tab, inject manager)
5. Register `fmhy` URL scheme in Info.plist
6. Add `.onOpenURL` handler in `FMHY_X_IOSApp.swift`
7. Create Share Extension target with App Groups entitlement
8. Update both entitlements files with App Groups
9. Add all new files to Xcode project (pbxproj)
10. Build and verify

## Verification

1. `xcodebuild` build succeeds with no errors
2. Test in simulator: manually paste a URL in the app → download starts with progress
3. Test segmented download: verify 16 connections open (check network activity or logs)
4. Test pause/resume: pause mid-download, resume, verify file completes correctly
5. Test Share Extension: if possible on device, share a URL from Safari → app opens → download starts
6. Test storage picker: verify user can choose download destination
7. Test download history persists across app restarts
