MovieMapper/PHASE_5_IMPLEMENTATION.md
jarianc 00d8e072c5 feat: Add Rust UI and backend implementation with project infrastructure
Adds the new Rust-based UI (iced), backend service, shared Swift models,
CI/CD workflows, build scripts, and project documentation.
2026-08-19 21:22:08 -05:00

8.0 KiB

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:

  • extraextras/
  • behindTheScenesbehind-the-scenes/
  • deletedelete/

Result Structure:

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.