CrownyAI 런처 — 클로드 디자인 목업 → ObjC 네이티브 drawRect 이식
개요
design_handoff_크라우니앱/런처-{네이티브,웹서비스,오프라인}-{라이트,다크}.html 6개 목업(800×600, 절대좌표)을
crowny-ai-engine.m의
CrownyAppView 런처 drawRect/mouseDown에 그대로 이식. 색·좌표·문구는 목업에서
복사(재창작 금지), 카드 데이터는
src/앱목록.psv(appListEntries) 실데이터.
무엇을 했는지
src/런처레이아웃.한선(SSOT, 신규) — 목업 800×600 절대좌표를 순수 함수로 이식(헤더/탭바/카드
9칸 그리드/페이지네이션/오프라인 카드). 나눗셈 자연반올림 함정 우회를 위해
_올림분할9(뺄셈 루프)
사용. 자체시험 29/29 PASS(hanseonc_high 컴파일 + crownyc run).
native/crowny-ai-engine.m(런처 구간만):
-
cavBasisToView(bounds, x0,y0,w0,h0) — 800×600 기준 좌표 → 뷰 bounds 매핑(비균등 스트레치
sx=뷰W/800, sy=뷰H/600,
drawVectorDisplayList와 동일 스케일 정책). 스케일 적용 유일 지점.
-
caiLogoImage extern 재사용(crowny-ai-chrome.m 정본 왕관 벡터, 재창작 안 함) — 로고 자리에 배치.
-
drawRect 런처 분기 전면 재작성: 목업 그대로(헤더+새로고침, 탭바+언더라인+구분선, 카드
9칸/쪽(3×3)+학습배지, 페이지네이션, 오프라인 카드).
-
launcherCardRects: — 9칸 고정 그리드로 재정의(cavBasisToView 기반).
-
mouseDown 런처 분기 — 로고(홈)/새로고침/탭전환/카드열기/이전·다음 페이지/오프라인 재시도 히트.
- 인스턴스 상태
런처탭(0=네이티브,1=웹)·
런처페이지네이티브·
런처페이지웹 추가(탭당 독립 페이지).
-
gLauncherWebOffline/
gLauncherLastSuccessAt/
launcherFetchManifestNow — 학습배지 manifest
fetch 성패를 오프라인 신호로 재사용(기존 dispatch_once 1회 캐시를 재시도 가능한 구조로 리팩터).
- 미사용 경고 방지:
launcherAccentForApp(신규 목업이 액센트 점을 안 씀)
__attribute__((unused)).
검증
런처레이아웃.한선: hanseonc_high 컴파일 exit0 → crownyc run "런처레이아웃 검증: 29/29" "[결과] 티 — PASS".
make ai: exit0, 신규 경고 0(사전존재 4건 — main.m getter 3 + butler unused-function 1, 회귀 아님).
- 파리티 대입표(한선 SSOT 출력값 ↔ ObjC cavBasisToView 인자, 발췌):
| 함수(한선) | 반환 | ObjC 호출 | 일치 |
|---|---|---|---|
| 카드_rect(0) | [24,136,240,108] | cavBasisToView(B,24,136,240,108) | ✓ |
| 카드_rect(4) | [280,258,240,108] | row=1,col=1→cx0=280,cy0=258 | ✓ |
| 카드_rect(8) | [536,380,240,108] | row=2,col=2→cx0=536,cy0=380 | ✓ |
| 로고rect() | [24,20,28,28] | cavBasisToView(B,24,20,28,28) | ✓ |
| 탭언더라인_x(웹) | 152 | underlineX=152(webTab) | ✓ |
| 페이지네이션_이전버튼() | [236,524,104,40] | prevR=cavBasisToView(B,236,524,104,40) | ✓ |
| 오프라인재시도버튼() | [332,336,136,44] | retryR=cavBasisToView(B,332,336,136,44) | ✓ |
| 페이지수(10) | 2 | (10+8)/9=2(C truncate=ceil for양수) | ✓ |
| 페이지수(17) | 2 | (17+8)/9=2 | ✓ |
| 페이지항목범위(1,10) | [9,1] | start=9,count=min(9,1)=1 | ✓ |
| 이전활성(0)/다음활성(0,2) | -1/1 | prevActive=NO/nextActive=YES | ✓ |
- 라이브 앱·9801 서버 무접촉(지시 준수). GUI 육안은 통합 세션 담당(범위 외).
관련 파일
/Users/ef/CrownyBrowser/src/런처레이아웃.한선 (신규 SSOT, 29/29 자체시험)
/Users/ef/CrownyBrowser/native/crowny-ai-engine.m (런처 구간만 수정, 백업=.bak-런처이식)
- 원본 목업:
/Users/ef/Downloads/design_handoff_크라우니앱/런처-{네이티브,웹서비스,오프라인}-{라이트,다크}.html
- 이식노트:
/Users/ef/.claude/design-port/크라우니앱벡터/이식노트.md (이번 작업 개선 아이디어 없음 — append 안 함)
크라우니코드 학습
~/.claude/scripts/crownycode-learn.sh lookup HIT 0건 / search·lookup MISS 2건(신규 패턴) / learn 추가 1건
(intent=
런처_디자인이식_레이아웃SSOT).
잔여 이슈
- GUI 실측(앱 재시작 후 crowny://app/런처 육안 확인, 라이트/다크·네이티브/웹서비스 탭·페이지네이션·
오프라인 상태)은 통합 세션 담당(이번 작업 지시 범위 밖 — "라이브 앱·9801 서버 무접촉").
install-ai-app.sh 미실행(지시에 따라 설치/앱 재시작은 통합 세션 담당) — 반영은 다음 설치+재시작부터.
- 오프라인 판정은 학습배지 manifest fetch(game.crowny.org) 성패에 결속 — 실제 웹서비스 카드 목록 자체는
로컬
src/앱목록.psv 기반이라 항상 로드됨(오프라인 카드가 뜨는 동안에도 카드 데이터 자체는 유실 아님,
기존 설계 의도인 "배지 소스 단절 신호"를 그대로 재해석).