Skip to content

Dismiss keyboard when leaving the edit-player screen#657

Open
wyne wants to merge 2 commits into
mainfrom
claude/xenodochial-thompson-e63792
Open

Dismiss keyboard when leaving the edit-player screen#657
wyne wants to merge 2 commits into
mainfrom
claude/xenodochial-thompson-e63792

Conversation

@wyne

@wyne wyne commented Jun 14, 2026

Copy link
Copy Markdown
Owner

Problem

Repro: create a new game → edit a player → tap the clear (✕) button on the name field → tap Back → start the game and exit → tap the FAB to start another new game. The on-screen keyboard pops up alongside the player-count menu.

Root cause

The clear button calls inputRef.current?.focus() to keep the field active after clearing the name — a programmatic focus that makes the TextInput the keyboard's first responder. When the screen unmounts on Back, nothing resigns that first responder, so iOS keeps a dangling reference to the now-destroyed text field. Later, when the native MenuView (the player-count menu from the FAB) presents, UIKit re-evaluates first responders and restores the keyboard.

That's why "hit the clear button" is the essential repro step — it's the only path that focuses the input programmatically without a real tap that iOS would otherwise clean up on back-navigation.

Fix

Dismiss the keyboard on beforeRemove in EditPlayerScreen, so the first responder resigns cleanly while the input is still mounted. This mirrors the existing beforeRemove pattern already used in EditGame.tsx.

Tests

  • Added a regression test that captures the beforeRemove listener and asserts it calls Keyboard.dismiss().
  • npx jest src/screens/EditPlayerScreen.test.tsx → 31 passed.
  • npx tsc --noEmit → clean.

🤖 Generated with Claude Code

The clear (x) button in the player editor focuses the input
programmatically. If the screen is removed while that input is still
the first responder, iOS keeps a dangling reference and re-shows the
keyboard the next time a native view presents -- e.g. tapping the FAB
to open the new-game player-count menu would pop up the keyboard too.

Dismiss the keyboard on `beforeRemove` so the first responder resigns
cleanly while the input is still mounted, matching the existing pattern
in EditGame.tsx.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Coverage after merging claude/xenodochial-thompson-e63792 into main will be

60.96%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
redux
   GamesSlice.ts54.09%27.50%56.52%64.58%101, 109, 131–133, 148, 167, 178, 185, 187, 190–192, 242, 256, 269, 278–279, 279, 279, 285, 285, 285–286, 288, 29, 290–291, 294, 294, 294, 294, 294–295, 298–299, 301, 303, 303, 303, 303, 303–304, 306, 306, 306, 308–309, 312, 312, 312, 314, 52, 63, 80, 85–86, 86, 86, 98–99, 99, 99
   PlayersSlice.ts89.90%100%87.50%85.11%103, 105, 33, 50–51, 68–69
   SettingsSlice.ts46.81%25%42.11%54.17%101, 104, 54, 57, 63, 66, 72, 75, 84, 84, 84, 90, 93, 98
   backup.ts0%0%0%0%11, 27–29, 31, 45–49, 51, 51, 51–52, 57, 60, 64–66, 71, 71, 71, 73–75, 78–79, 81–82, 85, 85, 85, 85, 85–87, 90–93, 95, 97
   hooks.ts100%100%100%100%
   selectors.ts100%100%100%100%
   store.ts0%0%0%0%10, 12, 12, 12–13, 13, 13–15, 18, 21–23, 23, 23, 23, 23–24, 28, 54, 61, 68, 75, 93
   testStore.ts0%100%0%0%11–15, 20–23, 25, 42–44, 5
src
   Analytics.ts100%100%100%100%
   ColorPalette.ts100%100%100%100%
   Logger.ts91.23%87.50%81.82%94.74%14–15, 22
   Navigation.tsx75.68%72.73%62.50%83.33%45, 49, 70, 73, 79–80
   constants.ts100%100%100%100%
   theme.ts93.75%85.71%100%100%79
