Skip to content

feat(ios): Player 런처 — Coding/Player 단일 앱 진입점 - #63

Merged
redsunjin merged 12 commits into
mainfrom
worktree-player-ios-launcher
Aug 14, 2026
Merged

feat(ios): Player 런처 — Coding/Player 단일 앱 진입점#63
redsunjin merged 12 commits into
mainfrom
worktree-player-ios-launcher

Conversation

@redsunjin

Copy link
Copy Markdown
Owner

Summary

  • iOS에서 Coding 앱과 Player(공개 URL 리플레이)를 하나의 설치로 제공하는 런처 화면 추가
  • player/와 루트 앱(src/)은 빌드 산출물 레벨에서만 결합 (소스 경계 유지)
  • 각 서브앱 헤더에 네이티브 셸 전용 "⇄ 전환" 버튼 추가

구현

  • ios/launcher/ — 순수 로직(launcher.js) + 정적 픽커 페이지(index.html), 마지막 선택 기억
  • scripts/build-ios-shell.mjs — coding/player 빌드 + 런처를 dist-ios-shell/로 합침, capacitor.config.jsonwebDir 갱신
  • player/src/lib/nativeShell.js — Player 전용 네이티브 셸 감지 유틸(신규 의존성 없음)
  • Coding/Player 양쪽 헤더에 전환 버튼

검증

  • 실기기(아이패드) 수동 검증 완료 — 런처 → Coding/Player 진입 → 전환 버튼 왕복 모두 정상 동작 확인
  • 8개 태스크 전부 subagent 구현 + 태스크별 리뷰 승인
  • 최종 전체 브랜치 리뷰(opus)에서 CI 브레이킹 이슈 2건 발견 → 수정 → 재리뷰 승인("Ready to merge: Yes")
    • tests/build-ios-shell.test.mjs가 기본 npm test/qa 글롭에 걸려 있어 player/ 의존성 없는 CI qa job/GH Pages 배포를 깨뜨릴 뻔한 문제를 tests/build-ios-shell.itest.mjs + 전용 npm run test:ios-shell로 분리
    • 그 외 런처 storage 예외 방어, 접근성 이름(aria-hidden) 처리, 문서(USER_GUIDE/스펙) 최신화 등 다수 반영
  • 잔여 Minor 5건(코스메틱/커버리지 배치 관련, 병합 비차단)은 PR 코멘트로 별도 기록 예정

Test plan

  • npm test (root, 21 files / 127 tests)
  • cd player && npm run qa (8 tests + UI + server)
  • npm run test:ios-shell (신규, iOS 셸 빌드 통합 테스트 — CI 기본 글롭에서는 제외됨, 로컬/수동 실행용)
  • npm run build (GH Pages 프로덕션 빌드 영향 없음 확인)
  • 실기기(아이패드) 수동 검증

🤖 Generated with Claude Code

