Procedure
実コンポーネントで「写真やシードデータ入りの特定状態」を撮るのが目的。deep-linkの確認ダイアログと埋め込みバンドルの2大罠を回避する。
- 撮影専用ルートを作る(認証/タブ依存を避ける)。例 expo-router:
src/app/shot.tsxがuseLocalSearchParams().sで deck/card/match 等を出し分け、実コンポーネント+ローカル束ねた画像で描画。冒頭でLogBox.ignoreAllLogs(true)、各分岐に<Stack.Screen options={{headerShown:false}}/>。 - 状態切替は index リダイレクト+コールド起動でやる(deep-linkは確認ダイアログが出る→後述)。
src/app/index.tsxのrouter.replace('/shot?s=deck')を deck→card→match と書き換え、毎回simctl terminate→simctl launchで index の useEffect を再実行させる。 - Debugビルドで metro 直結。
xcodebuild -workspace App.xcworkspace -scheme App -configuration Debug -destination 'id=<UDID>' -derivedDataPath build_dbg CODE_SIGNING_ALLOWED=NO build→simctl install→simctl launch。metroログにiOS Bundled …が出れば JS が反映されている。 - ステータスバーを整える:
xcrun simctl status_bar booted override --time "9:41" --batteryState charged --batteryLevel 100 --cellularBars 4 --dataNetwork wifi --wifiBars 3。撮影後... status_bar booted clear。 - 撮影:
xcrun simctl io booted screenshot /tmp/x.png(アニメ画面は launch 後 8-9s 待つ)。Readで目視確認。 - マーケ枠に合成: 既存の
make_store_shots.py(生1206×2622→紙枠+見出し+デバイス)に raw を差し替えて実行。 - 後片付け: 撮影ルート削除・index復元・束ねた一時画像削除・metro停止(
pkill -f "expo start")・status_bar clear・git status で一時物が残ってないか確認。
Pitfalls
- 埋め込みバンドルの罠: 既存インストール済みアプリ(eas/Releaseビルド)は
App.app/main.jsbundleを埋め込み、metroを叩かない=JS編集が一切反映されない。find <App.app> -name '*.jsbundle'で確認。反映には Debugビルドで作り直しが必須。 - deep-link確認ダイアログ:
simctl openurl booted "scheme://..."は「"App"で開きますか?」モーダルを出し、simctlにはタップ手段が無く詰む。残ったダイアログはアプリ起動もブロックする→simctl shutdown/bootで消すか、そもそも index リダイレクト+コールド起動で openurl を使わない。 - make_store_shots の FAB除去: Expo Go前提の
remove_expo_fabフォールバックが、FABの無いシム撮影では右上を紙色で塗り=レア度バッジ等を消す。シム撮影時は呼び出しをコメントアウト。 - アスペクト崩れ: カードコンポーネントに
flex:1を渡すとaspectRatioを上書きして歪む。width:'100%'を渡し親で中央寄せ。 - ステータスバーの「◄ 別アプリ名」: 別アプリ経由起動の名残。
status_bar overrideで上書きすれば消える。 - Expoのスプラッシュ/権限など prebuild時に焼かれる設定 はDebug再ビルドだけでは反映されない(ネイティブ生成が要る)。
Verification
- metroログに
iOS Bundledが出ている(=埋め込みでなくJS反映済み)。 - 各 raw を Read で目視し、狙った状態・写真・テキスト・バッジが欠けず出ている。
- 合成後の framed を Read で確認(6.9"=1320×2868)。
- 撮影後
git statusに撮影ルート/一時画像が残っていない。