Skip to content

Commit ad450dc

Browse files
committed
fix(mobile): keep floating controls outside scrolling panels
1 parent 5643a3e commit ad450dc

1 file changed

Lines changed: 128 additions & 129 deletions

File tree

‎apps/mobile/src/features/threads/ThreadDetailScreen.tsx‎

Lines changed: 128 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -1477,15 +1477,7 @@ function ThreadDetailBody(props: ThreadDetailScreenProps) {
14771477
onLayout={handleComposerOverlayLayout}
14781478
className="w-full"
14791479
>
1480-
<ComposerPanels
1481-
className="w-full self-center"
1482-
style={[
1483-
{ maxWidth: contentMaxWidth },
1484-
Platform.OS === "android" ? composerPanelsHeightStyle : undefined,
1485-
]}
1486-
keyboardShouldPersistTaps="handled"
1487-
nestedScrollEnabled
1488-
>
1480+
<View className="w-full self-center" style={{ maxWidth: contentMaxWidth }}>
14891481
<FloatingWorkingControl
14901482
colorScheme={isDarkMode ? "dark" : "light"}
14911483
status={floatingStatus}
@@ -1519,135 +1511,142 @@ function ThreadDetailBody(props: ThreadDetailScreenProps) {
15191511
});
15201512
}}
15211513
/>
1522-
{props.queuedRunEdit !== null ? (
1523-
<Animated.View
1524-
className="shrink-0"
1525-
entering={FadeInDown.duration(180)}
1526-
exiting={FadeOut.duration(120)}
1527-
>
1528-
<ComposerQueuedEditBanner
1529-
saving={props.isSavingQueuedEdit}
1530-
onCancel={() => {
1531-
voiceInputSession.cancel(props.composerDraftKey);
1532-
props.onCancelQueuedRunEdit();
1533-
}}
1534-
/>
1535-
</Animated.View>
1536-
) : null}
1537-
<UsageLimitRecoveryCard
1538-
key={props.selectedThread.latestRun?.runId}
1539-
thread={props.selectedThread}
1540-
environmentId={props.environmentId}
1541-
/>
1542-
<ChatGptUsageLimitNotice
1543-
key={`chatgpt-limit:${props.selectedThread.latestRun?.runId}`}
1544-
thread={props.selectedThread}
1545-
/>
1546-
<ChildThreadApprovals
1547-
threadRef={props.selectedThreadDetailRef}
1548-
maxHeight={pendingUserInputMaxHeight}
1549-
/>
1550-
<ThreadGuestShareBar
1551-
threadRef={props.selectedThreadDetailRef}
1552-
canOperateThread={props.canOperateThread}
1553-
/>
1554-
{props.draftMode ? null : (
1555-
<ThreadSideChatsRow
1514+
<ComposerPanels
1515+
className="w-full"
1516+
style={Platform.OS === "android" ? composerPanelsHeightStyle : undefined}
1517+
keyboardShouldPersistTaps="handled"
1518+
nestedScrollEnabled
1519+
>
1520+
{props.queuedRunEdit !== null ? (
1521+
<Animated.View
1522+
className="shrink-0"
1523+
entering={FadeInDown.duration(180)}
1524+
exiting={FadeOut.duration(120)}
1525+
>
1526+
<ComposerQueuedEditBanner
1527+
saving={props.isSavingQueuedEdit}
1528+
onCancel={() => {
1529+
voiceInputSession.cancel(props.composerDraftKey);
1530+
props.onCancelQueuedRunEdit();
1531+
}}
1532+
/>
1533+
</Animated.View>
1534+
) : null}
1535+
<UsageLimitRecoveryCard
1536+
key={props.selectedThread.latestRun?.runId}
1537+
thread={props.selectedThread}
15561538
environmentId={props.environmentId}
1557-
threadId={props.selectedThread.id}
15581539
/>
1559-
)}
1560-
{props.feedbackSubmissions.map((submission) => (
1561-
<ComposerFeedback
1562-
key={submission.id}
1563-
submission={submission}
1564-
onDismiss={() => props.onDismissFeedback(submission.id)}
1540+
<ChatGptUsageLimitNotice
1541+
key={`chatgpt-limit:${props.selectedThread.latestRun?.runId}`}
1542+
thread={props.selectedThread}
15651543
/>
1566-
))}
1567-
{composerError !== null ? (
1568-
<Animated.View
1569-
className="shrink-0"
1570-
entering={FadeInDown.duration(180)}
1571-
exiting={FadeOut.duration(120)}
1572-
>
1573-
<ComposerErrorNotice
1574-
message={composerError}
1575-
onDismiss={() => clearThreadComposerError(selectedThreadKey)}
1576-
/>
1577-
</Animated.View>
1578-
) : null}
1579-
{usageLimitsReport && activeUserInputRequestId === null ? (
1580-
<Animated.View
1581-
className="shrink-0 px-4"
1582-
style={{ paddingBottom: USAGE_LIMITS_PANEL_GAP }}
1583-
onLayout={handleUsageLimitsLayout}
1584-
entering={FadeInDown.duration(220)}
1585-
exiting={FadeOut.duration(140)}
1586-
>
1587-
<ComposerUsageLimits
1588-
report={usageLimitsReport}
1544+
<ChildThreadApprovals
1545+
threadRef={props.selectedThreadDetailRef}
1546+
maxHeight={pendingUserInputMaxHeight}
1547+
/>
1548+
<ThreadGuestShareBar
1549+
threadRef={props.selectedThreadDetailRef}
1550+
canOperateThread={props.canOperateThread}
1551+
/>
1552+
{props.draftMode ? null : (
1553+
<ThreadSideChatsRow
15891554
environmentId={props.environmentId}
1590-
maxHeight={usageLimitsMaxHeight}
1591-
onClose={dismissUsageLimits}
1555+
threadId={props.selectedThread.id}
15921556
/>
1593-
</Animated.View>
1594-
) : null}
1595-
{props.creationState?.kind === "failed" ? (
1596-
<Animated.View
1597-
className="shrink-0 px-4"
1598-
style={{ paddingBottom: composerBottomInset }}
1599-
entering={FadeInDown.duration(220)}
1600-
exiting={FadeOut.duration(140)}
1601-
>
1602-
<ThreadCreationFailedCard
1603-
reason={props.creationState.reason}
1604-
onEditTask={props.creationState.onEditTask}
1557+
)}
1558+
{props.feedbackSubmissions.map((submission) => (
1559+
<ComposerFeedback
1560+
key={submission.id}
1561+
submission={submission}
1562+
onDismiss={() => props.onDismissFeedback(submission.id)}
16051563
/>
1606-
</Animated.View>
1607-
) : null}
1608-
{props.activePendingApproval || props.activePendingUserInput ? (
1609-
<Animated.View
1610-
className="shrink-0 gap-3 px-4 pb-3"
1611-
style={
1612-
activeUserInputRequestId !== null
1613-
? { paddingBottom: composerBottomInset }
1614-
: undefined
1615-
}
1616-
entering={FadeInDown.duration(220)}
1617-
exiting={FadeOut.duration(140)}
1618-
>
1619-
{props.activePendingApproval ? (
1620-
<PendingApprovalCard
1621-
canOperateThread={props.canOperateThread}
1622-
approval={props.activePendingApproval}
1623-
respondingApprovalId={props.respondingApprovalId}
1624-
onRespond={props.onRespondToApproval}
1564+
))}
1565+
{composerError !== null ? (
1566+
<Animated.View
1567+
className="shrink-0"
1568+
entering={FadeInDown.duration(180)}
1569+
exiting={FadeOut.duration(120)}
1570+
>
1571+
<ComposerErrorNotice
1572+
message={composerError}
1573+
onDismiss={() => clearThreadComposerError(selectedThreadKey)}
16251574
/>
1626-
) : null}
1627-
{props.activePendingUserInput ? (
1628-
<PendingUserInputCard
1575+
</Animated.View>
1576+
) : null}
1577+
{usageLimitsReport && activeUserInputRequestId === null ? (
1578+
<Animated.View
1579+
className="shrink-0 px-4"
1580+
style={{ paddingBottom: USAGE_LIMITS_PANEL_GAP }}
1581+
onLayout={handleUsageLimitsLayout}
1582+
entering={FadeInDown.duration(220)}
1583+
exiting={FadeOut.duration(140)}
1584+
>
1585+
<ComposerUsageLimits
1586+
report={usageLimitsReport}
16291587
environmentId={props.environmentId}
1630-
canOperateThread={props.canOperateThread}
1631-
pendingUserInput={props.activePendingUserInput}
1632-
maxHeight={pendingUserInputMaxHeight}
1633-
collapsed={userInputCollapsed}
1634-
onToggleCollapsed={handleToggleUserInputCollapsed}
1635-
onStopThread={props.onStopThread}
1636-
cardProgress={userInputCardProgress}
1637-
cardCoverage={userInputCardCoverage}
1638-
onInputFocusChange={handleOwnedInputFocusChange}
1639-
drafts={props.activePendingUserInputDrafts}
1640-
answers={props.activePendingUserInputAnswers}
1641-
respondingUserInputId={props.respondingUserInputId}
1642-
onSelectOption={props.onSelectUserInputOption}
1643-
onChangeCustomAnswer={props.onChangeUserInputCustomAnswer}
1644-
onSubmit={props.onSubmitUserInput}
1645-
onDismiss={props.onDismissUserInput}
1588+
maxHeight={usageLimitsMaxHeight}
1589+
onClose={dismissUsageLimits}
1590+
/>
1591+
</Animated.View>
1592+
) : null}
1593+
{props.creationState?.kind === "failed" ? (
1594+
<Animated.View
1595+
className="shrink-0 px-4"
1596+
style={{ paddingBottom: composerBottomInset }}
1597+
entering={FadeInDown.duration(220)}
1598+
exiting={FadeOut.duration(140)}
1599+
>
1600+
<ThreadCreationFailedCard
1601+
reason={props.creationState.reason}
1602+
onEditTask={props.creationState.onEditTask}
16461603
/>
1647-
) : null}
1648-
</Animated.View>
1649-
) : null}
1650-
</ComposerPanels>
1604+
</Animated.View>
1605+
) : null}
1606+
{props.activePendingApproval || props.activePendingUserInput ? (
1607+
<Animated.View
1608+
className="shrink-0 gap-3 px-4 pb-3"
1609+
style={
1610+
activeUserInputRequestId !== null
1611+
? { paddingBottom: composerBottomInset }
1612+
: undefined
1613+
}
1614+
entering={FadeInDown.duration(220)}
1615+
exiting={FadeOut.duration(140)}
1616+
>
1617+
{props.activePendingApproval ? (
1618+
<PendingApprovalCard
1619+
canOperateThread={props.canOperateThread}
1620+
approval={props.activePendingApproval}
1621+
respondingApprovalId={props.respondingApprovalId}
1622+
onRespond={props.onRespondToApproval}
1623+
/>
1624+
) : null}
1625+
{props.activePendingUserInput ? (
1626+
<PendingUserInputCard
1627+
environmentId={props.environmentId}
1628+
canOperateThread={props.canOperateThread}
1629+
pendingUserInput={props.activePendingUserInput}
1630+
maxHeight={pendingUserInputMaxHeight}
1631+
collapsed={userInputCollapsed}
1632+
onToggleCollapsed={handleToggleUserInputCollapsed}
1633+
onStopThread={props.onStopThread}
1634+
cardProgress={userInputCardProgress}
1635+
cardCoverage={userInputCardCoverage}
1636+
onInputFocusChange={handleOwnedInputFocusChange}
1637+
drafts={props.activePendingUserInputDrafts}
1638+
answers={props.activePendingUserInputAnswers}
1639+
respondingUserInputId={props.respondingUserInputId}
1640+
onSelectOption={props.onSelectUserInputOption}
1641+
onChangeCustomAnswer={props.onChangeUserInputCustomAnswer}
1642+
onSubmit={props.onSubmitUserInput}
1643+
onDismiss={props.onDismissUserInput}
1644+
/>
1645+
) : null}
1646+
</Animated.View>
1647+
) : null}
1648+
</ComposerPanels>
1649+
</View>
16511650

16521651
<View style={composerSlotHidden ? { display: "none" } : undefined}>
16531652
{isProviderSubagent ? (

0 commit comments

Comments
 (0)