mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-20 17:02:53 -04:00
## What
A new workspace member, `artcraft-native/`. It is the ArtCraft desktop
app in pure Rust: an egui UI with no Tauri, no webview and no
JavaScript. It covers the two main product pages, **Create Image** and
**Create Video**, and reuses the Tauri-free API crates
(`artcraft_client`, `artcraft_api_defs`, `tokens`, `enums`).
It also adds:
- a Home page and a Library page
- a lightbox
- sign-in and settings dialogs
- a sidebar and top bar in the style of the brutalist
**artcraft-webapp**
Tools that aren't ported yet show a "coming soon" page that links to the
web app.
```bash
cargo run -p artcraft_native --release
```
## Why
To get a native, webview-free desktop app. Generation goes through
**OmniGen** (`/v1/omni_gen/{models,cost,generate}`), the same API as the
webapp. Model capabilities come from the server, so the pickers stay
current without app updates.
## Prompt box
Recreated feature for feature from `PromptBoxImage` / `PromptBoxVideo`:
- **Editor:** auto-grow, focus mode, resize grip, length counter with
the model's limit, Enter-to-generate setting, and `@Image1` / `@Video1`
/ `@Audio1` mentions with highlighting and autocomplete.
- **References:** the fanned reference deck (hover-expand, reorder, add
menus with limits) and the first/last keyframe slots with swap. Files
can be uploaded, picked from the library, dragged and dropped, or pasted
as images.
- **Model selector:** families with a flyout, maker logos and capability
badges.
- **Pickers:** aspect ratio, resolution, quality, count, bitrate, output
format, duration slider, sound and input mode (Keyframe / Omni
Reference).
- **Generate:** a live credit cost estimate, validation (starting frame,
text-only models, limits, uploads in progress), and clear-all with
confirmation.
The feed shows running jobs (with progress and time left), failures
(dismissable), finished results and the paginated library, in a masonry
grid or a list. It supports Recreate, Make Video, Share and Download,
plus select mode for batch downloads.
## Reviewer notes
- **Sign-in.** On first launch the app reuses an existing desktop login
by reading the session cookie from the Tauri app's jar, and keeps its
own copy in `~/Artcraft/credentials/native_session.json`. Browser
(device-code) and password sign-in are also available.
- **Decoding.**
- Generate and cost requests are sent as JSON maps, like the Tauri app's
omni path.
- Jobs, library, batch and prompt responses use lenient structs
(`backend/wire.rs`), so new server enum values can't break decoding.
- **Renderer.** It uses eframe's **glow** renderer. `wgpu-hal` fails to
build against the `windows` crate versions this workspace pins for
Tauri.
- **Model names and logos.** Known families use curated names: "Flux 1
Dev" rather than the server's "FLUX.1 [dev]". When the server reports
`artcraft` as a model's maker, the logo comes from the id prefix instead
(Nano Banana → Google), matching the webapp.
- **Fonts and assets.** Inter, Archivo and Geist Mono are bundled under
the OFL and listed in `NOTICE`. The wordmark, icon and maker logos are
the existing in-repo assets.
- **Diagnostics.** `ARTCRAFT_SCREENSHOT=<png>` (optionally with
`ARTCRAFT_PAGE` and `ARTCRAFT_SCREENSHOT_EXIT=1`) saves a screenshot
once the window has settled.
## Testing
- `cargo test -p artcraft_native`: 29 tests pass. Unit tests cover the
catalog, feed store, wire decoding and backend helpers. Headless
`egui_kittest` tests drive the prompt box: generate gating,
Enter-to-generate, pickers, `@` mentions and clear-all.
- `cargo clippy -p artcraft_native --all-targets --no-deps` is clean.
- Run against a real account: the session import, model lists, cost
estimates, job polling, library paging and thumbnails all worked.
- **Not exercised: a real paid generation and real uploads.** I held
back to avoid spending credits, so they need a manual check.
## Not done yet
- `@Character` mentions for Seedance 2.0
- Provider choice (Midjourney direct, fal); everything runs through
ArtCraft
- In-app video and audio playback; these open in the system player
- Animated previews in the feed
- The remaining tools (Audio, 3D, editors)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
107 lines
6.6 KiB
Markdown
107 lines
6.6 KiB
Markdown
# ArtCraft Native
|
|
|
|
ArtCraft's desktop app in pure Rust: an [egui](https://github.com/emilk/egui) UI over the same
|
|
ArtCraft API client crates the Tauri app uses. There is no Tauri, no webview and no JavaScript.
|
|
|
|
The look follows the brutalist webapp (`artcraft-services/frontend/apps/artcraft-webapp`). That
|
|
means near-black surfaces with white/15 hairlines and 3 px corners on controls. Type is Archivo for
|
|
display, Inter for body text and Geist Mono for labels. The brand blue marks the primary actions.
|
|
|
|
Create Image and Create Video are fully built. The other tools show a "coming soon" page that
|
|
links to the same tool in the web app.
|
|
|
|
## Running
|
|
|
|
```bash
|
|
cargo run -p artcraft_native --release
|
|
```
|
|
|
|
The workspace's default member is the Tauri app, so pass `-p artcraft_native`.
|
|
|
|
- **Sign-in.** On first launch the app reuses an existing ArtCraft login. It reads the session
|
|
cookie from the Tauri app's jar (`<cache dir>/ai.artcraft.app/.cookies`) and keeps its own copy in
|
|
`~/Artcraft/credentials/native_session.json`. Otherwise use "Sign in with browser" (device code)
|
|
or a username and password.
|
|
- **API host.** `~/Artcraft/settings/env_configs.json` selects it, exactly as for the Tauri app.
|
|
|
|
## Architecture
|
|
|
|
| Module | What it does |
|
|
|--------------------|--------------------------------------------------------------------------------|
|
|
| `backend` | Tokio runtime and every API call; results come back to the UI as `Event`s |
|
|
| `backend::wire` | Lenient response shapes; new server enum values can't break decoding |
|
|
| `backend::session` | Credentials: own file, Tauri cookie import, env config |
|
|
| `backend::media_cache` | Thumbnails and previews: downloaded and decoded off-thread, evicted when unused |
|
|
| `models` | Model catalog from OmniGen listings, plus names, families and limits |
|
|
| `prompt_box` | The shared prompt box: editor, reference deck, keyframes, pickers, model selector |
|
|
| `pages` | Create Image, Create Video, Home, Library, and the shared page shell |
|
|
| `feed` | Generation feed: running, failed and finished jobs, library paging, grid and list |
|
|
| `overlays` | Lightbox, library picker, sign-in and settings dialogs |
|
|
| `shell` | Sidebar and top bar |
|
|
| `theme`, `ui` | Colour and type tokens, Lucide-style vector icons, widgets, toasts |
|
|
|
|
How the backend works:
|
|
|
|
- **Generation.** It goes through OmniGen: `/v1/omni_gen/{models,cost,generate}/{image,video}`.
|
|
Model capabilities come from the server, so new models and options appear without an app update.
|
|
- **Typed client functions.** Model lists, uploads, credits, login and deletes use
|
|
`artcraft_client`.
|
|
- **Lenient decoding.** Generate and cost requests are JSON maps, as in the Tauri app. Job polling
|
|
(`/v1/jobs/session`), the library list, batches and prompts are decoded with lenient structs.
|
|
- **Identity headers.** Every request sends the desktop identity headers: `Origin` and
|
|
`User-Agent`.
|
|
|
|
## Prompt box parity
|
|
|
|
| Feature | Status |
|
|
|-----------------------------------------------------------------|-----------------------------------------|
|
|
| Auto-growing prompt (~4 lines), expand/collapse, resize grip | Done |
|
|
| Focus mode (fullscreen editor with deck and toolbar) | Done |
|
|
| Length counter, red over the model's limit | Done |
|
|
| Enter to generate (setting; Shift+Enter for a new line) | Done |
|
|
| `@Image1` / `@Video1` / `@Audio1` highlight and autocomplete | Done |
|
|
| Reference deck: fan, +N badge, hover-expand, reorder, clear all | Done |
|
|
| Keyframe slots: first/last frame, tilt, swap | Done |
|
|
| Upload, pick from library, drag & drop, paste image | Done (video uploads must be MP4) |
|
|
| Model selector with families, logos, capability badges | Done |
|
|
| Aspect ratio, resolution, quality, count | Done |
|
|
| Bitrate, output format, duration slider, sound, input mode | Done |
|
|
| Live credit cost on the generate button | Done |
|
|
| Validation: starting frame, text-only banner, limits, uploads | Done |
|
|
| Clear all (confirms when references are attached) | Done |
|
|
| `@Character` mentions and the Characters modal (Seedance 2.0) | Not yet |
|
|
| Provider choice (Midjourney direct, fal) | Not yet; everything runs via ArtCraft |
|
|
| In-app video and audio playback | Opens in the system player instead |
|
|
| Animated video previews in the feed | Still frames only |
|
|
|
|
Feed and lightbox:
|
|
|
|
- **Feed.** Pending cards show progress, time left and a batch banner. Failed cards show the reason
|
|
and can be dismissed. The grid is masonry, with a list view alongside. Hover actions are Recreate,
|
|
Make Video, Share and Download. Select mode does batch downloads. The last viewed item is marked.
|
|
- **Lightbox.** Prev/next with the arrow keys, prompt copy and details. Actions are Recreate, Make
|
|
Video, Download, Share and Delete.
|
|
|
|
## Diagnostics
|
|
|
|
Set `ARTCRAFT_SCREENSHOT=<file.png>` to save a screenshot once the window has settled.
|
|
`ARTCRAFT_PAGE` (`home`, `create-image`, `create-video` or `library`) picks the page, and
|
|
`ARTCRAFT_SCREENSHOT_EXIT=1` closes the app afterwards.
|
|
|
|
## Tests
|
|
|
|
```bash
|
|
cargo test -p artcraft_native
|
|
```
|
|
|
|
There are unit tests for the catalog, feed store, wire decoding and backend helpers. Headless UI
|
|
tests (`egui_kittest`) drive the prompt box: generate gating, Enter to generate, the pickers,
|
|
`@` mentions and clear-all.
|
|
|
|
## Fonts and brand assets
|
|
|
|
`assets/fonts` holds Inter, Archivo and Geist Mono, all under the SIL Open Font License; the
|
|
licences sit next to the files. The wordmark, app icon and creator logos are the Tauri app's own
|
|
(`frontend/apps/artcraft/app/public/resources`, `crates/desktop/artcraft/icons`); see `NOTICE`
|
|
for their terms.
|