selimDGAX and others added 12 commits August 14, 2026 18:18
2026-08-13 스펙(player-ios-launcher-design)의 8개 태스크 구현 계획.
런처 순수 로직 → 정적 페이지 → 빌드 스크립트 → 각 서브앱 전환 버튼 →
실기기 검증 순서.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
isNativeShell()이 true일 때만 player-hero__controls에 "Coding으로 전환"
버튼을 표시한다. 화살표 글리프는 aria-hidden으로 감춰 접근성 이름이
정확히 "Coding으로 전환"과 일치하도록 했다 (버튼 텍스트를 그대로
버튼명으로 쓰는 브리프 의도 유지).
isNativeShell()이 true일 때만 우측 컨트롤 그룹 맨 앞에 "Player로 전환"
버튼을 표시한다. Task 6(Player 헤더)과 동일하게 화살표 글리프를
aria-hidden으로 감춰 접근성 이름이 정확히 "Player로 전환"과 일치하도록
했다.
tests/build-ios-shell.test.mjs runs a real Vite build of player/ and
requires player/node_modules, which the default `npm test`/`npm run
qa` chain (and thus qa-gate.yml's qa job and deploy.yml's QA gate
step) never installs. Rename it to .itest.mjs so it's excluded from
the tests/*.test.mjs glob, add a dedicated `test:ios-shell` script to
run it manually/locally, and add a timeout to its execFileSync call so
a wedged build fails instead of hanging past the test's own timeout.

Also add a regression assertion that the Coding/Player header
"전환" buttons' target path (../index.html) still matches where the
launcher lands in the built shell.
…a padding

Reorder ios/launcher/index.html's inline script so both button click
listeners attach unconditionally before touching localStorage. Wrap
the getLastApp/badge-reading logic and the per-click setLastApp call
in their own try/catch blocks so a storage read/write failure (e.g.
WKWebView storage restricted or full) only skips the "마지막 사용"
badge instead of leaving the picker screen with dead buttons.

Also give the launcher's body padding safe-area awareness
(env(safe-area-inset-*)) to match the rest of the Capacitor shell,
so content doesn't sit under the device's rounded corners/home
indicator.
The 네이티브 셸에서만 전환 버튼이 보인다 test set window.Capacitor and
deleted it as the last line of the test body. If an earlier assertion
threw, cleanup never ran and window.Capacitor leaked into the next
test. Move the cleanup into the file's existing top-level afterEach,
matching the pattern already used in
src/App.native-shell-switch.ui.test.jsx.
USER_GUIDE.md's iOS section still described the pre-launcher flow
(server-address screen auto-opening on first launch). Add a launcher
subsection explaining the Coding/Player picker appears first and the
"⇄ 전환" header button returns to it, and update the manual
verification checklist to match.

The design spec's §2/§3 still described an abandoned approach
(copying into ios/App/App/public/, launcher source at public/launcher/,
CAPACITOR_BUILD=1 vite build). Rewrite them to describe what was
actually built: dist-ios-shell/ as the Vite output referenced by
capacitor.config.json's webDir, and launcher source at ios/launcher/
(kept out of public/ specifically so it doesn't leak into Coding's own
bundle). Also correct §6, which implied the iOS Player build exposes
only the public-URL mode — in fact it's the same web build as
browser/extension, with Local Repo / Connected Account tabs still
visible but non-functional on iOS. Documentation only, no code change.
@redsunjin

Copy link
Copy Markdown
Owner Author

최종 리뷰에서 남은 Minor 항목 (병합 비차단, 참고용)

  1. test:ios-shell의 CI 제외로 인해 새로 추가한 전환 버튼 경로 검증(../index.html 문자열 매칭)도 CI에서 안 돌게 됨 — 저비용 assertion 2개(webDir 값, 경로 매칭)만 tests/launcher.test.mjs(기본 글롭 포함)로 옮기면 해결.
  2. 스펙 §7과 plan 문서에 tests/build-ios-shell.test.mjs(구 파일명) 참조가 남아있음 — cosmetic.
  3. 스펙 §6의 "Connected Account 탭은 사용불가 안내로 막다른 길" 표현이 실제와 다름 — 실제로는 provider/PAT 입력 폼이 그대로 뜨고 GitHub/GitLab API를 직접 호출 시도함 (OAuth만 deferred). 문구 정정 필요.
  4. ios/launcher/index.htmlpaths 매핑에 존재하지 않는 data-app 값에 대한 폴백이 없음 — 현재 버튼 2개뿐이라 실질 위험은 낮음.
  5. vite.config.jsCAPACITOR_BUILD 분기가 이제 죽은 코드 — ios:build가 더 이상 이 env var를 설정하지 않음. 주석과 함께 정리 필요.

원한다면 후속 커밋으로 정리하겠습니다.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2e6acef465

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


await build({
configFile: path.join(rootDir, 'player/vite.config.js'),
root: path.join(rootDir, 'player'),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Disable the localhost bridge in the native Player

When this Player build runs under Capacitor, its hostname is localhost; player/src/main.jsx therefore installs the HTTP local-repo bridge because shouldInstallHttpLocalRepoBridge() accepts that hostname. This makes localBridgeAvailable true, so selecting Local Repo attempts a POST to /__maestro_player/local-replay inside the static Capacitor bundle instead of showing the intended “bridge unavailable” state, and the load fails. Suppress bridge installation for native shells or require a successful health check before treating it as available.

Useful? React with 👍 / 👎.

@redsunjin
redsunjin merged commit 6e001cd into main Aug 14, 2026
4 checks passed
@redsunjin
redsunjin deleted the worktree-player-ios-launcher branch August 14, 2026 11:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants