feat(clients): the OS marks tell gaming distros apart, and Windows looks current
Three things were wrong with the host-card OS icons. The Windows mark was Font Awesome 5's, which is still the Windows 8/10 flag with the perspective skew — dated next to the flat four-pane mark Microsoft has shipped since Windows 11. No icon set has the current one (Simple Icons carries no windows/microsoft slug at all), so it is drawn here: four equal squares at the authentic 11.377 + 1.246 proportion. The Decky plugin was pulling FaWindows straight from react-icons, so it now inlines the masters like the web console does, or it would have kept the old flag regardless. Bazzite, CachyOS and Nobara collapsed onto their family's mark. The host already advertises the full chain, so this is purely missing art: all three now ship a leaf mark, because "a Bazzite box" and "a Fedora box" are different machines to the person reading the card. CachyOS and Nobara come from Simple Icons; Bazzite has no icon anywhere, so its "b" is lifted out of the project's own badge (Apache-2.0, attributed). On Android every non-square mark was stretched. A VectorPainter maps the viewport onto the ImageVector's default size with independent x and y scales, so declaring a 448x512 Tux as 24x24 dp squashed it — silently, no crash, no warning. The longest viewport edge now sets the 24 dp box and the other follows the ratio, which is what Icon()'s ContentScale.Fit expects. A unit test pins the invariant; every other client was already correct. Also: scripts/gen-os-icons.sh replaces the undocumented hand-run pipeline that turns a master into the GTK symbolic SVG, the Windows PNG and the Apple template PDF. It reproduces the committed artifacts byte-identically. Verified: web and Decky typecheck, Decky bundles, Android compiles and its tests pass, PunktfunkKit builds, osinfo's tests pass. Not verified on glass, and the GTK/Windows client crates do not build on macOS. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Executable
+97
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env bash
|
||||
# Derive the per-client host-OS-icon assets from the assets/os-icons masters.
|
||||
#
|
||||
# The masters are monochrome `fill="currentColor"` SVGs, one per icon token of the host's
|
||||
# OS-identity chain (see assets/os-icons/README.md). Three clients need a baked derivative
|
||||
# because they cannot consume the master directly:
|
||||
#
|
||||
# GTK shell symbolic SVG, black fill -> clients/linux/data/icons/scalable/actions/
|
||||
# Windows shell PNG, h=32, mid-grey -> clients/windows/assets/os/
|
||||
# Apple clients vector PDF, black fill -> clients/apple/.../OsIcons.xcassets/
|
||||
#
|
||||
# The web console, the Decky plugin and the Android client transcribe the master's path
|
||||
# data inline instead — those are hand-kept, and this script prints them at the end so a
|
||||
# new token can be pasted straight in.
|
||||
#
|
||||
# Idempotent. Usage: bash scripts/gen-os-icons.sh [token ...] (default: every master)
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
MASTERS=assets/os-icons
|
||||
GTK=clients/linux/data/icons/scalable/actions
|
||||
WIN=clients/windows/assets/os
|
||||
APPLE=clients/apple/Sources/PunktfunkKit/Resources/OsIcons.xcassets
|
||||
|
||||
# The Windows shell has no vector element and no theme-aware tint, so its PNGs are baked in
|
||||
# one mid-grey that stays legible on both the light and the dark WinUI theme.
|
||||
WIN_GREY='#8A8F98'
|
||||
WIN_HEIGHT=32
|
||||
|
||||
log() { printf '\033[1;36m==>\033[0m %s\n' "$*"; }
|
||||
|
||||
command -v rsvg-convert >/dev/null 2>&1 || {
|
||||
echo "rsvg-convert not found (brew install librsvg / apt install librsvg2-bin)" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
tokens=("$@")
|
||||
if [ ${#tokens[@]} -eq 0 ]; then
|
||||
for f in "$MASTERS"/*.svg; do tokens+=("$(basename "$f" .svg)"); done
|
||||
fi
|
||||
|
||||
tmp=$(mktemp -d)
|
||||
trap 'rm -rf "$tmp"' EXIT
|
||||
|
||||
for t in "${tokens[@]}"; do
|
||||
src="$MASTERS/$t.svg"
|
||||
[ -f "$src" ] || { echo "no master for token '$t' ($src)" >&2; exit 1; }
|
||||
log "$t"
|
||||
|
||||
# GTK: the master with the fill resolved to black — Adwaita recolors a `-symbolic` icon
|
||||
# from the fill it finds, so the value only has to be a real colour, not the final one.
|
||||
sed 's/currentColor/#000000/' "$src" > "$GTK/pf-os-$t-symbolic.svg"
|
||||
|
||||
# Windows: same black-to-grey substitution, rasterized at a fixed height so every mark
|
||||
# shares an optical size and keeps its own aspect ratio.
|
||||
sed "s/currentColor/$WIN_GREY/" "$src" > "$tmp/$t.grey.svg"
|
||||
rsvg-convert -h "$WIN_HEIGHT" -f png -o "$WIN/$t.png" "$tmp/$t.grey.svg"
|
||||
|
||||
# Apple: a vector PDF at the master's natural size, in a template imageset — SwiftUI
|
||||
# tints it from foregroundStyle, so the baked colour is irrelevant.
|
||||
sed 's/currentColor/#000000/' "$src" > "$tmp/$t.black.svg"
|
||||
mkdir -p "$APPLE/os-$t.imageset"
|
||||
rsvg-convert -f pdf -o "$APPLE/os-$t.imageset/$t.pdf" "$tmp/$t.black.svg"
|
||||
cat > "$APPLE/os-$t.imageset/Contents.json" <<JSON
|
||||
{
|
||||
"images" : [
|
||||
{ "filename" : "$t.pdf", "idiom" : "universal" }
|
||||
],
|
||||
"info" : { "author" : "xcode", "version" : 1 },
|
||||
"properties" : {
|
||||
"preserves-vector-representation" : true,
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
||||
JSON
|
||||
done
|
||||
|
||||
echo
|
||||
log "Inline path data (web/src/components/os-icon.tsx, clients/decky/src/os-icon.tsx,"
|
||||
log " clients/android/.../components/OsIcons.kt — hand-kept, paste from here)"
|
||||
for t in "${tokens[@]}"; do
|
||||
python3 - "$MASTERS/$t.svg" "$t" <<'PY'
|
||||
import re, sys
|
||||
svg = open(sys.argv[1]).read()
|
||||
box = re.search(r'viewBox="([^"]+)"', svg).group(1)
|
||||
d = re.search(r'<path[^>]* d="([^"]+)"', svg).group(1)
|
||||
w, h = box.split()[2:]
|
||||
print(f'\n {sys.argv[2]}: viewBox "{box}" (viewport {w} x {h})\n {d}')
|
||||
PY
|
||||
done
|
||||
|
||||
echo
|
||||
log "Remember: a NEW token also has to be added to each client's shipped-token list —"
|
||||
log " clients/linux/src/ui_hosts.rs, clients/linux/data/resources.gresource.xml,"
|
||||
log " clients/windows/src/app/os_icons.rs, clients/apple/.../PunktfunkKit/OsIcon.swift,"
|
||||
log " plus the three inline registries above."
|
||||
@@ -68,14 +68,17 @@ VENDORED_TREES = [
|
||||
("Vulkan-Headers (vendored, crates/pyrowave-sys)",
|
||||
"crates/pyrowave-sys/vendor/pyrowave/Granite/third_party/khronos/vulkan-headers/LICENSE.md",
|
||||
"https://github.com/KhronosGroup/Vulkan-Headers"),
|
||||
# OS brand marks for the host-card OS icon (assets/os-icons/, CC BY 4.0 / CC0 —
|
||||
# see assets/os-icons/README.md; clients embed per-platform derivatives).
|
||||
# OS brand marks for the host-card OS icon (assets/os-icons/, CC BY 4.0 / CC0 /
|
||||
# Apache-2.0 — see assets/os-icons/README.md; clients embed per-platform derivatives).
|
||||
("Font Awesome Free brand icons (vendored, assets/os-icons)",
|
||||
"assets/os-icons/LICENSES/font-awesome-brands.txt",
|
||||
"https://fontawesome.com"),
|
||||
("Simple Icons (vendored, assets/os-icons)",
|
||||
"assets/os-icons/LICENSES/simple-icons.txt",
|
||||
"https://simpleicons.org"),
|
||||
("Bazzite logo (vendored, assets/os-icons)",
|
||||
"assets/os-icons/LICENSES/bazzite.txt",
|
||||
"https://github.com/ublue-os/bazzite"),
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user