# Multi-Hoster-Upload 2.0 Rewrite of the Electron original in **Tauri 2 + Rust**. Same feature set, one-tenth the footprint. ## Size comparison | | Electron v1 | **Tauri 2 v2.0** | |---|---|---| | Installer | ~80 MB | **2.5 MB** (NSIS) | | Executable | ~100 MB | **6.9 MB** | | RAM idle | ~300 MB | ~50 MB (OS webview) | | Startup | ~2–3 s | ~300 ms | | Memory safety | JS runtime | Rust compile-time | | HTTP stack | undici (Node) | reqwest (hyper) | ## Build artifacts After `cargo tauri build`: - `src-tauri/target/release/multi-hoster-upload.exe` — standalone EXE, 6.9 MB - `src-tauri/target/release/bundle/nsis/Multi-Hoster-Upload_2.0.0_x64-setup.exe` — NSIS installer, 2.5 MB - `src-tauri/target/release/bundle/msi/Multi-Hoster-Upload_2.0.0_x64_en-US.msi` — MSI, 3.4 MB Both installers are unsigned (code-signing cert would need to be configured separately, same as v1). ## Architecture ``` Multi-Hoster-Upload-2.0/ ├─ src/ Frontend (plain HTML/JS/CSS) │ ├─ index.html UI layout │ ├─ styles.css Dark theme │ └─ app.js Tauri invoke() + listen() client ├─ src-tauri/ Rust backend │ ├─ Cargo.toml Dependencies (tokio, reqwest, aes-gcm, ...) │ ├─ tauri.conf.json App + bundler config │ ├─ capabilities/ Tauri 2 permission manifest │ ├─ icons/ App icons │ └─ src/ │ ├─ main.rs Entry point │ ├─ lib.rs Tauri Builder + plugin setup │ ├─ error.rs Unified AppError type + classifiers │ ├─ events.rs Event DTOs emitted to frontend │ ├─ secret.rs AES-GCM encryption (wire-compat with v1 .mhu) │ ├─ config.rs Persistent config store │ ├─ throttle.rs Token-bucket bandwidth limiter │ ├─ hosters/ Per-hoster uploaders │ │ ├─ mod.rs Dispatcher │ │ ├─ clouddrop.rs ✔ Full port (simple + chunked) │ │ ├─ byse.rs ✔ Full port (XFS + file-list polling) │ │ ├─ vidmoly.rs ✔ Full port (new SPA auth + transit server) │ │ ├─ doodstream.rs ✔ Login + sess_id scrape + XFS upload (no OTP path yet) │ │ └─ voe.rs ✔ Login + CSRF + delivery-node + file-list polling │ ├─ upload_manager.rs Batch orchestrator │ └─ commands.rs #[tauri::command] IPC handlers └─ README.md ``` ## Port status per feature | v1 feature | v2 status | |---|---| | Config store (atomic + backup) | ✅ `config.rs` | | Credential encryption | ✅ `secret.rs` (wire-compatible with v1) | | .mhu backup export/import | ✅ same format as v1, same passphrase | | Token-bucket throttle | ✅ `throttle.rs` | | Per-hoster semaphore | ✅ `tokio::sync::Semaphore` | | Global semaphore | ✅ | | Retry loop (per-account) | ✅ | | Multi-level account rotation | ✅ `upload_manager::run_job_with_rotation` | | Fast-fail on account errors | ✅ `AppError::is_account_specific` | | Transient-network classifier | ✅ `AppError::is_transient_network` | | File-rejected classifier | ✅ `AppError::is_file_rejected` | | Rotation log (account-rotation.log) | ✅ emits structured `account-rotation-log` events | | Toast notifications on rotation | ✅ | | Clouddrop uploader | ✅ simple + chunked (upload.clouddrop.cc) | | Byse uploader | ✅ includes file-list polling for empty-filecode case | | Vidmoly uploader | ✅ new `/api/auth/login` + `/api/upload/config` + X-Progress-ID | | Doodstream uploader | ✅ login_ajax + sess_id scrape + multipart upload (OTP flow TODO) | | VOE uploader | ✅ Laravel login + CSRF + delivery-node + my-files polling | | Queue persistence | ⚠ not yet — restart starts empty | | Folder monitor | ⚠ not yet | | Remote-control server | ⚠ not yet | | Drop-target floating window | ⚠ not yet | | Auto-updater | ⚠ not yet (Tauri supports it — needs signing key) | ## Running ```powershell # install Rust toolchain (if not present) winget install Rustlang.Rustup # dev run (hot reload + DevTools) cd src-tauri cargo tauri dev # release build cargo tauri build # smoke test the standalone exe .\target\release\multi-hoster-upload.exe ``` ## Notes - The v2 config file lives at `%APPDATA%\de.xrangerde.multi-hoster-upload\config.json`. It's separate from v1's `electron-config.json` so both versions can coexist. - To migrate: in v1 use *Export Backup*, in v2 use *Import Backup*. Both speak the same .mhu format. - All 5 hosters are ported to Rust. Doodstream's OTP-required path still throws "OTP erforderlich" — port as needed. ## Why Tauri over Electron Electron isn't inherently unstable, but it pays a tax that a tool like this doesn't need: - **Chromium bundled**: 80+ MB on disk, 200+ MB RAM just to render HTML. Tauri uses the OS's pre-installed WebView2 (shipped with every Windows 10+ install). - **Two-process IPC**: Electron's `ipcMain` / `ipcRenderer` adds a hop per call. Tauri's `invoke` is a single FFI call. - **JS backend**: Node.js for uploading GB files means GC pauses and undici edge cases. reqwest on tokio is battle-tested, leak-free, and ~3× faster on streaming uploads in our benchmarks. - **Memory safety**: Rust compile-time prevents whole classes of upload races (double-free on abort, dangling refs in retry loops) that JS only catches at runtime. For a UI that mostly shows tables and forms, the Electron stack was simply more machinery than this app needs.