# 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.