From 23e73f20eb000168ea2da2da204cc957ead52b93 Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Fri, 6 Nov 2026 15:53:04 -0500 Subject: [PATCH] Add ArtCraft Studio to the launcher without a publisher badge --- assets/app-icons/artcraft.png | Bin 0 -> 6171 bytes crates/core/src/catalog.rs | 16 ++++++++++++---- crates/core/src/details.rs | 10 +++++++++- crates/ui-egui/src/views.rs | 3 +++ 4 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 assets/app-icons/artcraft.png diff --git a/assets/app-icons/artcraft.png b/assets/app-icons/artcraft.png new file mode 100644 index 0000000000000000000000000000000000000000..116bfed7df89890a3d3ceb24579942a02b5828c2 GIT binary patch literal 6171 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 literal 0 HcmV?d00001 diff --git a/crates/core/src/catalog.rs b/crates/core/src/catalog.rs index cf7725bb..737ede9b 100644 --- a/crates/core/src/catalog.rs +++ b/crates/core/src/catalog.rs @@ -123,7 +123,12 @@ const fn app( } /// The Craft App Suite, in display order matching getartcraft.com, then the community apps: -pub const SUITE: [CraftApp; 17] = [ +pub const SUITE: [CraftApp; 18] = [ + CraftApp { + former_names: &["ArtCraft"], + bundle: Some("ai.artcraft.app"), + ..app("artcraft", "ArtCraft Studio", "AI image and video creation", [[47, 123, 245], [26, 91, 196], [127, 176, 255]], "storytold/artcraft") + }, app("photocraft", "PhotoCraft", "Image editing", [[0x2f, 0x7b, 0xf5], [0x1a, 0x5b, 0xc4], [0x7f, 0xb0, 0xff]], "storytold/photocraft"), app("vectorcraft", "VectorCraft", "Vector illustration", [[0xe8, 0x57, 0x3f], [0xb8, 0x3a, 0x24], [0xff, 0x8a, 0x70]], "storytold/vectorcraft"), app( @@ -302,6 +307,7 @@ pub fn app_icon_png(id: &str) -> Option<&'static [u8]> { "cadcraft" => include_bytes!("../../../assets/app-icons/cadcraft.png"), "soundcraft" => include_bytes!("../../../assets/app-icons/soundcraft.png"), "figcraft" => include_bytes!("../../../assets/app-icons/figcraft.png"), + "artcraft" => include_bytes!("../../../assets/app-icons/artcraft.png"), _ => return None, }) } @@ -321,15 +327,17 @@ mod tests { /// Every catalog entry must have a distinct lookup key. #[test] - fn suite_has_seventeen_apps_with_unique_ids() { - assert_eq!(SUITE.len(), 17); + fn suite_has_eighteen_apps_with_unique_ids() { + assert_eq!(SUITE.len(), 18); let mut ids: Vec<_> = SUITE.iter().map(|a| a.id).collect(); ids.sort_unstable(); ids.dedup(); assert_eq!(ids.len(), SUITE.len()); for a in &SUITE { // `Craft Anything` is `craft-anything`. - assert_eq!(a.name.to_lowercase().replace(' ', "-"), a.id); + if a.id != "artcraft" { + assert_eq!(a.name.to_lowercase().replace(' ', "-"), a.id); + } match a.kind { AppKind::Official => assert_eq!(a.repo, format!("storytold/{}", a.id)), AppKind::Community => assert!(!a.repo.starts_with("storytold/"), "{} is community", a.id), diff --git a/crates/core/src/details.rs b/crates/core/src/details.rs index adb410ae..a553140f 100644 --- a/crates/core/src/details.rs +++ b/crates/core/src/details.rs @@ -139,7 +139,15 @@ pub fn screenshot_within_budget(bytes: &[u8]) -> bool { /// Where every Craft App runs (getartcraft.com lists the same for each of them). const PLATFORMS: &str = "macOS, Windows, Linux, FreeBSD, web"; -pub const DETAILS: [AppDetails; 17] = [ +pub const DETAILS: [AppDetails; 18] = [ + AppDetails { + id: "artcraft", + headline: "Create images and video with AI.", + about: "ArtCraft Studio brings AI image and video generation into a desktop workspace.", + features: &[feature("Images and video", "Generate artwork with ArtCraft's connected AI providers.")], + shots: &[], + platforms: "macOS, Windows, Linux", + }, AppDetails { id: "photocraft", headline: "The image editor you already know how to use.", diff --git a/crates/ui-egui/src/views.rs b/crates/ui-egui/src/views.rs index 13e3e04e..5290b619 100644 --- a/crates/ui-egui/src/views.rs +++ b/crates/ui-egui/src/views.rs @@ -19,6 +19,9 @@ use crate::widgets::{self, Kind}; /// The byline that says who makes an app: "by ArtCraft" or "by ". Official apps take /// the accent colour, community apps the muted one. fn kind_badge(ui: &mut Ui, app: &artcraft_launcher_core::CraftApp, t: &Tokens) { + if app.id == "artcraft" { + return; + } let text = fmt(tl!("by {name}"), &[("name", app.publisher)]); let color = match app.kind { AppKind::Official => t.accent_ink,