Skip to content

fix(chat): new-chat stale selection + blank thread header entering created conversations - #29452

Merged
chrisnojima merged 3 commits into
masterfrom
nojima/HOTPOT-chat-nav
Jul 21, 2026
Merged

fix(chat): new-chat stale selection + blank thread header entering created conversations#29452
chrisnojima merged 3 commits into
masterfrom
nojima/HOTPOT-chat-nav

Conversation

@chrisnojima

@chrisnojima chrisnojima commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Problem

Two bugs in the new-chat flow:

  1. Stale selection: open new chat → pick a user → Start → reopen new chat: the previous user is still selected.
  2. Blank header: entering the conversation created by this flow often leaves the navigation header blank until you press back.

Root causes / fixes

Stale selection — the team-building store is a per-namespace singleton that outlives the modal. finishedTeamBuilding deliberately preserved teamSoFar, and the blur-listener cleanup (CancelOnBlur) doesn't fire when the modal is removed, so the selection leaked into the next session.

  • finishedTeamBuilding now clears the selection for every namespace except teams (whose add-members error path re-opens the builder and relies on the chips being intact; every onComplete handler receives a copied set, so nothing else reads the store after finish).
  • The builder screen also resets stale non-teams selections on mount, covering the back-out path.

Blank header — the pendingWaiting → real-conversation switch went through navigateAppend's replace, which degrades to setParams for the same route name. That keeps the native screen alive, and its header title was measured while pendingWaiting rendered it empty — iOS never re-measures an initially-empty title subview. Instrumentation confirmed the JS side was fully healthy (title rendered and laid out at 105pt) and the existing one-shot setOptions reconfigure fired, yet the bar stayed blank.

  • navigateToThread now dispatches a real StackActions.replace for this case, so the fresh screen measures the title with its content already present.
  • BadgeHeaderUpdater moved outside the conversation-keyed provider so its title-was-empty tracking survives same-screen conversation swaps.
  • The header title component now arms ensureConversationMetaLoaded itself, so the header self-heals for any conversation whose meta never loaded.

Tests

  • New store test: chat-namespace finish clears the selection; existing teams-preservation test unchanged.
  • yarn lint, yarn tsc, yarn jest stores/tests/team-building.test.ts all green.

…eader

Two bugs entering a conversation via new chat:

- The team-building store is a per-namespace singleton that outlives the
  modal, and finishedTeamBuilding preserved teamSoFar while the blur
  cancel doesn't fire on modal removal, so reopening new chat showed the
  previous selection. Finish now clears the selection for every
  namespace except teams (whose add-members error path re-opens the
  builder with the chips intact), and the screen resets stale non-teams
  selections on mount.

- The pendingWaiting -> real conversation switch is a setParams on the
  same screen, so the native header measured an empty title and iOS
  never re-measures it. BadgeHeaderUpdater (which force-reconfigures the
  bar once title content arrives) lived inside the conversation-keyed
  provider and remounted on the switch, seeing the title as already
  present and never firing. It now lives outside the keyed subtree, and
  the header title arms ensureConversationMetaLoaded itself so it can
  self-heal a conversation whose meta never loaded.
navigateAppend's replace degrades to setParams for the same route name,
which keeps the native screen alive; its header title was measured while
pendingWaiting rendered it empty and iOS never re-measures an
initially-empty title subview, so the header stayed blank even after the
one-shot setOptions reconfigure fired (verified via instrumentation: JS
title rendered and laid out at 105pt wide, bar still blank). Replacing
with a fresh screen measures the title with content already present.

Includes temporary [HDR] console instrumentation to verify on device;
strip before merging.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Fixes two regressions in the new-chat flow: (1) stale user/team selection persisting across re-opening the team builder, and (2) an intermittently blank iOS conversation header when transitioning from pendingWaiting to the real conversation.

Changes:

  • Reset team-building state for non-teams namespaces both on finishedTeamBuilding and on builder mount to prevent stale selection leakage.
  • Force a true React Navigation StackActions.replace when transitioning pendingWaiting → real conversation to ensure iOS re-measures the header title.
  • Make the header more resilient by keeping BadgeHeaderUpdater alive across same-screen conversation swaps and having the header arm ensureConversationMetaLoaded directly.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
shared/team-building/page.tsx Resets non-teams team-builder state on mount to avoid stale chips across modal re-opens.
shared/stores/tests/team-building.test.ts Adds coverage verifying finishedTeamBuilding clears selection/error for chat namespace while preserving teams behavior.
shared/stores/team-building.tsx Updates finishedTeamBuilding to clear selection outside teams, keeping teams selection preservation intact.
shared/constants/router.tsx Uses StackActions.replace for pendingWaiting → real conversation to avoid header blanking caused by setParams.
shared/chat/conversation/header-area/index.tsx Ensures conversation meta is loaded from the header to self-heal missing title data.
shared/chat/conversation/container.tsx Moves BadgeHeaderUpdater outside the conversation-keyed provider so its “title was empty” tracking survives param-based swaps.

@chrisnojima
chrisnojima merged commit bc6e852 into master Jul 21, 2026
2 checks passed
@chrisnojima
chrisnojima deleted the nojima/HOTPOT-chat-nav branch July 21, 2026 18:24
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