Description
On Android, the back button in the session header becomes unresponsive when a session has multiple parallel agents running, preventing navigation to other sessions.
Root Cause
A z-index / touch layering conflict in the SessionView layout causes the ChatList's absolute-fill container to capture touches intended for the header back button.
Layout Structure
SessionView (Fragment <>)
├── Header wrapper (position: absolute, top: 0, zIndex: 1000)
│ └── ChatHeaderView with back button
│
└── Content wrapper (flex: 1, paddingTop: headerHeight)
└── AgentContentView
├── Content container (flexGrow: 1)
│ └── ChatList wrapper (position: absolute, top: 0, bottom: 0) ← PROBLEM
│ └── Inverted FlatList
└── Input container
└── AgentInput
└── permissionRequestsContainer (no zIndex)
└── PermissionFooter × N
Three interacting issues
1. ChatList wrapper ignores parent padding and fills behind the header
AgentContentView.tsx line 22 renders the ChatList inside:
<View style={[{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }]}>
{content}
</View>
The parent has paddingTop to make room for the header, but the absolute-positioned child ignores padding — it starts at top: 0 of the parent, directly behind the header. This creates an invisible full-screen touch target overlapping the header area.
2. No pointerEvents anywhere in the chain
Neither the ChatList absolute wrapper, the AgentContentView, nor the content container set pointerEvents="box-none". This means the absolute-fill container is a valid touch target that can capture taps in the header area.
3. Android z-index doesn't reliably control touch ordering
The header uses zIndex: 1000 but on Android, zIndex doesn't reliably determine touch event ordering the way it does on web/iOS. Android uses elevation for native z-ordering of touch targets, and the header container doesn't set elevation.
Why it's worse with parallel agents
- More content from multiple agents = more frequent FlatList re-renders and layout recalculations
maintainVisibleContentPosition triggers additional layout passes on every update
- Multiple permission footers stacking in AgentInput (no zIndex) add more interactive touch targets competing for events
- UI thread saturation from rapid updates causes touch events to be delayed or dropped
- React Native's touch responder system re-evaluates on each layout change — during rapid updates the ChatList container can "win" the responder negotiation over the header
Landscape mode is worse
The landscape back button (SessionView.tsx ~line 1266) has elevation: 2 but no zIndex, making it trivially overlapped by any content.
Suggested Fix
- Add
pointerEvents="box-none" to the absolute-fill ChatList wrapper in AgentContentView.tsx line 22 so it doesn't capture touches in the header area
- Add
elevation: 10 (or similar) to the header wrapper in SessionView.tsx line 244 for Android touch ordering
- Add
zIndex: 1000 to the landscape back button (SessionView.tsx ~line 1268)
- Consider adding
pointerEvents="box-none" to the content wrapper as well
Related
Description
On Android, the back button in the session header becomes unresponsive when a session has multiple parallel agents running, preventing navigation to other sessions.
Root Cause
A z-index / touch layering conflict in the SessionView layout causes the ChatList's absolute-fill container to capture touches intended for the header back button.
Layout Structure
Three interacting issues
1. ChatList wrapper ignores parent padding and fills behind the header
AgentContentView.tsxline 22 renders the ChatList inside:The parent has
paddingTopto make room for the header, but the absolute-positioned child ignores padding — it starts attop: 0of the parent, directly behind the header. This creates an invisible full-screen touch target overlapping the header area.2. No
pointerEventsanywhere in the chainNeither the ChatList absolute wrapper, the AgentContentView, nor the content container set
pointerEvents="box-none". This means the absolute-fill container is a valid touch target that can capture taps in the header area.3. Android z-index doesn't reliably control touch ordering
The header uses
zIndex: 1000but on Android,zIndexdoesn't reliably determine touch event ordering the way it does on web/iOS. Android useselevationfor native z-ordering of touch targets, and the header container doesn't setelevation.Why it's worse with parallel agents
maintainVisibleContentPositiontriggers additional layout passes on every updateLandscape mode is worse
The landscape back button (
SessionView.tsx~line 1266) haselevation: 2but nozIndex, making it trivially overlapped by any content.Suggested Fix
pointerEvents="box-none"to the absolute-fill ChatList wrapper inAgentContentView.tsxline 22 so it doesn't capture touches in the header areaelevation: 10(or similar) to the header wrapper inSessionView.tsxline 244 for Android touch orderingzIndex: 1000to the landscape back button (SessionView.tsx~line 1268)pointerEvents="box-none"to the content wrapper as wellRelated