mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-11 02:07:15 +01:00
Every Flutter app still shipped the stock Flutter "beach" launcher icon, and none had an adaptive-icon descriptor at all. Rather than hand-drawing five one-off icons, define the family once and let each app contribute only an accent colour and a glyph. The family: a charcoal #1B1D21 field carrying one glyph in that app's own theme seed colour, at a single stroke weight. Glyphs are optically centred automatically - render.centre_offset rasterises a glyph alone, measures its ink box, and translates (never scales) the fragment, so a row of icons lines up while every icon keeps the exact family stroke weight. safe_box_overflow warns when a glyph exceeds the 560px adaptive-icon safe box; it caught three real overflows that a launcher mask would have clipped. The registry points dufs_client at ~/dufs-cloud/app: ~/dufs_client was a stale, remote-less checkout with an identical package name, since deleted. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
112 lines
3.1 KiB
Python
112 lines
3.1 KiB
Python
"""Registry of the Flutter apps that use the shared icon family.
|
|
|
|
Adding a new app here (plus a glyph in :mod:`python_pkg.app_icons.glyphs`) is
|
|
all that is needed for it to get an on-style icon. The accent is deliberately
|
|
taken from each app's own theme seed so the launcher icon matches the app's
|
|
first screen.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
from typing import Final
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class AppIcon:
|
|
"""One app's icon configuration.
|
|
|
|
Parameters:
|
|
key (str): Short identifier used on the command line.
|
|
repo (Path): Flutter project root, i.e. the directory holding pubspec.yaml.
|
|
accent (str): Hex accent colour, matching the app's theme seed.
|
|
glyph (str): Glyph name from :data:`~python_pkg.app_icons.glyphs.GLYPHS`.
|
|
icon_name (str): Basename for Linux hicolor/desktop installation.
|
|
linux (bool): Whether the app has a Linux desktop target.
|
|
"""
|
|
|
|
key: str
|
|
repo: Path
|
|
accent: str
|
|
glyph: str
|
|
icon_name: str
|
|
linux: bool
|
|
|
|
@property
|
|
def asset_dir(self) -> Path:
|
|
"""Return the directory holding this app's icon source assets."""
|
|
return self.repo / "assets" / "icon"
|
|
|
|
|
|
_HOME = Path.home()
|
|
|
|
APPS: Final[dict[str, AppIcon]] = {
|
|
app.key: app
|
|
for app in (
|
|
AppIcon(
|
|
key="dufs_client",
|
|
# The live app: ~/dufs_client is a stale, remote-less checkout that
|
|
# was superseded when dufs-cloud absorbed it (see testsAndMisc
|
|
# CLAUDE.md). Same package name, so it is easy to icon the wrong one.
|
|
repo=_HOME / "dufs-cloud" / "app",
|
|
accent="#5C6BC0",
|
|
glyph="cloud-down",
|
|
icon_name="dufs-client",
|
|
linux=False,
|
|
),
|
|
AppIcon(
|
|
key="workout_app",
|
|
repo=_HOME / "screen-locker" / "stronglift_replacement" / "workout_app",
|
|
accent="#FF4444",
|
|
glyph="barbell",
|
|
icon_name="workout-app",
|
|
linux=False,
|
|
),
|
|
AppIcon(
|
|
key="wake_alarm_sync",
|
|
repo=_HOME / "wake-alarm" / "phone_app",
|
|
accent="#FFA726",
|
|
glyph="clock",
|
|
icon_name="wake-alarm-sync",
|
|
linux=False,
|
|
),
|
|
AppIcon(
|
|
key="diet_guard_app",
|
|
repo=_HOME / "diet-guard" / "app",
|
|
accent="#26A69A",
|
|
glyph="shield-cutlery",
|
|
icon_name="diet-guard-app",
|
|
linux=True,
|
|
),
|
|
AppIcon(
|
|
key="todo",
|
|
repo=_HOME / "todo",
|
|
accent="#7E57C2",
|
|
glyph="checklist",
|
|
icon_name="todo",
|
|
linux=True,
|
|
),
|
|
)
|
|
}
|
|
|
|
|
|
def get_app(key: str) -> AppIcon:
|
|
"""Look up an app by key.
|
|
|
|
Parameters:
|
|
key (str): App identifier, e.g. ``"todo"``.
|
|
|
|
Returns:
|
|
AppIcon: The matching configuration.
|
|
|
|
Raises:
|
|
KeyError: If no app with that key is registered.
|
|
"""
|
|
try:
|
|
return APPS[key]
|
|
except KeyError:
|
|
available = ", ".join(sorted(APPS))
|
|
msg = f"unknown app {key!r}; available: {available}"
|
|
raise KeyError(msg) from None
|