src/components
   EditGame.tsx81.40%70%71.43%88.46%25, 39, 64, 64, 64–65
   FloatingActionButton.tsx68.97%100%50%73.68%38, 41–42, 55–56
   GameListItem.tsx66.10%47.83%100%73.33%103, 20, 23–24, 24, 24–26, 26, 26–28, 28, 28–30, 30, 30–31, 73
   GameListItemPlayerName.tsx100%100%100%100%
   MenuOpenContext.tsx87.50%100%66.67%100%
   PlayerListItem.tsx0%0%0%0%123, 123, 134, 24, 32–34, 34, 34–38, 40, 40, 40, 40, 40–41, 41, 41–42, 42, 42, 44–45, 56, 63–64, 66, 72–73, 76, 79, 82–83, 90, 93, 93, 96, 96, 96–97, 99
   ScoreLogTable.tsx92.59%82.35%100%96.15%50, 52, 54, 54
   SplashOverlay.tsx0%0%0%0%22–24, 24, 24, 26–28, 30, 32–33, 35, 37, 40, 40, 40, 43, 49, 53, 58, 74
src/components/AppInfo
   RotatingIcon.tsx0%0%0%0%18–19, 21–24, 26, 28–30, 37–38, 40, 40, 40–41, 44, 44, 44–48, 51, 53–54, 59
   SeedData.ts0%100%0%0%17, 47, 49–50, 52, 54–56, 58–60, 62, 68, 71, 82–85
src/components/BigButtons
   BigButton.tsx0%0%0%0%18, 18–20, 22–23, 23, 25, 25–26, 26, 48
src/components/Boards
   ListBoard.tsx86.81%72.73%84.21%98.57%123, 180, 206–207, 220, 223, 262, 29, 33, 59–61, 84, 84, 88, 92
   PlayerTile.tsx0%0%0%0%29, 39, 39, 39, 39, 39–40, 40, 40, 40, 40, 42–46, 46, 46–47, 47, 47, 47, 47–48, 48, 48–50, 50, 50, 52–54, 54, 54, 56, 59, 59, 63–64, 67–68, 70, 80, 80, 97
   TileBoard.tsx96.39%90.32%100%100%18, 78, 92
src/components/Buttons
   AppSettingsButton.tsx100%100%100%100%
   BackButton.tsx0%100%0%0%16–18, 20–21
   GameOptionsButton.tsx53.40%45%75%54.90%100, 118, 118, 118, 118, 118, 118, 118, 120–122, 124–126, 128–130, 132–135, 137–139, 141–143, 150, 156–157, 168, 170, 170, 176, 176, 176, 176, 38, 44, 46, 56, 63, 71, 92, 96
   HeaderButton.tsx100%100%100%100%
src/components/ColorPalettes
   ColorSelector.tsx100%100%100%100%
   PalettePreview.tsx0%0%0%0%10–12, 14, 19, 19, 25
   PaletteSelector.tsx0%0%0%0%13, 15–18, 20, 22, 22, 22, 24–25, 31, 37, 40, 45, 56
src/components/Headers
   RoundHeaderTitle.tsx0%0%0%0%12–14, 16, 18, 18, 18, 20–21, 21, 21–22, 22, 22, 24–25, 27–28, 28, 28, 28, 28, 30–31, 31, 34–35, 44–45, 45, 45, 47–49, 57, 59, 62, 62, 62, 62, 64, 64, 70, 70, 70, 70, 73, 73, 73, 73, 73, 75, 75,

The beforeRemove handler alone fired too late during the back
transition to reliably resign the first responder. Add two more
direct dismissals:

- FloatingActionButton: dismiss the keyboard in MenuView.onOpenMenu,
  so a dangling first responder can't be restored alongside the
  player-count menu (the visible symptom).
- EditPlayerScreen: dismiss synchronously in the Back button before
  goBack(), while the input is still mounted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Coverage after merging claude/xenodochial-thompson-e63792 into main will be

60.90%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
redux
   GamesSlice.ts54.09%27.50%56.52%64.58%101, 109, 131–133, 148, 167, 178, 185, 187, 190–192, 242, 256, 269, 278–279, 279, 279, 285, 285, 285–286, 288, 29, 290–291, 294, 294, 294, 294, 294–295, 298–299, 301, 303, 303, 303, 303, 303–304, 306, 306, 306, 308–309, 312, 312, 312, 314, 52, 63, 80, 85–86, 86, 86, 98–99, 99, 99
   PlayersSlice.ts89.90%100%87.50%85.11%103, 105, 33, 50–51, 68–69
   SettingsSlice.ts46.81%25%42.11%54.17%101, 104, 54, 57, 63, 66, 72, 75, 84, 84, 84, 90, 93, 98
   backup.ts0%0%0%0%11, 27–29, 31, 45–49, 51, 51, 51–52, 57, 60, 64–66, 71, 71, 71, 73–75, 78–79, 81–82, 85, 85, 85, 85, 85–87, 90–93, 95, 97
   hooks.ts100%100%100%100%
   selectors.ts100%100%100%100%
   store.ts0%0%0%0%10, 12, 12, 12–13, 13, 13–15, 18, 21–23, 23, 23, 23, 23–24, 28, 54, 61, 68, 75, 93
   testStore.ts0%100%0%0%11–15, 20–23, 25, 42–44, 5
