@@ -28,12 +28,15 @@ import kotlinx.coroutines.flow.collectLatest
2828 * HandOffScreen — CANNOT be skipped. Full opaque overlay. 3-second mandatory countdown.
2929 * Back gesture completely disabled. Screen orientation locked. Section 8.4, Section 12.
3030 *
31- * FIX: The `phase` field on [HandOffRoute] now distinguishes two use-cases:
31+ * FIX (turn bug): In the BATTLE phase, we must write to BattleScreen's savedStateHandle
32+ * BEFORE calling popBackStack(). popBackStack() is async — after calling it,
33+ * currentBackStackEntry is still HandOffScreen, not BattleScreen.
34+ * The correct target is navController.previousBackStackEntry (= BattleScreen while
35+ * HandOff is still on the stack), then pop.
36+ *
37+ * FIX (setup): The `phase` field on [HandOffRoute] distinguishes two use-cases:
3238 * - "SETUP" → initial placement handoff between P1 and P2 (or P2 to Battle start)
3339 * - "BATTLE" → mid-game turn handoff during Pass & Play battles
34- *
35- * Without this distinction, P2's post-placement handoff incorrectly tried to
36- * popBackStack() to BattleScreen which had never been pushed onto the stack.
3740 */
3841@Composable
3942fun HandOffScreen (
@@ -78,9 +81,8 @@ fun HandOffScreen(
7881 }
7982
8083 phase == " SETUP" && mode == " LOCAL" && ! route.isP1HandOff -> {
81- // FIX: After P2 places fleet → navigate forward to BattleScreen.
82- // Old code did popBackStack() here which went back to P2's placement
83- // screen because BattleScreen had never been pushed onto the stack.
84+ // After P2 places fleet → navigate forward to BattleScreen.
85+ // Do NOT popBackStack() here — BattleScreen was never pushed.
8486 navController.navigate(
8587 com.battleship.fleetcommand.navigation.BattleRoute (gameId = gameId)
8688 ) {
@@ -103,12 +105,14 @@ fun HandOffScreen(
103105
104106 // ── BATTLE phase: mid-game turn handoffs (Pass & Play only) ──
105107 phase == " BATTLE" -> {
106- // Pop back to BattleScreen (it IS in the back stack during battle)
107- // and signal whose turn begins via saved state handle.
108- navController.popBackStack()
109- navController.currentBackStackEntry
108+ // FIX: Write to previousBackStackEntry (= BattleScreen) BEFORE
109+ // popping. After popBackStack() the currentBackStackEntry pointer
110+ // is still HandOff until the coroutine yields, so writing to
111+ // currentBackStackEntry after the pop silently drops the signal.
112+ navController.previousBackStackEntry
110113 ?.savedStateHandle
111114 ?.set(" passAndPlayResumeP1" , route.isP1HandOff)
115+ navController.popBackStack()
112116 }
113117
114118 else -> {
0 commit comments