Files
shinalok 4a7ef5cc29 improve PWA feel on iOS: offline fallback, overscroll, tap feedback, dark status bar, apple touch icon
Add offline.html served by the service worker when a never-visited route
is requested without network. Disable rubber-band overscroll bounce and
gray tap highlights so standalone mode feels less like a webview. Split
theme-color by prefers-color-scheme so the iOS status bar matches dark
mode, and add a proper 180x180 apple-touch-icon instead of downscaling
the 192px icon.
2026-07-20 15:34:19 +09:00

53 lines
1.8 KiB
Python

"""PWA 아이콘(icon-192, icon-512, icon-maskable-512)을 생성한다.
Pillow가 필요하다 (런타임 의존성 아님, 아이콘을 새로 만들 때만 `pip install pillow` 후 1회 실행).
사용법: python scripts/generate_icons.py
"""
from pathlib import Path
from PIL import Image, ImageDraw
ACCENT = (217, 119, 87, 255) # --color-accent
WHITE = (255, 255, 255, 255)
OUT_DIR = Path(__file__).resolve().parent.parent / "app" / "static" / "icons"
# 24x24 viewBox 기준 체크마크 좌표 (elbow 3점)
CHECK_POINTS = [(4.8, 12.0), (9.0, 16.2), (19.0, 6.4)]
def draw_icon(size: int) -> Image.Image:
img = Image.new("RGBA", (size, size), ACCENT)
draw = ImageDraw.Draw(img)
check_span = size * 0.58 # 24유닛이 차지할 실제 픽셀 크기
scale = check_span / 24
offset = (size - check_span) / 2
points = [(offset + x * scale, offset + y * scale) for x, y in CHECK_POINTS]
stroke_width = max(2, round(size * 0.066))
draw.line(points, fill=WHITE, width=stroke_width, joint="curve")
# 선 끝을 둥글게 마무리
r = stroke_width / 2
for x, y in (points[0], points[-1]):
draw.ellipse([x - r, y - r, x + r, y + r], fill=WHITE)
return img
def main() -> None:
OUT_DIR.mkdir(parents=True, exist_ok=True)
draw_icon(192).save(OUT_DIR / "icon-192.png")
draw_icon(512).save(OUT_DIR / "icon-512.png")
# 배경이 전체를 채우고 체크마크가 중앙 58%에만 있어 마스커블 세이프존(중앙 80%)을 만족한다.
draw_icon(512).save(OUT_DIR / "icon-maskable-512.png")
# iOS apple-touch-icon 권장 사이즈(180x180) — 192px를 그대로 쓰면 iOS가 다운스케일한다.
draw_icon(180).save(OUT_DIR / "icon-apple-180.png")
print(f"generated icons in {OUT_DIR}")
if __name__ == "__main__":
main()