From 4aa07a56f8828ace7d43adc09c8890b31f157330 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Fri, 9 Oct 2026 22:23:59 -0400 Subject: [PATCH] Social links: X, YouTube, TikTok and Instagram icons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Small monochrome service icons (Simple Icons 16.34.0, CC0) linking to ArtCraft's accounts, after Website · GitHub · Discord in the footer and in Settings › Community; quieter than Discord, brighter on hover - Settings: the community description gets its own line, so the Website and GitHub buttons no longer overlap it - Credit the icons in assets/social/README.md, ATTRIBUTION.md and NOTICE Co-Authored-By: Claude Opus 5.5 --- ATTRIBUTION.md | 1 + NOTICE | 3 +++ assets/social/README.md | 10 ++++++++++ assets/social/instagram.svg | 1 + assets/social/tiktok.svg | 1 + assets/social/x.svg | 1 + assets/social/youtube.svg | 1 + crates/core/src/catalog.rs | 8 ++++++++ crates/ui-egui/src/dialogs.rs | 15 ++++++++++----- crates/ui-egui/src/icons.rs | 11 +++++++++++ crates/ui-egui/src/views.rs | 7 ++++++- crates/ui-egui/src/widgets.rs | 21 +++++++++++++++++++++ crates/ui-egui/tests/ui.rs | 5 +++++ 13 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 assets/social/README.md create mode 100644 assets/social/instagram.svg create mode 100644 assets/social/tiktok.svg create mode 100644 assets/social/x.svg create mode 100644 assets/social/youtube.svg diff --git a/ATTRIBUTION.md b/ATTRIBUTION.md index f1840e1..6dea0bd 100644 --- a/ATTRIBUTION.md +++ b/ATTRIBUTION.md @@ -11,6 +11,7 @@ next to them. | Path | Title | Author | Source | License | |---|---|---|---|---| | `assets/app-icon/` (all files) | ArtCraft Launcher app icon (grid of app-coloured tiles with a launch arrow) | ArtCraft Launcher contributors | Original work, see [`assets/app-icon/README.md`](assets/app-icon/README.md) | MIT OR Apache-2.0, [`assets/app-icon/LICENSE.txt`](assets/app-icon/LICENSE.txt) | +| `assets/social/x.svg`, `youtube.svg`, `tiktok.svg`, `instagram.svg` | X, YouTube, TikTok and Instagram logos, linking to ArtCraft's accounts | [Simple Icons](https://simpleicons.org/) contributors | Simple Icons, `fill` set to white for tinting; see [`assets/social/README.md`](assets/social/README.md) | CC0 1.0. The logos are trademarks of X Corp., Google LLC, TikTok / ByteDance and Meta Platforms, Inc. | | `docs/brand/artcraft-logo.svg`, `artcraft-logo-white.svg` | ArtCraft wordmark, shown in the window header | ArtCraft Team | Supplied brand files, unmodified (same as PhotoCraft's `docs/brand/`) | **Not open source; not MIT or Apache-2.0.** ArtCraft trademark, [`docs/brand/LICENSE-brand.txt`](docs/brand/LICENSE-brand.txt) | | `docs/brand/artcraft-mark-64.png`, `artcraft-mark-black-44.png` | ArtCraft "A" mark, the tray / menu-bar icon | ArtCraft Team | Rendered unmodified from `docs/brand/artcraft-mark.svg` and `artcraft-mark-black.svg` by `packaging/icons.sh` | **Not open source; not MIT or Apache-2.0.** ArtCraft trademark, [`docs/brand/LICENSE-brand.txt`](docs/brand/LICENSE-brand.txt) | | `assets/fonts/Inter-Regular.ttf`, `Inter-Medium.ttf`, `Inter-SemiBold.ttf` | Inter 4.001 (UI font) | The Inter Project Authors (Rasmus Andersson) | (copied from PhotoCraft's `assets/fonts/`) | SIL OFL 1.1, [`assets/fonts/OFL-Inter.txt`](assets/fonts/OFL-Inter.txt) | diff --git a/NOTICE b/NOTICE index 3c5f99a..e5844f1 100644 --- a/NOTICE +++ b/NOTICE @@ -14,6 +14,9 @@ Third-party material This product bundles third-party material under its own licenses, listed below. The per-file list (author, source, license) is in ATTRIBUTION.md. +Social service icons (assets/social/*.svg) — Simple Icons, CC0 1.0. The X, YouTube, TikTok and +Instagram logos are trademarks of their respective owners and are used only to link to ArtCraft's +accounts. Inter font (assets/fonts/Inter-*.ttf) — SIL Open Font License 1.1. See assets/fonts/OFL-Inter.txt. Craft App Suite app icons (assets/app-icons/*.png) — from each app's repository (github.com/storytold/), MIT OR Apache-2.0, Copyright (c) 2026 ArtCraft Team and the diff --git a/assets/social/README.md b/assets/social/README.md new file mode 100644 index 0000000..d677d38 --- /dev/null +++ b/assets/social/README.md @@ -0,0 +1,10 @@ +Social service icons +==================== + +`x.svg`, `youtube.svg`, `tiktok.svg` and `instagram.svg` are from [Simple Icons](https://simpleicons.org/) +16.34.0 (`https://cdn.jsdelivr.net/npm/simple-icons@16.34.0/icons/.svg`), released under +[CC0 1.0](https://github.com/simple-icons/simple-icons/blob/develop/LICENSE.md). The only change is +`fill="#ffffff"` on the root element, so the app can tint them to the theme. + +The logos themselves are trademarks of their owners (X Corp., Google LLC, TikTok / ByteDance Ltd. +and Meta Platforms, Inc.). They are used only to link to ArtCraft's own accounts on those services. diff --git a/assets/social/instagram.svg b/assets/social/instagram.svg new file mode 100644 index 0000000..cdbf501 --- /dev/null +++ b/assets/social/instagram.svg @@ -0,0 +1 @@ +Instagram \ No newline at end of file diff --git a/assets/social/tiktok.svg b/assets/social/tiktok.svg new file mode 100644 index 0000000..e9a9d3b --- /dev/null +++ b/assets/social/tiktok.svg @@ -0,0 +1 @@ +TikTok \ No newline at end of file diff --git a/assets/social/x.svg b/assets/social/x.svg new file mode 100644 index 0000000..93bb5ca --- /dev/null +++ b/assets/social/x.svg @@ -0,0 +1 @@ +X \ No newline at end of file diff --git a/assets/social/youtube.svg b/assets/social/youtube.svg new file mode 100644 index 0000000..33e276a --- /dev/null +++ b/assets/social/youtube.svg @@ -0,0 +1 @@ +YouTube \ No newline at end of file diff --git a/crates/core/src/catalog.rs b/crates/core/src/catalog.rs index 3697758..3dbe2ed 100644 --- a/crates/core/src/catalog.rs +++ b/crates/core/src/catalog.rs @@ -159,6 +159,14 @@ affiliated with, sponsored by or endorsed by any of these companies."; pub const WEBSITE_URL: &str = "https://getartcraft.com"; /// ArtCraft on GitHub: every Craft App's source. pub const GITHUB_URL: &str = "https://github.com/storytold"; +/// ArtCraft's social accounts: (service, URL). Shown as small icons, less prominent than Discord. +pub const SOCIAL: [(&str, &str); 4] = [ + ("X", "https://x.com/get_artcraft"), + ("YouTube", "https://www.youtube.com/@OfficialArtcraftStudios"), + ("TikTok", "https://www.tiktok.com/@artcraft.studios"), + ("Instagram", "https://www.instagram.com/officialartcraftstudios"), +]; + /// The ArtCraft community on Discord. pub const DISCORD_URL: &str = "https://discord.gg/artcraft"; diff --git a/crates/ui-egui/src/dialogs.rs b/crates/ui-egui/src/dialogs.rs index ef4a161..6b7371e 100644 --- a/crates/ui-egui/src/dialogs.rs +++ b/crates/ui-egui/src/dialogs.rs @@ -160,18 +160,23 @@ impl LauncherUi { } section(ui, "Community"); - row(ui, "Questions, ideas and news from the ArtCraft team", &mut |ui| { + ui.label(RichText::new("Questions, ideas and news from the ArtCraft team").color(t.text_muted)); + ui.add_space(4.0); + ui.horizontal(|ui| { use artcraft_launcher_core::catalog::{DISCORD_URL, GITHUB_URL, WEBSITE_URL}; - // Right to left: Website, GitHub, Discord. if widgets::discord_button(ui).clicked() { ui.ctx().open_url(egui::OpenUrl::new_tab(DISCORD_URL)); } - if widgets::secondary(ui, "GitHub", 0.0).on_hover_text(GITHUB_URL).clicked() { - ui.ctx().open_url(egui::OpenUrl::new_tab(GITHUB_URL)); - } if widgets::secondary(ui, "Website", 0.0).on_hover_text(WEBSITE_URL).clicked() { ui.ctx().open_url(egui::OpenUrl::new_tab(WEBSITE_URL)); } + if widgets::secondary(ui, "GitHub", 0.0).on_hover_text(GITHUB_URL).clicked() { + ui.ctx().open_url(egui::OpenUrl::new_tab(GITHUB_URL)); + } + ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { + ui.spacing_mut().item_spacing.x = 4.0; + widgets::social_icons(ui, 16.0); + }); }); section(ui, "Appearance"); diff --git a/crates/ui-egui/src/icons.rs b/crates/ui-egui/src/icons.rs index 83429ac..c39f7ad 100644 --- a/crates/ui-egui/src/icons.rs +++ b/crates/ui-egui/src/icons.rs @@ -34,6 +34,17 @@ pub fn artcraft_logo(dark_background: bool) -> ImageSource<'static> { /// The ArtCraft wordmark's width / height (its SVG view box: 1038.05 × 108). pub const ARTCRAFT_LOGO_ASPECT: f32 = 1038.05 / 108.0; +/// A social service's logo (Simple Icons, white, for tinting), by its name in `catalog::SOCIAL`. +pub fn social(service: &str) -> Option> { + Some(match service { + "X" => egui::include_image!("../../../assets/social/x.svg"), + "YouTube" => egui::include_image!("../../../assets/social/youtube.svg"), + "TikTok" => egui::include_image!("../../../assets/social/tiktok.svg"), + "Instagram" => egui::include_image!("../../../assets/social/instagram.svg"), + _ => return None, + }) +} + /// The launcher's icon. pub fn launcher() -> ImageSource<'static> { egui::include_image!("../../../assets/app-icon/hicolor/128x128/apps/ai.storyteller.artcraft-launcher.png") diff --git a/crates/ui-egui/src/views.rs b/crates/ui-egui/src/views.rs index 991c4fb..aa451e8 100644 --- a/crates/ui-egui/src/views.rs +++ b/crates/ui-egui/src/views.rs @@ -195,7 +195,12 @@ impl LauncherUi { }; ui.label(small(label)); ui.add_space(14.0); - // Right to left: these read Website · GitHub · Discord. + // Right to left, so this reads: Website · GitHub · Discord, then the social icons. + ui.scope(|ui| { + ui.spacing_mut().item_spacing.x = 2.0; + widgets::social_icons(ui, 13.0); + }); + ui.add_space(8.0); use artcraft_launcher_core::catalog::{DISCORD_URL, GITHUB_URL, WEBSITE_URL}; widgets::small_link(ui, "Discord", DISCORD_URL); ui.label(RichText::new("·").size(11.5).color(t.text_faint)); diff --git a/crates/ui-egui/src/widgets.rs b/crates/ui-egui/src/widgets.rs index fba05bb..b664677 100644 --- a/crates/ui-egui/src/widgets.rs +++ b/crates/ui-egui/src/widgets.rs @@ -235,3 +235,24 @@ pub fn small_link(ui: &mut Ui, text: &str, url: &str) -> Response { } resp } + +/// ArtCraft's social accounts as a row of small monochrome icons (faint, brighter on hover). +/// In a right-to-left layout they still read left to right. +pub fn social_icons(ui: &mut Ui, size: f32) { + let t = Tokens::get(ui.ctx()); + let rtl = ui.layout().prefer_right_to_left(); + let services = artcraft_launcher_core::catalog::SOCIAL; + let ordered: Vec<&(&str, &str)> = if rtl { services.iter().rev().collect() } else { services.iter().collect() }; + for (name, url) in ordered { + let Some(icon) = crate::icons::social(name) else { continue }; + let pad = 4.0; + let (rect, resp) = ui.allocate_exact_size(vec2(size + 2.0 * pad, size + 2.0 * pad), Sense::click()); + let color = if resp.hovered() { t.text } else { t.text_faint }; + egui::Image::new(icon).tint(color).paint_at(ui, rect.shrink(pad)); + resp.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::Link, true, *name)); + let resp = resp.on_hover_text(format!("ArtCraft on {name}")).on_hover_cursor(egui::CursorIcon::PointingHand); + if resp.clicked() { + ui.ctx().open_url(egui::OpenUrl::new_tab(*url)); + } + } +} diff --git a/crates/ui-egui/tests/ui.rs b/crates/ui-egui/tests/ui.rs index 88fb508..fa0189c 100644 --- a/crates/ui-egui/tests/ui.rs +++ b/crates/ui-egui/tests/ui.rs @@ -332,6 +332,11 @@ fn links_open_the_right_pages() { let sites = all_opened(&mut h, "Website"); assert!(sites.contains(&"https://getartcraft.com".to_string()), "{sites:?}"); assert!(sites.contains(&"https://getartcraft.com/apps/photocraft".to_string()), "{sites:?}"); + // Social icons in the footer. + assert_eq!(click_opens(&mut h, "X").as_deref(), Some("https://x.com/get_artcraft")); + assert_eq!(click_opens(&mut h, "YouTube").as_deref(), Some("https://www.youtube.com/@OfficialArtcraftStudios")); + assert_eq!(click_opens(&mut h, "TikTok").as_deref(), Some("https://www.tiktok.com/@artcraft.studios")); + assert_eq!(click_opens(&mut h, "Instagram").as_deref(), Some("https://www.instagram.com/officialartcraftstudios")); // The … menu. h.get_all_by_label("…").next().unwrap().click(); h.run_steps(3);