Let composer controls adapt to narrow panes (#1270)

This commit is contained in:
Mohamed Boudra
2026-06-01 22:58:03 +08:00
committed by GitHub
parent 1ede1bccf7
commit ce8ad8c68f
7 changed files with 118 additions and 39 deletions
@@ -97,6 +97,7 @@ interface ControlledAgentControlsProps {
/** Extra elements rendered inline with the agent controls (desktop only). */ /** Extra elements rendered inline with the agent controls (desktop only). */
desktopExtras?: ReactNode; desktopExtras?: ReactNode;
modelSelectorServerId?: string | null; modelSelectorServerId?: string | null;
isCompactLayout?: boolean;
} }
export interface DraftAgentControlsProps { export interface DraftAgentControlsProps {
@@ -124,12 +125,14 @@ export interface DraftAgentControlsProps {
isRetryingModelProvider?: boolean; isRetryingModelProvider?: boolean;
disabled?: boolean; disabled?: boolean;
modelSelectorServerId?: string | null; modelSelectorServerId?: string | null;
isCompactLayout?: boolean;
} }
interface AgentControlsProps { interface AgentControlsProps {
agentId: string; agentId: string;
serverId: string; serverId: string;
onDropdownClose?: () => void; onDropdownClose?: () => void;
isCompactLayout?: boolean;
} }
function findOptionLabel( function findOptionLabel(
@@ -409,9 +412,11 @@ function ControlledAgentControls({
isRetryingModelProvider = false, isRetryingModelProvider = false,
desktopExtras, desktopExtras,
modelSelectorServerId = null, modelSelectorServerId = null,
isCompactLayout,
}: ControlledAgentControlsProps) { }: ControlledAgentControlsProps) {
const { theme } = useUnistyles(); const { theme } = useUnistyles();
const isCompact = useIsCompactFormFactor(); const isCompactFormFactor = useIsCompactFormFactor();
const isCompact = isCompactLayout ?? isCompactFormFactor;
const [activeSheet, setActiveSheet] = useState<ActiveSheet>(null); const [activeSheet, setActiveSheet] = useState<ActiveSheet>(null);
const [openSelector, setOpenSelector] = useState<AgentControlSelector | null>(null); const [openSelector, setOpenSelector] = useState<AgentControlSelector | null>(null);
@@ -1345,6 +1350,7 @@ export const AgentControls = memo(function AgentControls({
agentId, agentId,
serverId, serverId,
onDropdownClose, onDropdownClose,
isCompactLayout,
}: AgentControlsProps) { }: AgentControlsProps) {
const { preferences, updatePreferences } = useFormPreferences(); const { preferences, updatePreferences } = useFormPreferences();
const agent = useSessionStore( const agent = useSessionStore(
@@ -1518,8 +1524,15 @@ export const AgentControls = memo(function AgentControls({
); );
const modeChip = useMemo( const modeChip = useMemo(
() => <AgentModeControl serverId={serverId} agentId={agentId} placement="toolbar" />, () => (
[serverId, agentId], <AgentModeControl
serverId={serverId}
agentId={agentId}
placement="toolbar"
isCompactLayout={isCompactLayout}
/>
),
[serverId, agentId, isCompactLayout],
); );
if (!agent) { if (!agent) {
@@ -1548,6 +1561,7 @@ export const AgentControls = memo(function AgentControls({
disabled={!client} disabled={!client}
desktopExtras={modeChip} desktopExtras={modeChip}
modelSelectorServerId={serverId} modelSelectorServerId={serverId}
isCompactLayout={isCompactLayout}
/> />
); );
}); });
@@ -1577,9 +1591,11 @@ export function DraftAgentControls({
isRetryingModelProvider = false, isRetryingModelProvider = false,
disabled = false, disabled = false,
modelSelectorServerId = null, modelSelectorServerId = null,
isCompactLayout,
}: DraftAgentControlsProps) { }: DraftAgentControlsProps) {
const { preferences, updatePreferences } = useFormPreferences(); const { preferences, updatePreferences } = useFormPreferences();
const isCompact = useIsCompactFormFactor(); const isCompactFormFactor = useIsCompactFormFactor();
const isCompact = isCompactLayout ?? isCompactFormFactor;
const mappedThinkingOptions = useMemo<AgentControlOption[]>(() => { const mappedThinkingOptions = useMemo<AgentControlOption[]>(() => {
return toThinkingControlOptions(thinkingOptions); return toThinkingControlOptions(thinkingOptions);
@@ -1625,9 +1641,18 @@ export function DraftAgentControls({
selectedMode={selectedMode} selectedMode={selectedMode}
onSelectMode={onSelectMode} onSelectMode={onSelectMode}
disabled={disabled} disabled={disabled}
isCompactLayout={isCompactLayout}
/> />
), ),
[selectedProvider, providerDefinitions, modeOptions, selectedMode, onSelectMode, disabled], [
selectedProvider,
providerDefinitions,
modeOptions,
selectedMode,
onSelectMode,
disabled,
isCompactLayout,
],
); );
if (!isCompact) { if (!isCompact) {
@@ -1661,6 +1686,7 @@ export function DraftAgentControls({
isRetryingModelProvider={isRetryingModelProvider} isRetryingModelProvider={isRetryingModelProvider}
disabled={disabled} disabled={disabled}
desktopExtras={draftModeChip} desktopExtras={draftModeChip}
isCompactLayout={isCompactLayout}
/> />
) : null} ) : null}
</View> </View>
@@ -1688,6 +1714,7 @@ export function DraftAgentControls({
isRetryingModelProvider={isRetryingModelProvider} isRetryingModelProvider={isRetryingModelProvider}
disabled={disabled} disabled={disabled}
modelSelectorServerId={modelSelectorServerId} modelSelectorServerId={modelSelectorServerId}
isCompactLayout={isCompactLayout}
/> />
); );
} }
@@ -235,14 +235,17 @@ interface AgentModeControlProps {
serverId: string; serverId: string;
agentId: string; agentId: string;
placement: AgentModeControlPlacement; placement: AgentModeControlPlacement;
isCompactLayout?: boolean;
} }
export const AgentModeControl = memo(function AgentModeControl({ export const AgentModeControl = memo(function AgentModeControl({
serverId, serverId,
agentId, agentId,
placement, placement,
isCompactLayout,
}: AgentModeControlProps) { }: AgentModeControlProps) {
const isCompact = useIsCompactFormFactor(); const isCompactFormFactor = useIsCompactFormFactor();
const isCompact = isCompactLayout ?? isCompactFormFactor;
const slice = useSessionStore( const slice = useSessionStore(
useShallow((state) => { useShallow((state) => {
const agent = state.sessions[serverId]?.agents?.get(agentId); const agent = state.sessions[serverId]?.agents?.get(agentId);
@@ -303,6 +306,7 @@ export interface DraftAgentModeControlProps {
onSelectMode: (modeId: string) => void; onSelectMode: (modeId: string) => void;
disabled?: boolean; disabled?: boolean;
placement: AgentModeControlPlacement; placement: AgentModeControlPlacement;
isCompactLayout?: boolean;
} }
export function DraftAgentModeControl({ export function DraftAgentModeControl({
@@ -313,8 +317,10 @@ export function DraftAgentModeControl({
onSelectMode, onSelectMode,
disabled, disabled,
placement, placement,
isCompactLayout,
}: DraftAgentModeControlProps) { }: DraftAgentModeControlProps) {
const isCompact = useIsCompactFormFactor(); const isCompactFormFactor = useIsCompactFormFactor();
const isCompact = isCompactLayout ?? isCompactFormFactor;
if (!selectedProvider || modeOptions.length === 0) return null; if (!selectedProvider || modeOptions.length === 0) return null;
if (!shouldRenderForPlacement(placement, isCompact)) return null; if (!shouldRenderForPlacement(placement, isCompact)) return null;
return ( return (
@@ -4,6 +4,7 @@ import ReanimatedAnimated from "react-native-reanimated";
import { StyleSheet } from "react-native-unistyles"; import { StyleSheet } from "react-native-unistyles";
import { useSafeAreaInsets } from "react-native-safe-area-context"; import { useSafeAreaInsets } from "react-native-safe-area-context";
import { useKeyboardShiftStyle } from "@/hooks/use-keyboard-shift-style"; import { useKeyboardShiftStyle } from "@/hooks/use-keyboard-shift-style";
import { useContainerWidthBelow } from "@/hooks/use-container-width";
import invariant from "tiny-invariant"; import invariant from "tiny-invariant";
import { Composer } from "@/composer"; import { Composer } from "@/composer";
import { DraftAgentModeControl } from "@/composer/agent-controls/mode-control"; import { DraftAgentModeControl } from "@/composer/agent-controls/mode-control";
@@ -36,7 +37,11 @@ import {
useWorkspaceAttachmentScopeKey, useWorkspaceAttachmentScopeKey,
} from "@/attachments/workspace-attachments-store"; } from "@/attachments/workspace-attachments-store";
import type { UserMessageImageAttachment } from "@/types/stream"; import type { UserMessageImageAttachment } from "@/types/stream";
import { MAX_CONTENT_WIDTH, useIsCompactFormFactor } from "@/constants/layout"; import {
COMPACT_FORM_FACTOR_WIDTH,
MAX_CONTENT_WIDTH,
useIsCompactFormFactor,
} from "@/constants/layout";
import { isWeb } from "@/constants/platform"; import { isWeb } from "@/constants/platform";
import type { WorkspaceDraftTabSetup } from "@/stores/workspace-tabs-store"; import type { WorkspaceDraftTabSetup } from "@/stores/workspace-tabs-store";
@@ -380,7 +385,11 @@ export function WorkspaceDraftAgentTab({
}; };
}, [pendingAutoSubmit, pendingCreateAttempt]); }, [pendingAutoSubmit, pendingCreateAttempt]);
const allowsEmptyAutoSubmit = pendingAutoSubmit?.allowEmptyText === true; const allowsEmptyAutoSubmit = pendingAutoSubmit?.allowEmptyText === true;
const isCompact = useIsCompactFormFactor(); const isCompactFormFactor = useIsCompactFormFactor();
const { onLayout: onInputAreaLayout, isBelow: isCompactComposerLayout } = useContainerWidthBelow(
COMPACT_FORM_FACTOR_WIDTH,
{ initialIsBelow: isCompactFormFactor },
);
const workspaceAttachmentScopeKey = useWorkspaceAttachmentScopeKey({ const workspaceAttachmentScopeKey = useWorkspaceAttachmentScopeKey({
serverId, serverId,
cwd: composerState.workingDir, cwd: composerState.workingDir,
@@ -401,14 +410,14 @@ export function WorkspaceDraftAgentTab({
}; };
openFileExplorerForCheckout({ openFileExplorerForCheckout({
checkout, checkout,
isCompact, isCompact: isCompactFormFactor,
}); });
setExplorerTabForCheckout({ setExplorerTabForCheckout({
...checkout, ...checkout,
tab: "changes", tab: "changes",
}); });
}, },
[isCompact, openFileExplorerForCheckout, serverId, setExplorerTabForCheckout], [isCompactFormFactor, openFileExplorerForCheckout, serverId, setExplorerTabForCheckout],
); );
const { const {
@@ -625,10 +634,14 @@ export function WorkspaceDraftAgentTab({
); );
const composerFooter = useMemo( const composerFooter = useMemo(
() => () =>
isCompact ? ( isCompactComposerLayout ? (
<DraftAgentModeControl placement="footer" {...composerAgentControls} /> <DraftAgentModeControl
placement="footer"
{...composerAgentControls}
isCompactLayout={isCompactComposerLayout}
/>
) : undefined, ) : undefined,
[isCompact, composerAgentControls], [isCompactComposerLayout, composerAgentControls],
); );
return ( return (
@@ -662,7 +675,7 @@ export function WorkspaceDraftAgentTab({
)} )}
</View> </View>
<ReanimatedAnimated.View style={inputAreaWrapperStyle}> <ReanimatedAnimated.View style={inputAreaWrapperStyle} onLayout={onInputAreaLayout}>
{importPillPress ? ( {importPillPress ? (
<View style={styles.importPillRow}> <View style={styles.importPillRow}>
<View style={styles.importPillContent}> <View style={styles.importPillContent}>
@@ -692,6 +705,7 @@ export function WorkspaceDraftAgentTab({
commandDraftConfig={composerState.commandDraftConfig} commandDraftConfig={composerState.commandDraftConfig}
agentControls={composerAgentControls} agentControls={composerAgentControls}
footer={composerFooter} footer={composerFooter}
isCompactLayout={isCompactComposerLayout}
/> />
</ReanimatedAnimated.View> </ReanimatedAnimated.View>
</View> </View>
+31 -14
View File
@@ -140,6 +140,10 @@ function resolveIsDesktopWebBreakpoint(isMobile: boolean): boolean {
return isWeb && !isMobile; return isWeb && !isMobile;
} }
function resolveCompactLayout(override: boolean | undefined, formFactor: boolean): boolean {
return override ?? formFactor;
}
function resolveMessagePlaceholder(isDesktopWebBreakpoint: boolean): string { function resolveMessagePlaceholder(isDesktopWebBreakpoint: boolean): string {
return isDesktopWebBreakpoint ? DESKTOP_MESSAGE_PLACEHOLDER : MOBILE_MESSAGE_PLACEHOLDER; return isDesktopWebBreakpoint ? DESKTOP_MESSAGE_PLACEHOLDER : MOBILE_MESSAGE_PLACEHOLDER;
} }
@@ -223,14 +227,22 @@ interface RenderLeftContentArgs {
agentId: string; agentId: string;
serverId: string; serverId: string;
focusInput: () => void; focusInput: () => void;
isCompactLayout: boolean;
} }
function renderLeftContent(args: RenderLeftContentArgs): ReactElement { function renderLeftContent(args: RenderLeftContentArgs): ReactElement {
const { agentControls, agentId, serverId, focusInput } = args; const { agentControls, agentId, serverId, focusInput, isCompactLayout } = args;
if (resolveAgentControlsMode(agentControls) === "draft" && agentControls) { if (resolveAgentControlsMode(agentControls) === "draft" && agentControls) {
return <DraftAgentControls {...agentControls} />; return <DraftAgentControls {...agentControls} isCompactLayout={isCompactLayout} />;
} }
return <AgentControls agentId={agentId} serverId={serverId} onDropdownClose={focusInput} />; return (
<AgentControls
agentId={agentId}
serverId={serverId}
onDropdownClose={focusInput}
isCompactLayout={isCompactLayout}
/>
);
} }
interface RenderAttachmentTrayArgs { interface RenderAttachmentTrayArgs {
@@ -674,6 +686,8 @@ interface ComposerProps {
footer?: ReactNode; footer?: ReactNode;
/** When true, a parent wrapper owns the keyboard shift, so the composer skips its own. */ /** When true, a parent wrapper owns the keyboard shift, so the composer skips its own. */
externalKeyboardShift?: boolean; externalKeyboardShift?: boolean;
/** Optional panel/container layout breakpoint. Defaults to the screen breakpoint. */
isCompactLayout?: boolean;
} }
const EMPTY_ARRAY: readonly QueuedMessage[] = []; const EMPTY_ARRAY: readonly QueuedMessage[] = [];
@@ -869,6 +883,7 @@ export function Composer({
inputWrapperStyle, inputWrapperStyle,
footer, footer,
externalKeyboardShift, externalKeyboardShift,
isCompactLayout: isCompactLayoutOverride,
}: ComposerProps) { }: ComposerProps) {
const buttonIconSize = resolveComposerButtonIconSize(); const buttonIconSize = resolveComposerButtonIconSize();
const client = useHostRuntimeClient(serverId); const client = useHostRuntimeClient(serverId);
@@ -899,9 +914,11 @@ export function Composer({
const setAgentStreamTail = useSessionStore((state) => state.setAgentStreamTail); const setAgentStreamTail = useSessionStore((state) => state.setAgentStreamTail);
const setAgentStreamHead = useSessionStore((state) => state.setAgentStreamHead); const setAgentStreamHead = useSessionStore((state) => state.setAgentStreamHead);
const isMobile = useIsCompactFormFactor(); const isCompactFormFactor = useIsCompactFormFactor();
const isDesktopWebBreakpoint = resolveIsDesktopWebBreakpoint(isMobile); const isCompactLayout = resolveCompactLayout(isCompactLayoutOverride, isCompactFormFactor);
const messagePlaceholder = resolveMessagePlaceholder(isDesktopWebBreakpoint); const isDesktopWebBreakpoint = resolveIsDesktopWebBreakpoint(isCompactFormFactor);
const isDesktopLayout = resolveIsDesktopWebBreakpoint(isCompactLayout);
const messagePlaceholder = resolveMessagePlaceholder(isDesktopLayout);
const userInput = value; const userInput = value;
const setUserInput = onChangeText; const setUserInput = onChangeText;
const { const {
@@ -1437,7 +1454,7 @@ export function Composer({
isAgentRunning={isAgentRunning} isAgentRunning={isAgentRunning}
hasSendableContent={hasSendableContent} hasSendableContent={hasSendableContent}
isProcessing={isProcessing} isProcessing={isProcessing}
isCompact={isMobile} isCompact={isCompactLayout}
buttonIconSize={buttonIconSize} buttonIconSize={buttonIconSize}
handleToggleRealtimeVoice={handleToggleRealtimeVoice} handleToggleRealtimeVoice={handleToggleRealtimeVoice}
isConnected={isConnected} isConnected={isConnected}
@@ -1455,7 +1472,7 @@ export function Composer({
hasSendableContent, hasSendableContent,
isAgentRunning, isAgentRunning,
isConnected, isConnected,
isMobile, isCompactLayout,
isProcessing, isProcessing,
isVoiceModeForAgent, isVoiceModeForAgent,
isVoiceSwitching, isVoiceSwitching,
@@ -1475,13 +1492,13 @@ export function Composer({
contextWindowMaxTokens, contextWindowMaxTokens,
contextWindowUsedTokens, contextWindowUsedTokens,
agentState.totalCostUsd, agentState.totalCostUsd,
isMobile, isCompactLayout,
), ),
[contextWindowMaxTokens, contextWindowUsedTokens, agentState.totalCostUsd, isMobile], [contextWindowMaxTokens, contextWindowUsedTokens, agentState.totalCostUsd, isCompactLayout],
); );
const { beforeVoiceContent, footerInlineContent } = useMemo( const { beforeVoiceContent, footerInlineContent } = useMemo(
() => resolveContextWindowPlacement(contextWindowMeter, isMobile), () => resolveContextWindowPlacement(contextWindowMeter, isCompactLayout),
[contextWindowMeter, isMobile], [contextWindowMeter, isCompactLayout],
); );
const githubSearchQueryTrimmed = githubSearchQuery.trim(); const githubSearchQueryTrimmed = githubSearchQuery.trim();
@@ -1548,8 +1565,8 @@ export function Composer({
); );
const leftContent = useMemo( const leftContent = useMemo(
() => renderLeftContent({ agentControls, agentId, serverId, focusInput }), () => renderLeftContent({ agentControls, agentId, serverId, focusInput, isCompactLayout }),
[agentId, focusInput, serverId, agentControls], [agentId, focusInput, serverId, agentControls, isCompactLayout],
); );
const handleAttachButtonRef = useCallback((node: View | null) => { const handleAttachButtonRef = useCallback((node: View | null) => {
+1
View File
@@ -13,6 +13,7 @@ export const HEADER_TOP_PADDING_MOBILE = 8;
// Max width for chat content (stream view, input area, new agent form) // Max width for chat content (stream view, input area, new agent form)
export const MAX_CONTENT_WIDTH = 820; export const MAX_CONTENT_WIDTH = 820;
export const COMPACT_FORM_FACTOR_WIDTH = 768;
// Desktop app constants for macOS traffic light buttons // Desktop app constants for macOS traffic light buttons
// These buttons (close/minimize/maximize) overlay the top-left corner // These buttons (close/minimize/maximize) overlay the top-left corner
@@ -20,11 +20,14 @@ export function useContainerWidth(): {
/** /**
* Tracks only whether a container is narrower than a threshold. * Tracks only whether a container is narrower than a threshold.
*/ */
export function useContainerWidthBelow(threshold: number): { export function useContainerWidthBelow(
threshold: number,
options?: { initialIsBelow?: boolean },
): {
onLayout: (e: LayoutChangeEvent) => void; onLayout: (e: LayoutChangeEvent) => void;
isBelow: boolean; isBelow: boolean;
} { } {
const [isBelow, setIsBelow] = useState(true); const [isBelow, setIsBelow] = useState(options?.initialIsBelow ?? true);
return { return {
onLayout: useCallback( onLayout: useCallback(
(e: LayoutChangeEvent) => { (e: LayoutChangeEvent) => {
+19 -8
View File
@@ -22,7 +22,7 @@ import {
useWorkspaceAttachments, useWorkspaceAttachments,
useWorkspaceAttachmentScopeKey, useWorkspaceAttachmentScopeKey,
} from "@/attachments/workspace-attachments-store"; } from "@/attachments/workspace-attachments-store";
import { useIsCompactFormFactor } from "@/constants/layout"; import { COMPACT_FORM_FACTOR_WIDTH, useIsCompactFormFactor } from "@/constants/layout";
import { isNative, isWeb } from "@/constants/platform"; import { isNative, isWeb } from "@/constants/platform";
import { useAgentAttentionClear } from "@/hooks/use-agent-attention-clear"; import { useAgentAttentionClear } from "@/hooks/use-agent-attention-clear";
import { useAgentInitialization } from "@/hooks/use-agent-initialization"; import { useAgentInitialization } from "@/hooks/use-agent-initialization";
@@ -36,6 +36,7 @@ import {
} from "@/hooks/use-agent-screen-state-machine"; } from "@/hooks/use-agent-screen-state-machine";
import { useArchiveAgent } from "@/hooks/use-archive-agent"; import { useArchiveAgent } from "@/hooks/use-archive-agent";
import { useKeyboardShiftStyle } from "@/hooks/use-keyboard-shift-style"; import { useKeyboardShiftStyle } from "@/hooks/use-keyboard-shift-style";
import { useContainerWidthBelow } from "@/hooks/use-container-width";
import { usePaneContext, usePaneFocus } from "@/panels/pane-context"; import { usePaneContext, usePaneFocus } from "@/panels/pane-context";
import type { PanelDescriptor, PanelRegistration } from "@/panels/panel-registry"; import type { PanelDescriptor, PanelRegistration } from "@/panels/panel-registry";
import { RenderProfile } from "@/utils/render-profiler"; import { RenderProfile } from "@/utils/render-profiler";
@@ -1317,7 +1318,11 @@ function ActiveAgentComposer({
onMessageSent: () => void; onMessageSent: () => void;
}) { }) {
const insets = useSafeAreaInsets(); const insets = useSafeAreaInsets();
const isCompact = useIsCompactFormFactor(); const isCompactFormFactor = useIsCompactFormFactor();
const { onLayout: onInputAreaLayout, isBelow: isCompactComposerLayout } = useContainerWidthBelow(
COMPACT_FORM_FACTOR_WIDTH,
{ initialIsBelow: isCompactFormFactor },
);
const paneContext = usePaneContext(); const paneContext = usePaneContext();
const { workspaceId, tabId, retargetCurrentTab } = paneContext; const { workspaceId, tabId, retargetCurrentTab } = paneContext;
const { archiveAgent } = useArchiveAgent(); const { archiveAgent } = useArchiveAgent();
@@ -1355,14 +1360,14 @@ function ActiveAgentComposer({
}; };
openFileExplorerForCheckout({ openFileExplorerForCheckout({
checkout, checkout,
isCompact, isCompact: isCompactFormFactor,
}); });
setExplorerTabForCheckout({ setExplorerTabForCheckout({
...checkout, ...checkout,
tab: "changes", tab: "changes",
}); });
}, },
[isCompact, openFileExplorerForCheckout, serverId, setExplorerTabForCheckout], [isCompactFormFactor, openFileExplorerForCheckout, serverId, setExplorerTabForCheckout],
); );
const handleClientSlashCommand = useCallback( const handleClientSlashCommand = useCallback(
@@ -1414,14 +1419,19 @@ function ActiveAgentComposer({
const composerFooter = useMemo( const composerFooter = useMemo(
() => () =>
isCompact ? ( isCompactComposerLayout ? (
<AgentModeControl serverId={serverId} agentId={agentId} placement="footer" /> <AgentModeControl
serverId={serverId}
agentId={agentId}
placement="footer"
isCompactLayout={isCompactComposerLayout}
/>
) : undefined, ) : undefined,
[isCompact, serverId, agentId], [isCompactComposerLayout, serverId, agentId],
); );
return ( return (
<ReanimatedAnimated.View style={inputAreaStyle}> <ReanimatedAnimated.View style={inputAreaStyle} onLayout={onInputAreaLayout}>
<SubagentsTrack <SubagentsTrack
rows={subagentRows} rows={subagentRows}
onOpenSubagent={handleOpenSubagent} onOpenSubagent={handleOpenSubagent}
@@ -1449,6 +1459,7 @@ function ActiveAgentComposer({
onMessageSent={onMessageSent} onMessageSent={onMessageSent}
onClientSlashCommand={handleClientSlashCommand} onClientSlashCommand={handleClientSlashCommand}
footer={composerFooter} footer={composerFooter}
isCompactLayout={isCompactComposerLayout}
/> />
</ReanimatedAnimated.View> </ReanimatedAnimated.View>
); );