mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-01-23 03:28:11 +00:00
331 lines
8.7 KiB
Markdown
331 lines
8.7 KiB
Markdown
# Download System Refactor - Summary
|
|
|
|
## Overview
|
|
|
|
The download system has been completely refactored to use a new native iOS module for background downloads, replacing the third-party library with a custom, streamlined solution.
|
|
|
|
## What Was Done
|
|
|
|
### 1. Created New Native Module (`BackgroundDownloader`)
|
|
|
|
**Location**: `modules/background-downloader/`
|
|
|
|
A complete Expo native module for iOS background file downloads:
|
|
|
|
- **Swift Implementation**: `BackgroundDownloaderModule.swift`
|
|
- Uses `NSURLSession` with background configuration
|
|
- Implements `URLSessionDownloadDelegate` for progress tracking
|
|
- Handles iOS background session events via AppDelegate subscriber
|
|
- Session ID: `com.fredrikburmester.streamyfin.backgrounddownloader`
|
|
|
|
- **TypeScript Interface**: Full type-safe API with events
|
|
- `startDownload(url, destinationPath?)` - Start a download
|
|
- `cancelDownload(taskId)` - Cancel a specific download
|
|
- `cancelAllDownloads()` - Cancel all downloads
|
|
- `getActiveDownloads()` - List active downloads
|
|
|
|
- **Events**:
|
|
- `onDownloadProgress` - Progress updates with bytes/percentage
|
|
- `onDownloadComplete` - Completion with file path
|
|
- `onDownloadError` - Error handling
|
|
- `onDownloadStarted` - Download initiation confirmation
|
|
|
|
- **Documentation**: Complete README with usage examples
|
|
|
|
### 2. Rewrote DownloadProvider
|
|
|
|
**Location**: `providers/DownloadProvider.tsx`
|
|
|
|
A simplified, focused implementation:
|
|
|
|
**Features Included**:
|
|
- ✅ Video file downloads with progress tracking
|
|
- ✅ Background download support
|
|
- ✅ Database persistence (same format as before)
|
|
- ✅ Movies and TV episodes support
|
|
- ✅ Download notifications (success/error)
|
|
- ✅ File deletion and management
|
|
- ✅ Size calculation
|
|
- ✅ Same context API for backward compatibility
|
|
|
|
**Features Removed (for simplicity)**:
|
|
- ❌ Trickplay image downloads
|
|
- ❌ Subtitle downloads
|
|
- ❌ Queue management with concurrent limits
|
|
- ❌ Pause/Resume (can be added back easily)
|
|
- ❌ Download speed/ETA calculations
|
|
- ❌ Cache directory management
|
|
|
|
**Key Improvements**:
|
|
- Event-driven architecture (no polling)
|
|
- Better background handling via native module
|
|
- Cleaner, more maintainable code
|
|
- Proper TypeScript typing throughout
|
|
- Simplified state management
|
|
|
|
### 3. Preserved Old Implementation
|
|
|
|
**Location**: `providers/DownloadProvider.deprecated.tsx`
|
|
|
|
The old implementation has been preserved for reference but should not be used.
|
|
|
|
### 4. Documentation
|
|
|
|
Created comprehensive documentation:
|
|
|
|
- **Module README**: `modules/background-downloader/README.md`
|
|
- API reference
|
|
- Usage examples
|
|
- Implementation details
|
|
|
|
- **Migration Guide**: `providers/Downloads/MIGRATION.md`
|
|
- What changed
|
|
- API compatibility matrix
|
|
- Migration steps
|
|
- Troubleshooting guide
|
|
|
|
- **System README**: `providers/Downloads/README.md`
|
|
- Architecture overview
|
|
- Type definitions
|
|
- Usage examples
|
|
- File storage details
|
|
|
|
## Technical Details
|
|
|
|
### Background Download Implementation
|
|
|
|
The native module uses iOS's recommended approach:
|
|
|
|
1. **Background URLSession**: Persistent identifier ensures downloads continue
|
|
2. **Delegate Pattern**: Progress and completion via delegate callbacks
|
|
3. **AppDelegate Integration**: Handles system wake-ups for download events
|
|
4. **Completion Handler**: Properly signals iOS when background work is done
|
|
|
|
### State Management
|
|
|
|
```typescript
|
|
// Active downloads tracked in Jotai atom
|
|
const processesAtom = atom<JobStatus[]>([]);
|
|
|
|
// Task ID to Process ID mapping for event correlation
|
|
const taskMap = Map<number, string>();
|
|
|
|
// Persistent database in MMKV
|
|
storage.set('downloads.v2.json', JSON.stringify(database));
|
|
```
|
|
|
|
### Download Flow
|
|
|
|
```
|
|
User initiates download
|
|
↓
|
|
Create JobStatus & add to processes
|
|
↓
|
|
Generate destination path
|
|
↓
|
|
Start native BackgroundDownloader
|
|
↓
|
|
Map taskId ↔ processId
|
|
↓
|
|
Receive progress events → Update UI
|
|
↓
|
|
Receive completion event
|
|
↓
|
|
Move file to permanent location
|
|
↓
|
|
Save to database
|
|
↓
|
|
Send notification
|
|
↓
|
|
Clean up process
|
|
```
|
|
|
|
## Configuration
|
|
|
|
### iOS Background Modes
|
|
|
|
Already configured in `app.json`:
|
|
|
|
```json
|
|
{
|
|
"ios": {
|
|
"infoPlist": {
|
|
"UIBackgroundModes": ["audio", "fetch"]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
The "fetch" mode enables background URLSession downloads.
|
|
|
|
### Module Integration
|
|
|
|
The module is:
|
|
- ✅ Auto-linked via Expo
|
|
- ✅ Exported from `modules/index.ts`
|
|
- ✅ Type-safe with full TypeScript support
|
|
- ✅ Registered as AppDelegate subscriber
|
|
|
|
## Breaking Changes
|
|
|
|
### None for Normal Usage
|
|
|
|
The public API remains the same for the most common operations:
|
|
|
|
```typescript
|
|
const {
|
|
startBackgroundDownload,
|
|
cancelDownload,
|
|
getDownloadedItems,
|
|
deleteFile,
|
|
processes
|
|
} = useDownload();
|
|
```
|
|
|
|
### No-op Methods
|
|
|
|
These methods exist but do nothing (for compatibility):
|
|
- `pauseDownload()`
|
|
- `resumeDownload()`
|
|
- `startDownload()` (use `startBackgroundDownload` instead)
|
|
- `deleteFileByType()`
|
|
- `cleanCacheDirectory()`
|
|
- `updateDownloadedItem()`
|
|
- `dumpDownloadDiagnostics()`
|
|
|
|
## Testing Checklist
|
|
|
|
Before deployment, test:
|
|
|
|
- [ ] Download a movie
|
|
- [ ] Download a TV episode
|
|
- [ ] Download multiple items simultaneously
|
|
- [ ] Cancel an active download
|
|
- [ ] Delete a downloaded item
|
|
- [ ] View list of downloads
|
|
- [ ] Background the app during download
|
|
- [ ] Force quit and restart (download should be cancelled)
|
|
- [ ] Verify notifications appear
|
|
- [ ] Check file integrity and playback
|
|
- [ ] Verify database persistence
|
|
- [ ] Check storage calculations
|
|
|
|
## Next Steps
|
|
|
|
### Immediate
|
|
|
|
1. **Rebuild iOS app**:
|
|
```bash
|
|
npx expo prebuild -p ios
|
|
cd ios && pod install && cd ..
|
|
npx expo run:ios
|
|
```
|
|
|
|
2. **Test thoroughly**: Use the testing checklist above
|
|
|
|
3. **Monitor for issues**: Check console logs and user reports
|
|
|
|
### Future Enhancements
|
|
|
|
Priority features to add back:
|
|
|
|
1. **Pause/Resume** (High Priority)
|
|
- Easy to implement with NSURLSession
|
|
- User-requested feature
|
|
|
|
2. **Queue Management** (Medium Priority)
|
|
- Concurrent download limits
|
|
- Automatic queue processing
|
|
|
|
3. **Progress Persistence** (Medium Priority)
|
|
- Resume interrupted downloads after app restart
|
|
- Save download state to database
|
|
|
|
4. **Trickplay & Subtitles** (Low Priority)
|
|
- Re-add auxiliary file downloads
|
|
- Integrate with video playback
|
|
|
|
5. **Download Analytics** (Low Priority)
|
|
- Speed calculation
|
|
- ETA estimation
|
|
- Failure rate tracking
|
|
|
|
## Known Limitations
|
|
|
|
1. **iOS Only**: Android support not yet implemented
|
|
2. **No Pause**: Cannot pause/resume downloads yet
|
|
3. **No Queue**: All downloads start immediately
|
|
4. **Force Quit**: Downloads cancelled if app is force-quit (iOS limitation)
|
|
5. **No Persistence**: Downloads lost if app crashes or is terminated
|
|
|
|
## Performance Improvements
|
|
|
|
Over the old system:
|
|
|
|
- **Better Background Support**: True iOS background sessions
|
|
- **Event-Driven**: No polling, immediate updates
|
|
- **Lower Overhead**: Removed unused features
|
|
- **Native Integration**: Tighter iOS system integration
|
|
- **Cleaner Code**: Easier to maintain and extend
|
|
|
|
## Dependencies Changed
|
|
|
|
### Removed
|
|
- `@kesha-antonov/react-native-background-downloader`
|
|
|
|
### Added
|
|
- Custom `BackgroundDownloader` native module (local)
|
|
|
|
No external dependencies added, reducing maintenance burden.
|
|
|
|
## File Changes Summary
|
|
|
|
### New Files
|
|
- `modules/background-downloader/` (entire module)
|
|
- `providers/Downloads/MIGRATION.md`
|
|
- `providers/Downloads/README.md`
|
|
- `DOWNLOAD_SYSTEM_REFACTOR.md` (this file)
|
|
|
|
### Modified Files
|
|
- `modules/index.ts` (exported new module)
|
|
- `providers/DownloadProvider.tsx` (complete rewrite)
|
|
|
|
### Renamed Files
|
|
- `providers/DownloadProvider.tsx` → `providers/DownloadProvider.deprecated.tsx`
|
|
|
|
### Unchanged
|
|
- `providers/Downloads/types.ts` (types remain the same)
|
|
- Database format and storage location
|
|
- Public API for most common operations
|
|
|
|
## Rollback Plan
|
|
|
|
If issues arise:
|
|
|
|
1. Rename `DownloadProvider.deprecated.tsx` back to `DownloadProvider.tsx`
|
|
2. Remove the `background-downloader` module export from `modules/index.ts`
|
|
3. Re-install `@kesha-antonov/react-native-background-downloader`
|
|
4. Rebuild the app
|
|
|
|
Note: The database format is unchanged, so existing downloads will work with either version.
|
|
|
|
## Success Metrics
|
|
|
|
The refactor is successful if:
|
|
|
|
- ✅ Downloads work in foreground
|
|
- ✅ Downloads continue in background
|
|
- ✅ Progress updates are accurate
|
|
- ✅ Notifications work correctly
|
|
- ✅ Files are saved and playable
|
|
- ✅ No crashes or memory leaks
|
|
- ✅ Performance is equal or better
|
|
- ✅ Code is cleaner and more maintainable
|
|
|
|
## Conclusion
|
|
|
|
This refactor provides a solid foundation for the download system moving forward. The native module approach gives us full control over the download experience and makes it easier to add features in the future.
|
|
|
|
The simplified DownloadProvider focuses on core functionality while maintaining API compatibility, making this a low-risk, high-reward change.
|
|
|