- Move phase/plan docs into docs/ - Move legacy node:test files into tests/legacy/ with README - Remove .backup file, test audit artifacts, and unused AI prompt/skill files - Remove broken iOS GitHub workflows (reference missing MovieMapper-iOS/)
536 lines
15 KiB
Markdown
536 lines
15 KiB
Markdown
# 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<PathBuf>,
|
|
navigation_stack: Vec<PathBuf>,
|
|
|
|
// File state
|
|
files: Vec<FileMetadata>,
|
|
tagged_files: HashMap<PathBuf, TagType>,
|
|
|
|
// TVDB state
|
|
search_query: String,
|
|
search_results: Vec<Show>,
|
|
selected_show: Option<Show>,
|
|
selected_season: Option<Season>,
|
|
episodes: Vec<Episode>,
|
|
|
|
// 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<FileMetadata>),
|
|
|
|
// 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<Show>),
|
|
ShowSelected(Show),
|
|
SeasonsLoaded(Vec<Season>),
|
|
SeasonSelected(Season),
|
|
EpisodesLoaded(Vec<Episode>),
|
|
|
|
// Mapping
|
|
BeginMapping,
|
|
MappingComplete(Result<MappingResult, String>),
|
|
|
|
// 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<FileMetadata>,
|
|
tagged_files: HashMap<PathBuf, TagType>,
|
|
on_file_click: Callback<PathBuf>,
|
|
on_tag: Callback<(PathBuf, TagType)>,
|
|
on_play: Callback<PathBuf>,
|
|
}
|
|
|
|
impl Component for FileList {
|
|
type Message = Message;
|
|
|
|
fn view(&self) -> Element<Message> {
|
|
// Render file list with tags, play buttons, etc.
|
|
}
|
|
}
|
|
|
|
// ui/src/components/sidebar.rs
|
|
pub struct Sidebar {
|
|
search_query: String,
|
|
search_results: Vec<Show>,
|
|
selected_show: Option<Show>,
|
|
on_search: Callback<String>,
|
|
on_show_select: Callback<Show>,
|
|
}
|
|
|
|
impl Component for Sidebar {
|
|
type Message = Message;
|
|
|
|
fn view(&self) -> Element<Message> {
|
|
// 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<Vec<FileMetadata>, 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. |