65596eee2b
Adds Web App Manifest, a minimal Service Worker, and Apple/Android meta tags so the app can be added to a phone home screen and opens full-screen in standalone mode (no browser chrome). - static/manifest.json: name, short_name, display=standalone, icons - static/sw.js: minimal SW served at /sw.js (root scope) via new Flask route - static/icon-192.png, icon-512.png: generated by sbin/gen_icons.py (stdlib only) - base.html: manifest link, theme-color, apple-mobile-web-app-* tags, SW registration
32 lines
1.1 KiB
Python
32 lines
1.1 KiB
Python
"""Generate solid-color PNG icons for PWA manifest using stdlib only (no Pillow)."""
|
|
import zlib, struct, os
|
|
|
|
def make_png(size, rgb=(0x25, 0x63, 0xEB)):
|
|
"""Create a minimal valid RGB PNG of the given size filled with one color."""
|
|
w = h = size
|
|
raw = b''
|
|
for _ in range(h):
|
|
raw += b'\x00' + bytes(rgb) * w # filter byte 0 (None) + RGB pixels
|
|
|
|
compressed = zlib.compress(raw, 9)
|
|
|
|
def chunk(name, data):
|
|
c = name + data
|
|
return struct.pack('>I', len(data)) + c + struct.pack('>I', zlib.crc32(c) & 0xffffffff)
|
|
|
|
sig = b'\x89PNG\r\n\x1a\n'
|
|
ihdr = chunk(b'IHDR', struct.pack('>IIBBBBB', w, h, 8, 2, 0, 0, 0))
|
|
idat = chunk(b'IDAT', compressed)
|
|
iend = chunk(b'IEND', b'')
|
|
return sig + ihdr + idat + iend
|
|
|
|
|
|
if __name__ == '__main__':
|
|
out_dir = os.path.join(os.path.dirname(__file__), '..', 'static')
|
|
os.makedirs(out_dir, exist_ok=True)
|
|
for size in [192, 512]:
|
|
path = os.path.join(out_dir, f'icon-{size}.png')
|
|
with open(path, 'wb') as f:
|
|
f.write(make_png(size))
|
|
print(f'Wrote {path}')
|