src
   Analytics.ts100%100%100%100%
   ColorPalette.ts100%100%100%100%
   Logger.ts91.23%87.50%81.82%94.74%14–15, 22
   Navigation.tsx75.68%72.73%62.50%83.33%45, 49, 70, 73, 79–80
   constants.ts100%100%100%100%
   theme.ts93.75%85.71%100%100%79
src/components
   EditGame.tsx81.40%70%71.43%88.46%25, 39, 64, 64, 64–65
   FloatingActionButton.tsx64.52%100%44.44%70%38, 41–42, 58, 60–61
   GameListItem.tsx66.10%47.83%100%73.33%103, 20, 23–24, 24, 24–26, 26, 26–28, 28, 28–30, 30, 30–31, 73
   GameListItemPlayerName.tsx100%100%100%100%
   MenuOpenContext.tsx87.50%100%66.67%100%
   PlayerListItem.tsx0%0%0%0%123, 123, 134, 24, 32–34, 34, 34–38, 40, 40, 40, 40, 40–41, 41, 41–42, 42, 42, 44–45, 56, 63–64, 66, 72–73, 76, 79, 82–83, 90, 93, 93, 96, 96, 96–97, 99
   ScoreLogTable.tsx92.59%82.35%100%96.15%50, 52, 54, 54
   SplashOverlay.tsx0%0%0%0%22–24, 24, 24, 26–28, 30, 32–33, 35, 37, 40, 40, 40, 43, 49, 53, 58, 74
src/components/AppInfo
   RotatingIcon.tsx0%0%0%0%18–19, 21–24, 26, 28–30, 37–38, 40, 40, 40–41, 44, 44, 44–48, 51, 53–54, 59
   SeedData.ts0%100%0%0%17, 47, 49–50, 52, 54–56, 58–60, 62, 68, 71, 82–85
src/components/BigButtons
   BigButton.tsx0%0%0%0%18, 18–20, 22–23, 23, 25, 25–26, 26, 48
src/components/Boards
   ListBoard.tsx86.81%72.73%84.21%98.57%123, 180, 206–207, 220, 223, 262, 29, 33, 59–61, 84, 84, 88, 92
   PlayerTile.tsx0%0%0%0%29, 39, 39, 39, 39, 39–40, 40, 40, 40, 40, 42–46, 46, 46–47, 47, 47, 47, 47–48, 48, 48–50, 50, 50, 52–54, 54, 54, 56, 59, 59, 63–64, 67–68, 70, 80, 80, 97
   TileBoard.tsx96.39%90.32%100%100%18, 78, 92
src/components/Buttons
   AppSettingsButton.tsx100%100%100%100%
   BackButton.tsx0%100%0%0%16–18, 20–21
   GameOptionsButton.tsx53.40%45%75%54.90%100, 118, 118, 118, 118, 118, 118, 118, 120–122, 124–126, 128–130, 132–135, 137–139, 141–143, 150, 156–157, 168, 170, 170, 176, 176, 176, 176, 38, 44, 46, 56, 63, 71, 92, 96
   HeaderButton.tsx100%100%100%100%
src/components/ColorPalettes
   ColorSelector.tsx100%100%100%100%
   PalettePreview.tsx0%0%0%0%10–12, 14, 19, 19, 25
   PaletteSelector.tsx0%0%0%0%13, 15–18, 20, 22, 22, 22, 24–25, 31, 37, 40, 45, 56
src/components/Headers
   RoundHeaderTitle.tsx0%0%0%0%12–14, 16, 18, 18, 18, 20–21, 21, 21–22, 22, 22, 24–25, 27–28, 28, 28, 28, 28, 30–31, 31, 34–35, 44–45, 45, 45, 47–49, 57, 59, 62, 62, 62, 62, 64, 64, 70, 70, 70, 70, 73, 73, 73, 73, 73, 75,

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.

1 participant