# Rust UI Implementation Plan for MovieMapper ## Executive Summary This plan outlines the architecture and implementation strategy for replacing the current Electron-based UI with a native Rust UI using a performant GUI framework. The plan maintains full compatibility with the existing Rust backend while providing a modern, responsive desktop application. ## Architecture Overview ### Current Architecture ``` Electron App (Renderer + Main) ├── index.html (UI) ├── renderer.js (UI logic) └── main.js (IPC handlers → Rust backend) ``` ### New Architecture ``` Native Desktop App ├── Rust UI Layer (iced/winit) ├── Rust Backend (existing) └── IPC Bridge (optional: direct function calls) ``` ## GUI Framework Selection ### Options Considered #### 1. **Iced** (RECOMMENDED) ⭐ **Pros:** - Modern, React-inspired API with Elm architecture - Excellent performance (native rendering) - Cross-platform (Windows, macOS, Linux) - Active community and good documentation - Async/await support built-in - Small binary size (~5MB runtime) - No WebKit dependencies **Cons:** - Less mature than some alternatives - Smaller ecosystem **Why Chosen:** - Perfect for data-heavy applications like MovieMapper - Similar state management to Electron/React - Excellent performance characteristics - Modern Rust ecosystem alignment #### 2. **Dioxus** **Pros:** - React-inspired syntax (RSX) - Web, desktop, and mobile support - Strong community **Cons:** - Heavier runtime (~50MB+) - Less mature for desktop apps - More complex build process #### 3. **Tauri** (Alternative) **Pros:** - Use existing HTML/CSS/JS - Small binary size - Native performance **Cons:** - Would keep web stack (defeats purpose) - Additional WebView overhead - Less "pure Rust" approach #### 4. **Slint** **Pros:** - Declarative UI design - Good performance **Cons:** - Learning curve for DSL - Smaller community - Less Rust-idiomatic ### Final Choice: **Iced** ## Project Structure ``` MovieMapper/ ├── Cargo.toml # Workspace configuration ├── Cargo.lock ├── rust/ │ ├── Cargo.toml # Backend crate │ ├── src/ │ │ ├── lib.rs │ │ ├── main.rs │ │ ├── error.rs │ │ ├── types.rs │ │ ├── scanner.rs │ │ ├── ffmpeg.rs │ │ ├── tvdb.rs │ │ ├── file_manager.rs │ │ └── mapper.rs │ └── tests/ │ ├── ui/ # NEW: Rust UI implementation │ ├── Cargo.toml # UI crate configuration │ ├── src/ │ │ ├── main.rs # Application entry point │ │ ├── app.rs # Main app structure │ │ ├── theme.rs # Styling and theming │ │ ├── components/ # Reusable UI components │ │ │ ├── mod.rs │ │ │ ├── breadcrumb.rs # Navigation breadcrumbs │ │ │ ├── file_list.rs # File listing component │ │ │ ├── sidebar.rs # Search and show details │ │ │ ├── progress.rs # Progress indicator │ │ │ ├── tag_manager.rs # Tagging UI │ │ │ ├── episode_editor.rs # Episode range editing │ │ │ └── floating_action.rs # FAB component │ │ ├── state.rs # Application state management │ │ ├── messages.rs # UI messages/events │ │ ├── backend.rs # Backend integration │ │ ├── windows/ │ │ │ ├── mod.rs │ │ │ ├── main.rs # Main window │ │ │ └── video_preview.rs # Video preview modal │ │ └── utils/ │ │ ├── mod.rs │ │ ├── path.rs # Path utilities │ │ ├── format.rs # Formatting helpers │ │ └── ffmpeg.rs # FFmpeg helpers │ └── assets/ │ ├── icons/ │ └── styles/ │ ├── backend/ # Backend integration layer │ ├── Cargo.toml │ └── src/ │ ├── lib.rs # Re-exports from rust/ │ └── bridge.rs # IPC/FFI bridge if needed │ ├── main.rs # Workspace entry point ├── index.html # Keep for reference/compatibility ├── renderer.js # Keep for reference ├── main.js # Keep for reference └── package.json # Updated workspace config ``` ## Implementation Phases ### Phase 1: Foundation (Week 1) #### 1.1 Setup Rust UI Project - [ ] Create `ui/` directory with `Cargo.toml` - [ ] Configure workspace in root `Cargo.toml` - [ ] Add `iced = "0.12"` dependency to `ui/Cargo.toml` - [ ] Set up basic project structure - [ ] Configure build for cross-platform - [ ] Set up asset management (icons, styles) #### 1.2 Backend Integration - [ ] Create `backend/` crate for Rust backend access - [ ] Implement direct function calls (no IPC overhead) - [ ] Handle async operations with `tokio` - [ ] Implement error propagation - [ ] Create backend state management #### 1.3 Core Application Structure - [ ] Implement `iced::Application` trait - [ ] Set up main window with `Settings` - [ ] Implement state management with `Clone` + `Default` - [ ] Create message enum for all UI events - [ ] Set up logging with `tracing` ### Phase 2: UI Components (Week 2) #### 2.1 Basic Layout - [ ] Implement main layout (sidebar + content) - [ ] Create breadcrumb navigation component - [ ] Implement directory selector button - [ ] Add progress indicator component - [ ] Create file list container #### 2.2 File List Component - [ ] Implement file item rendering - [ ] Add drag-and-drop support (using `iced_native::event::drag`) - [ ] Create folder vs file visual distinction - [ ] Implement file metadata display (duration, quality, FPS) - [ ] Add episode number display with arrows #### 2.3 Sidebar Components - [ ] Search input with debouncing - [ ] Search results dropdown - [ ] Show details panel - [ ] Season selector with episode list - [ ] Episode hover highlighting ### Phase 3: Feature Implementation (Week 3) #### 3.1 File Operations - [ ] Implement directory scanning UI - [ ] Add progress updates during scan - [ ] Create file rename functionality - [ ] Implement file tagging system - [ ] Add play button for individual files - [ ] Implement FAB for moving all tagged files #### 3.2 Episode Mapping - [ ] Create episode range editor component - [ ] Implement arrow buttons for range adjustment - [ ] Add visual feedback for episode matching - [ ] Create "Begin Mapping" button and flow - [ ] Implement mapping progress display #### 3.3 Show/Season/Episode Selection - [ ] Implement TVDB search - [ ] Display search results - [ ] Show details panel - [ ] Season selector with episode counts - [ ] Episode list with episode number matching ### Phase 4: Advanced Features (Week 4) #### 4.1 Video Preview Modal - [ ] Create modal window component - [ ] Integrate with system video player - [ ] Display file metadata - [ ] Add close button and styling #### 4.2 Breadcrumb Navigation - [ ] Implement navigation stack - [ ] Add back button functionality - [ ] Display directory path history - [ ] Handle folder navigation #### 4.3 Audit Logging - [ ] Implement audit event logging - [ ] Display audit log in UI (optional) - [ ] Export audit logs (optional) #### 4.4 Performance Optimizations - [ ] Virtual scrolling for large file lists - [ ] Lazy loading for episode data - [ ] Caching for TVDB results - [ ] Background processing for large operations - [ ] Memory usage monitoring ### Phase 5: Polish & Testing (Week 5) #### 5.1 Theming - [ ] Implement dark theme (match current design) - [ ] Create reusable component styles - [ ] Add hover states - [ ] Implement focus states - [ ] Support system theme detection (optional) #### 5.2 Testing - [ ] Unit tests for UI components - [ ] Integration tests for workflows - [ ] E2E tests with `iced_test` or similar - [ ] Manual testing on all platforms - [ ] Performance testing #### 5.3 Documentation - [ ] User documentation - [ ] API documentation - [ ] Architecture documentation - [ ] Contribution guidelines ## Component Architecture ### State Management ```rust #[derive(Debug, Clone, Default)] pub struct AppState { // Directory state current_directory: Option, navigation_stack: Vec, // File state files: Vec, tagged_files: HashMap, // TVDB state search_query: String, search_results: Vec, selected_show: Option, selected_season: Option, episodes: Vec, // Mapping state is_mapping: bool, mapping_progress: u32, // UI state progress_visible: bool, progress_message: String, } ``` ### Messages (Events) ```rust #[derive(Debug, Clone)] pub enum Message { // Navigation SelectDirectory, OpenDirectory(PathBuf), NavigateBack, // File operations ScanDirectory(PathBuf), FileScanned(FileMetadata), ScanComplete(Vec), // Tagging TagFile(PathBuf, TagType), UntagFile(PathBuf, TagType), MoveTaggedFile(PathBuf, TagType), MoveAllTaggedFiles, // Episode editing UpdateEpisodeRange(usize, u32, u32), ShiftEpisodes(usize, i32), // TVDB SearchShows(String), ShowsLoaded(Vec), ShowSelected(Show), SeasonsLoaded(Vec), SeasonSelected(Season), EpisodesLoaded(Vec), // Mapping BeginMapping, MappingComplete(Result), // UI updates ProgressUpdate(u32, u32, String), ShowProgress, HideProgress, // System OpenVideoPreview(PathBuf), OpenFileInPlayer(PathBuf), LogAuditEvent(AuditEvent), } ``` ### Component Structure ```rust // ui/src/components/file_list.rs pub struct FileList { files: Vec, tagged_files: HashMap, on_file_click: Callback, on_tag: Callback<(PathBuf, TagType)>, on_play: Callback, } impl Component for FileList { type Message = Message; fn view(&self) -> Element { // Render file list with tags, play buttons, etc. } } // ui/src/components/sidebar.rs pub struct Sidebar { search_query: String, search_results: Vec, selected_show: Option, on_search: Callback, on_show_select: Callback, } impl Component for Sidebar { type Message = Message; fn view(&self) -> Element { // Render search and show details } } ``` ## Backend Integration Strategy ### Direct Function Calls (Preferred) Instead of IPC, use direct Rust function calls: ```rust // ui/src/backend.rs use movie_mapper_rust::{scan_directory, rename_file, move_to_folder}; pub async fn scan_directory_ui(path: &str) -> Result, String> { scan_directory(path, Some(|current, total, filename| { // Send progress updates to UI Message::ProgressUpdate(current, total, filename.to_string()) })).await.map_err(|e| e.to_string()) } ``` ### Benefits: - Zero IPC overhead - Type safety - Better error handling - Simpler code - Easier debugging ### When IPC Might Be Needed: - Long-running operations that could block UI - When backend is in separate process for isolation - For plugin architecture ## Performance Targets - **Startup time**: < 1 second - **Directory scan (100 files)**: < 500ms - **File rendering**: Smooth 60fps - **Memory usage**: < 100MB for typical workflow - **Binary size**: < 15MB (with all dependencies) ## Cross-Platform Considerations ### macOS - Native look and feel - Touch Bar support (optional) - Spotlight integration (optional) ### Windows - Taskbar integration - File association (optional) - Aero effects ### Linux - AppImage support - Desktop file integration - Theme compatibility ## Deployment ### Build Commands ```bash # Development cargo build --package ui --features debug # Release cargo build --package ui --release # Cross-platform cargo build --package ui --release --target x86_64-apple-darwin cargo build --package ui --release --target x86_64-pc-windows-msvc cargo build --package ui --release --target x86_64-unknown-linux-gnu ``` ### Distribution **Option 1: Standalone Binary** - Single executable for each platform - No runtime installation required - Include FFmpeg binaries if needed **Option 2: Installer** - Platform-specific installers - Automatic updates (using `taffy` or similar) - Clean uninstall **Option 3: Package Managers** - macOS: Homebrew - Windows: Scoop, MSI - Linux: AppImage, Flatpak, Snap ## Risk Assessment ### Technical Risks | Risk | Impact | Mitigation | |------|--------|------------| | Iced ecosystem maturity | Medium | Contribute back, use well-established features | | Learning curve | Low | Team Rust expertise, documentation | | Feature parity | Low | Phased implementation, testing | ### Schedule Risks | Risk | Impact | Mitigation | |------|--------|------------| | Feature complexity | Medium | Break into small PRs, daily demos | | Platform differences | Low | Test early on all platforms | | Backend integration | Low | Direct calls, type safety | ## Success Criteria - [ ] All existing features implemented - [ ] Performance matches or exceeds Electron version - [ ] UI looks native on all platforms - [ ] No memory leaks (verified with `valgrind`/`ASAN`) - [ ] All tests passing - [ ] Documentation complete - [ ] User testing successful ## Next Steps 1. **Approve plan** - Get stakeholder approval 2. **Setup repository** - Create `ui/` directory structure 3. **Build MVP** - Implement basic window with file list 4. **Weekly reviews** - Demo progress each week 5. **Iterate** - Add features incrementally 6. **Test** - Comprehensive testing on all platforms 7. **Release** - Beta release with user feedback ## Appendix: Alternative Approaches ### Hybrid Approach (Tauri + Rust UI) If Tauri is preferred: - Keep Tauri for window management - Use Rust UI components (Dioxus or Slint) - Keep some Electron features for compatibility ### Web UI with Rust Backend If web stack is preferred: - Keep HTML/CSS/JS for UI - Use Rust backend via WASM - Electron replaced with `tao`/`wry` ### Native Desktop with Different Framework Other options: - **egui**: Immediate mode GUI, very performant - **slint**: Declarative, good for form-like apps - **gtk-rs**: Mature, but heavier dependencies ## Conclusion The recommended approach using **Iced** provides the best balance of performance, maintainability, and developer experience for a Rust-based MovieMapper UI. It maintains the performance benefits of the Rust backend while providing a modern, responsive user interface that feels native on all platforms. This plan provides a clear roadmap for implementation while allowing flexibility for adjustments based on team feedback and technical discoveries during development.