testsAndMisc/python_pkg/app_icons
Krzysztof Rudnicki 45f4311993
Some checks are pending
Pre-commit checks / pre-commit (push) Waiting to run
Python tests / test (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
app_icons: add home_inventory storage-box glyph; whitelist it on the phone
The new ~/home_inventory Flutter app needs two things from this repo: a
family launcher icon, and a focus-mode whitelist entry so the daemon does
not pm disable-user it ~1s after launch.

The glyph is an isometric carton — a hexagon plus the three edges meeting
at the near-top corner. A front-on rectangle with a lid seam was tried
first and rejected on the contact sheet: a seam plus a divider reads as a
browser window, not a box.

Body is 488x440, not a rounder 500x440, because STROKE_WIDTH straddles the
path and adds 72px to each rendered dimension; 488 is the widest body whose
ink still fits SAFE_BOX. The generator warned about exactly this at 500.

Accent stays the one shared family accent — apps differ by glyph, not
colour.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-27 07:35:55 +02:00
..
tests app_icons: auto-sync pubspec.yaml's adaptive_icon_background 2026-07-21 21:38:22 +02:00
__init__.py Add shared launcher-icon generator for the Flutter apps 2026-07-19 16:55:48 +02:00
__main__.py Add shared launcher-icon generator for the Flutter apps 2026-07-19 16:55:48 +02:00
apps.py app_icons: add home_inventory storage-box glyph; whitelist it on the phone 2026-07-27 07:35:55 +02:00
cli.py Add shared launcher-icon generator for the Flutter apps 2026-07-19 16:55:48 +02:00
generate.py app_icons: auto-sync pubspec.yaml's adaptive_icon_background 2026-07-21 21:38:22 +02:00
glyphs.py app_icons: add home_inventory storage-box glyph; whitelist it on the phone 2026-07-27 07:35:55 +02:00
preview.py Add shared launcher-icon generator for the Flutter apps 2026-07-19 16:55:48 +02:00
README.md app_icons: warm-tint the shared icon family palette 2026-07-21 21:20:41 +02:00
render.py Add shared launcher-icon generator for the Flutter apps 2026-07-19 16:55:48 +02:00
style.py app_icons: warm-tint the shared icon family palette 2026-07-21 21:20:41 +02:00

app_icons — shared launcher icons for the Flutter apps

One icon family across every Flutter/Dart app: a charcoal #211D1B field with a single glyph in the shared unified-design-system accent (#B8862E), drawn at one stroke weight and optically centred so a row of them lines up.

Commands

# what is registered
PYTHONPATH=~/testsAndMisc python3 -m python_pkg.app_icons list

# contact sheet for visual review: full size / circle-masked / 48dp
PYTHONPATH=~/testsAndMisc python3 -m python_pkg.app_icons preview -o /tmp/sheet.png

# write assets into every app repo and rebuild the Android mipmaps
PYTHONPATH=~/testsAndMisc python3 -m python_pkg.app_icons generate --android

# one app, plus the hicolor PNGs for a Linux desktop target
PYTHONPATH=~/testsAndMisc python3 -m python_pkg.app_icons \
    generate --app todo --android --linux-out ~/todo/linux/icons

What gets written

Per app, into <repo>/assets/icon/:

Layer Purpose
icon Charcoal field + glyph. Legacy square launcher icon and Linux icon.
icon_foreground Glyph only, transparent. Adaptive-icon foreground layer.
icon_monochrome Glyph only, white. Android 13+ themed icons.

Both an .svg source and a 1024px .png are written for each, so a build never needs rsvg-convert. flutter_launcher_icons then turns the PNGs into the density buckets and mipmap-anydpi-v26/ic_launcher.xml.

Design constraints that bite

  • Negative space ≥ half the stroke weight. Strokes closer than that merge into a solid blob at launcher size. A fork whose tines sat exactly one stroke width apart rendered as a tulip.
  • Ink must stay inside the 560px safe box. Android masks adaptive icons to roughly the inner 66% of the canvas. generate warns when a glyph overflows.
  • Stroked outlines can read wrong. A stroked three-tine fork reads as a trident; a filled fork-and-knife pair reads as cutlery. Prefer a filled silhouette when the outline is ambiguous.
  • Glyph positioning inside the fragment is irrelevant — render.centre_offset measures the rendered ink and recentres it. Only the extents matter.

Adding an app

See the app-icon skill (~/.claude/skills/app-icon/SKILL.md) for the full procedure. In short: add a glyph to glyphs.py, register the app in apps.py, wire flutter_launcher_icons into its pubspec.yaml, generate, review the contact sheet, then verify on the phone.

Tests

cd ~/testsAndMisc
python3 -m pytest python_pkg/app_icons --cov=python_pkg.app_icons \
    --cov-report=term-missing

External tools (rsvg-convert, magick, dart) are mocked; the suite needs none of them installed.