Files
artcraft/artcraft-native/src/main.rs
T
BFlatandClaude Opus 5.5 bb27304b8b artcraft-native: custom title bar and Claude-style layout (#2068)
## What

The native app now draws its own window chrome, laid out like the Claude
desktop app.

- **Custom title bar** (40 px) replaces the native frame:
  - Left: the ArtCraft mark (goes Home) and the sidebar toggle.
- Right: credits, the account menu or Sign in, then minimize,
maximize/restore and close.
  - Dragging the empty space moves the window; a double-click maximizes.
  - On macOS the traffic lights stay, with room left for them.
- **Sidebar** is flush with the window's left edge, on the darker
chrome, with no floating card.
- **Content panel** is inset 8 px from the window edges, with rounded
corners and a hairline border. Its header holds the breadcrumbs and the
select and grid/list toggles.
- **Borderless window**: the edges and corners resize it, and a hairline
outlines it (hidden when maximized).

## Notes

- The window chrome helpers (`ui/window.rs`) are ported from the
ArtCraft Launcher, which uses the same egui 0.36.
- The mark is the in-repo `services/artcraft.svg`, tinted brand blue.
The old wordmark loader is removed.
- Toasts are moved down to sit below the new header.

## Testing

- `cargo test -p artcraft_native`: 29 tests pass.
- `cargo clippy -p artcraft_native --all-targets --no-deps` is clean.
- Screenshot-verified against a live account.
- Not tested by hand: dragging, resizing and the caption buttons.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 00:54:50 +07:00

36 lines
1.4 KiB
Rust

#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
//! ArtCraft, natively: an egui desktop app over the ArtCraft API (no Tauri, no webview).
mod app;
mod backend;
mod feed;
mod models;
mod overlays;
mod pages;
mod prompt_box;
mod shell;
mod theme;
mod ui;
const APP_ID: &str = "ai.artcraft.native";
fn main() -> eframe::Result {
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
let mut viewport = egui::ViewportBuilder::default().with_title("ArtCraft").with_app_id(APP_ID).with_inner_size([1440.0, 900.0]).with_min_inner_size([960.0, 640.0]);
if let Some(icon) = app_icon() {
viewport = viewport.with_icon(icon);
}
// The app draws its own title bar; macOS keeps its traffic lights over it.
viewport = if cfg!(target_os = "macos") { viewport.with_fullsize_content_view(true).with_titlebar_shown(false).with_title_shown(false) } else { viewport.with_decorations(false) };
let options = eframe::NativeOptions { viewport, persist_window: true, ..Default::default() };
eframe::run_native("ArtCraft", options, Box::new(|cc| Ok(Box::new(app::ArtcraftApp::new(cc)))))
}
/// The window and taskbar icon.
fn app_icon() -> Option<egui::IconData> {
const ICON: &[u8] = include_bytes!("../../crates/desktop/artcraft/icons/icon.png");
let rgba = image::load_from_memory(ICON).ok()?.into_rgba8();
Some(egui::IconData { width: rgba.width(), height: rgba.height(), rgba: rgba.into_raw() })
}