# Project Plan: Anime (Rust GUI) A cross-platform (Arch Linux + Windows) GUI application for searching, browsing, and watching anime. Inspired by [ani-cli](https://github.com/pystardust/ani-cli). ## Features ### Core (MVP) - Search anime by name via the AllAnime GraphQL API - Display search results in a list - Select an anime and view its available episodes - Select an episode to play in the OS default media player - Watch history -- track what you've watched, resume from where you left off ### Extended - Download episodes (mp4 direct download via reqwest, m3u8 via yt-dlp/ffmpeg subprocess) - Download progress bar - Sub/Dub toggle - Quality selection - Episode range selection for batch downloads --- ## Tech Stack ### GUI Framework **egui / eframe** - Immediate-mode GPU-rendered GUI - Single binary, no runtime dependencies - Native look on both Linux and Windows - Easy to iterate on, good for list-based UIs ### Crates | Crate | Version | Purpose | |---|---|---| | `eframe` | latest | Window management, OpenGL/wgpu backend for egui | | `egui` | latest | Immediate-mode UI widgets (comes with eframe) | | `reqwest` | latest | HTTP client for GraphQL API calls and mp4 downloads | | `tokio` | latest | Async runtime (required by reqwest, keeps GUI responsive) | | `serde` | latest | Serialization framework | | `serde_json` | latest | JSON parsing for GraphQL responses | | `open` | latest | Open video URL in OS default player (`xdg-open` on Linux, `start` on Windows) | | `directories` | latest | Cross-platform paths for config/state (history file) | | `anyhow` | latest | Ergonomic error handling with context | | `indicatif` | latest | Progress bars for downloads (can integrate into egui) | ### Standard Library (no extra crate needed) | Module | Purpose | |---|---| | `std::process::Command` | Shell out to `yt-dlp` / `ffmpeg` for m3u8 downloads | | `std::fs` | Read/write history file | ### External Tools (runtime, not compile-time) | Tool | Required? | Purpose | |---|---|---| | `mpv` / `vlc` / system default | Yes (any player) | Video playback | | `yt-dlp` | For m3u8 downloads | HLS stream downloading | | `ffmpeg` | Fallback for m3u8 | HLS stream downloading (if yt-dlp unavailable) | --- ## Architecture ``` src/ ├── main.rs -- App entry, eframe::run_native() setup ├── app.rs -- Main App struct implementing eframe::App │ Holds app state, routes between views ├── views/ │ ├── mod.rs │ ├── search.rs -- Search input + results list view │ ├── episodes.rs -- Episode list view for a selected anime │ └── player.rs -- "Now playing" view (current episode, next/prev controls) ├── api/ │ ├── mod.rs │ ├── client.rs -- Shared reqwest::Client setup (user-agent, referer) │ ├── search.rs -- search_anime() -- GraphQL search query │ ├── episodes.rs -- episodes_list() -- GraphQL episodes query │ ├── sources.rs -- get_episode_url() -- GraphQL embed query + provider decoding │ ├── providers.rs -- Provider-specific link extraction (wixmp, hianime, etc.) │ └── cipher.rs -- Hex substitution cipher for decoding provider URLs ├── download.rs -- Download logic: direct mp4 via reqwest, m3u8 via subprocess ├── history.rs -- Read/write watch history to local state file └── player.rs -- Launch video in OS default player via `open` crate ``` --- ## Data Flow ``` ┌──────────────────────────────────────────────────────────────┐ │ GUI (egui) │ │ │ │ ┌─────────┐ ┌────────────┐ ┌────────────────────┐ │ │ │ Search │───>│ Episodes │───>│ Play / Download │ │ │ │ View │ │ View │ │ View │ │ │ └─────────┘ └────────────┘ └────────────────────┘ │ │ │ │ │ │ │ └───────┼───────────────┼──────────────────┼─────────┼────────┘ │ │ │ │ v v v v search_anime() episodes_list() get_episode_url()│ │ │ │ │ └───────┬───────┘ │ ┌────┘ v v v AllAnime GraphQL API ┌──────────────┐ (api.allanime.day) │ Playback │ ├──────────────┤ │ open crate │ -> OS default player │ reqwest │ -> direct mp4 download │ yt-dlp/ffmpeg│ -> m3u8 download └──────────────┘ ``` --- ## API Details See [ani-cli.md](./ani-cli.md) for full documentation of: - GraphQL queries and variables - Hex substitution cipher mapping - Provider-specific link extraction - Video source formats (mp4 vs m3u8) ### Key Constants ```rust const USER_AGENT: &str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/121.0"; const ALLANIME_REFERER: &str = "https://allmanga.to"; const ALLANIME_API: &str = "https://api.allanime.day"; const ALLANIME_BASE: &str = "allanime.day"; ``` --- ## History File - **Linux**: `~/.local/state/anime/history.json` - **Windows**: `C:\Users\\AppData\Local\anime\state\history.json` - Resolved via the `directories` crate (`ProjectDirs::from("", "", "anime")`) Format (JSON for easy serde): ```json [ { "show_id": "abc123", "title": "Cyberpunk Edgerunners", "episode": "5", "mode": "sub", "last_watched": "2026-04-14T12:00:00Z" } ] ``` --- ## Download Strategy ### Direct MP4 links - Use `reqwest` to stream the response body to a file - Show progress via content-length header + bytes received - No external tools needed ### m3u8 / HLS streams - Shell out to `yt-dlp` (preferred) or `ffmpeg` (fallback) via `std::process::Command` - Pass referrer header as argument - Capture stdout/stderr for progress reporting - This avoids reimplementing HLS segment fetching, concatenation, and remuxing ### Download directory - Default: current working directory (or configurable) - File naming: ` Episode .mp4` --- ## Build Targets | Platform | Target Triple | Notes | |---|---|---| | Arch Linux | `x86_64-unknown-linux-gnu` | Primary dev target | | Windows | `x86_64-pc-windows-msvc` | Cross-platform support | Both are tier 1 Rust targets with full support. --- ## Implementation Order 1. **Project setup** -- Add dependencies to `Cargo.toml`, basic eframe window 2. **API client** -- reqwest client with correct headers, test connectivity 3. **Cipher** -- Implement hex substitution decoder 4. **Search** -- GraphQL search query, parse results 5. **Episodes** -- GraphQL episode list query, parse results 6. **Sources** -- GraphQL embed query, decode providers, extract video links 7. **Playback** -- Open video URL in default player via `open` crate 8. **GUI: Search view** -- Text input, results list, selection 9. **GUI: Episodes view** -- Episode list, selection, play button 10. **GUI: Now playing view** -- Current episode info, next/prev/replay controls 11. **History** -- Read/write history file, continue watching flow 12. **Downloads** -- Direct mp4 download, m3u8 via subprocess, progress reporting 13. **Polish** -- Error handling, loading states, quality selection, sub/dub toggle