| 1 | #!/usr/bin/env python3 |
| 2 | """Copy approved artwork to an explicit application checkout; --check detects drift.""" |
| 3 | import argparse |
| 4 | from pathlib import Path |
| 5 | |
| 6 | APPS = ["home", "docs", "sheets", "slides", "calendar", "calls", "memoria", "fichas"] |
| 7 | # Apps with a native client, and where each keeps its icons. iOS applies its |
| 8 | # own mask to a full-bleed square; the Mac takes the shaped icon on Apple's |
| 9 | # grid, as PNG (Calls' AppKit resources) or as the Finder's .icns. |
| 10 | NATIVE = { |
| 11 | "calls": { |
| 12 | "native/ios/Assets.xcassets/AppIcon.appiconset/AppIcon.png": "ios-1024.png", |
| 13 | "native/apple/Sources/CallsMac/Resources/AppIcon.png": "macos-1024.png", |
| 14 | "native/apple/Sources/CallsMac/Resources/MacIcon.png": "macos-1024.png", |
| 15 | }, |
| 16 | **{app: { |
| 17 | "native/ios/Assets.xcassets/AppIcon.appiconset/AppIcon.png": "ios-1024.png", |
| 18 | "native/macos/AppIcon.icns": "AppIcon.icns", |
| 19 | } for app in ["docs", "sheets", "calendar", "memoria"]}, |
| 20 | } |
| 21 | |
| 22 | parser = argparse.ArgumentParser(description=__doc__) |
| 23 | parser.add_argument("app", choices=APPS) |
| 24 | parser.add_argument("checkout", type=Path) |
| 25 | parser.add_argument("--check", action="store_true") |
| 26 | args = parser.parse_args() |
| 27 | source = Path(__file__).resolve().parent |
| 28 | app = args.app |
| 29 | destination = args.checkout / "internal" / app |
| 30 | if not destination.is_dir(): |
| 31 | parser.error("checkout does not contain internal/" + app) |
| 32 | destination /= "brand" if app == "docs" else "static/brand" |
| 33 | product = "oficina" if app == "home" else app |
| 34 | files = { |
| 35 | "icon.svg": source / "svg" / (product + ".svg"), |
| 36 | "icon-32.png": source / "png" / (product + "-32.png"), |
| 37 | "apple-touch-icon.png": source / "png" / (product + "-180.png"), |
| 38 | "brand.css": source / "brand.css", |
| 39 | "LICENSE.lucide": source / "LICENSE.lucide", |
| 40 | } |
| 41 | if app == "home": |
| 42 | # The launcher shows every app, including those still to come. |
| 43 | for name in ["docs", "sheets", "slides", "calendar", "calls", "memoria", "fichas", "mail", "files"]: |
| 44 | files[name + ".svg"] = source / "svg" / (name + ".svg") |
| 45 | copies = {destination / name: path for name, path in files.items()} |
| 46 | for target, native in NATIVE.get(app, {}).items(): |
| 47 | copies[args.checkout / target] = source / "native" / app / native |
| 48 | for target, original in copies.items(): |
| 49 | data = original.read_bytes() |
| 50 | if args.check: |
| 51 | if not target.is_file() or target.read_bytes() != data: |
| 52 | raise SystemExit("Brand asset missing or stale: " + str(target)) |
| 53 | else: |
| 54 | target.parent.mkdir(parents=True, exist_ok=True) |
| 55 | target.write_bytes(data) |
| 56 | print(("Checked " if args.check else "Copied ") + str(len(copies)) + " assets for " + app) |
| 57 | |