Adds the new Rust-based UI (iced), backend service, shared Swift models, CI/CD workflows, build scripts, and project documentation.
287 lines
8.0 KiB
Markdown
287 lines
8.0 KiB
Markdown
# Phase 5: Advanced Features Implementation Summary
|
|
|
|
## Overview
|
|
Phase 5 implements advanced features for the MovieMapper iOS app, focusing on offline-first architecture and enhanced tagging capabilities.
|
|
|
|
---
|
|
|
|
## 1. Offline-First Architecture
|
|
|
|
### LocalCache.swift
|
|
**Location**: `Sources/Services/LocalCache.swift`
|
|
|
|
**Features**:
|
|
- Caches show search results in UserDefaults with 7-day expiration
|
|
- Supports caching of individual shows and arrays of shows
|
|
- Automatic cache expiration handling
|
|
- Methods:
|
|
- `cacheShows(key:shows:)` - Cache an array of shows
|
|
- `getCachedShows(key:)` - Retrieve cached shows
|
|
- `cacheSearchResults(key:shows:)` - Cache search results
|
|
- `getCachedSearchResults(key:)` - Get cached search results
|
|
- `cacheShowDetails(key:show:)` - Cache individual show details
|
|
- `getCachedShowDetails(key:)` - Get cached show details
|
|
- `clearCache()` - Clear all cached data
|
|
- `clearCacheEntry(key:)` - Clear specific cache entry
|
|
|
|
**Integration**:
|
|
- Used by `TVDBClient` to cache search results and show details
|
|
- Provides offline access to recently searched shows and show details
|
|
- Automatically expires old cache entries
|
|
|
|
### OfflineManager.swift
|
|
**Location**: `Sources/Services/OfflineManager.swift`
|
|
|
|
**Features**:
|
|
- Monitors network connectivity using Combine
|
|
- Queues operations when offline for later execution
|
|
- Automatic retry mechanism (up to 3 attempts)
|
|
- Persistent operation queue using UserDefaults
|
|
- Methods:
|
|
- `queueOperation(description:operation:)` - Add operation to queue
|
|
- `processQueue()` - Process queued operations
|
|
- `loadQueue()` - Load queue from UserDefaults on app launch
|
|
- `clearQueue()` - Clear all queued operations
|
|
- `getQueuedOperations()` - Get current queue
|
|
|
|
**Network Status**:
|
|
- `isOnline: Bool` - Current connectivity status
|
|
- `status: NetworkStatus` - `.online` or `.offline`
|
|
|
|
**Operation Structure**:
|
|
- UUID-based operation tracking
|
|
- Retry count tracking
|
|
- Error logging for failed operations
|
|
|
|
---
|
|
|
|
## 2. Tagging System
|
|
|
|
### TagManager.swift
|
|
**Location**: `Sources/Services/TagManager.swift`
|
|
|
|
**Features**:
|
|
- Add/remove tags on files
|
|
- Move tagged files to Jellyfin-compatible folders
|
|
- Automatic folder creation for target folders
|
|
- Audit logging for all tagging operations
|
|
|
|
**Methods**:
|
|
- `addTag(_tag:to:in:)` - Add a tag to a file
|
|
- `removeTag(_tag:from:in:)` - Remove a tag from a file
|
|
- `hasTag(_tag:in:)` - Check if file has a tag
|
|
- `getAllTags(for:)` - Get all tags for a file
|
|
- `moveTaggedFiles(_files:to:in:)` - Move tagged files to a folder
|
|
- `moveFilesWithTags(_files:in:)` - Move files to appropriate folders based on their tags
|
|
- `getTaggedFiles(in:)` - Get all tagged files in a directory
|
|
|
|
**Jellyfin Compatible Folders**:
|
|
- `extra` → `extras/`
|
|
- `behindTheScenes` → `behind-the-scenes/`
|
|
- `delete` → `delete/`
|
|
|
|
**Result Structure**:
|
|
```swift
|
|
public struct MoveTaggedFilesResult {
|
|
let success: Bool
|
|
let movedCount: Int
|
|
let failedCount: Int
|
|
let movedFiles: [MediaFile]
|
|
let failedFiles: [MoveFailure]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 3. UI Integration
|
|
|
|
### FileListView.swift Updates
|
|
|
|
**New Features**:
|
|
- Toggle tagging mode with floating action button
|
|
- Visual tag badges on files showing tag state
|
|
- Floating action button for moving all tagged files
|
|
- Individual file tag toggling when in tagging mode
|
|
|
|
**Floating Action Button**:
|
|
- Two buttons stacked vertically:
|
|
1. "Tag Files" - Toggle tagging mode on/off
|
|
2. "Move All Tagged" - Move all tagged files to appropriate folders
|
|
- Auto-hides when not needed
|
|
- Smooth animation for appearance/disappearance
|
|
|
|
**Tag Badges**:
|
|
- Shows tag name with first letter capitalized
|
|
- Color-coded based on tag type (purple for extra, orange for behind-the-scenes, red for delete)
|
|
- Tap to toggle tag when in tagging mode
|
|
- Visual feedback with border and shadow
|
|
|
|
---
|
|
|
|
## 4. TVDB Client Updates
|
|
|
|
### TVDBClient.swift
|
|
|
|
**Updates**:
|
|
- Uses `LocalCache` for caching search results and show details
|
|
- Removed manual UserDefaults caching
|
|
- Cleaner separation of concerns
|
|
- Offline-capable search and show details
|
|
|
|
**Caching Behavior**:
|
|
- Search results cached with key `search_{query}`
|
|
- Show details cached with key `show_{id}`
|
|
- Episodes cached with key `episodes_{showId}_{seasonNumber}`
|
|
- Cache expires after 7 days
|
|
|
|
---
|
|
|
|
## 5. Data Model Updates
|
|
|
|
### SharedModels Files (all made public)
|
|
|
|
Updated to use `public` access control:
|
|
- `MediaFile.swift` - File structure with tags
|
|
- `Show.swift` - Show structure with caching support
|
|
- `Season.swift` - Season structure
|
|
- `Episode.swift` - Episode structure
|
|
- `TagType.swift` - Tag type enum (extra, behindTheScenes, delete)
|
|
- `TaggedFile.swift` - Tagged file structure
|
|
|
|
---
|
|
|
|
## 6. Package Structure
|
|
|
|
### Package.swift Updates
|
|
|
|
**Structure**:
|
|
- All source files in `Sources/` directory
|
|
- SharedModels included in Sources directory
|
|
- Proper module structure for Swift Package Manager
|
|
- Dependencies: FFmpegKitSwift, Alamofire, ReactiveSwift
|
|
|
|
---
|
|
|
|
## Integration Summary
|
|
|
|
### File Flow
|
|
|
|
1. **Search**:
|
|
- User searches for show → TVDBClient checks cache first
|
|
- If not in cache, fetch from network and cache result
|
|
- Offline: shows cached results
|
|
|
|
2. **File Scanning**:
|
|
- FileScanner scans directory (completely offline)
|
|
- Files loaded with metadata (duration, quality, FPS)
|
|
- Files can be tagged locally
|
|
|
|
3. **Tagging**:
|
|
- User toggles tagging mode
|
|
- Tags added/removed via TagManager
|
|
- Tags persisted to `.metadata` file
|
|
- Audit log updated for each action
|
|
|
|
4. **File Movement**:
|
|
- User selects "Move All Tagged"
|
|
- TagManager moves files to appropriate folders
|
|
- Audit log entry created
|
|
- Files removed from UI
|
|
|
|
### Offline Capabilities
|
|
|
|
- **File scanning**: 100% offline
|
|
- **Tagging**: 100% offline
|
|
- **File movement**: 100% offline
|
|
- **TVDB search**: Cached results available offline
|
|
- **TVDB show details**: Cached results available offline
|
|
- **Episode data**: Cached results available offline
|
|
|
|
---
|
|
|
|
## Testing Recommendations
|
|
|
|
1. **LocalCache**:
|
|
- Cache write/read operations
|
|
- Cache expiration (7-day test)
|
|
- Clear cache functionality
|
|
|
|
2. **OfflineManager**:
|
|
- Queue operations while offline
|
|
- Automatic processing when online
|
|
- Retry mechanism (3 attempts)
|
|
- Persistence across app launches
|
|
|
|
3. **TagManager**:
|
|
- Add/remove tags
|
|
- Move files to correct folders
|
|
- Folder creation (extras, behind-the-scenes, delete)
|
|
- Audit logging
|
|
|
|
4. **FileListView**:
|
|
- Tagging mode toggle
|
|
- Tag badge display
|
|
- Floating action button visibility
|
|
- Move all tagged files
|
|
|
|
---
|
|
|
|
## Known Limitations
|
|
|
|
1. **FileScanner**:
|
|
- Non-recursive scanning (current directory only)
|
|
- No parent directory navigation yet
|
|
- Tag state lost on directory change
|
|
|
|
2. **LocalCache**:
|
|
- UserDefaults based (not suitable for large datasets)
|
|
- 7-day expiration
|
|
- No manual cache management UI
|
|
|
|
3. **OfflineManager**:
|
|
- No UI feedback for queued operations
|
|
- No priority system for operations
|
|
- Limited retry options
|
|
|
|
---
|
|
|
|
## Next Steps (Future Phases)
|
|
|
|
1. **Phase 6**: Build & Distribution
|
|
2. **Phase 7**: Advanced Features
|
|
- iCloud sync
|
|
- File preview
|
|
- Bulk operations
|
|
- Advanced filtering
|
|
|
|
---
|
|
|
|
## Files Created/Modified
|
|
|
|
### Created:
|
|
- `Sources/Services/LocalCache.swift`
|
|
- `Sources/Services/OfflineManager.swift`
|
|
- `Sources/Services/TagManager.swift`
|
|
- `Sources/SharedModels/` (copied from parent directory)
|
|
|
|
### Modified:
|
|
- `Sources/Services/TVDBClient.swift` - Uses LocalCache
|
|
- `Sources/UI/FileListView.swift` - Enhanced tagging UI
|
|
- `Sources/SharedModels/*.swift` - Made public
|
|
- `Package.swift` - Updated targets
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
Phase 5 successfully implements:
|
|
- ✅ Local caching of show search results (7-day expiration)
|
|
- ✅ File scanning works completely offline
|
|
- ✅ TVDB features optional (internet required for fresh data)
|
|
- ✅ TagManager with addTag, removeTag, moveTaggedFiles methods
|
|
- ✅ Jellyfin compatible folders (extras/, behind-the-scenes/, delete/)
|
|
- ✅ Floating action button for moving all tagged files
|
|
- ✅ Tag state persistence
|
|
- ✅ Audit logging for tagging operations
|
|
|
|
The implementation follows the iOS app architecture and integrates seamlessly with existing services. |