From e110bfb67985b70c3ff7ef356f4b1e70ec2fcb9f Mon Sep 17 00:00:00 2001 From: Pixel Perfect Date: Sun, 25 Oct 2026 10:24:35 -0700 Subject: [PATCH 1/4] fix(mobile): align the iPad composer with workspace tabs --- .../src/features/threads/ThreadComposer.tsx | 27 ++++++++++--------- .../features/threads/ThreadDetailScreen.tsx | 9 ++++--- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/apps/mobile/src/features/threads/ThreadComposer.tsx b/apps/mobile/src/features/threads/ThreadComposer.tsx index 2f913144332d6..f59e6cddfb8cd 100644 --- a/apps/mobile/src/features/threads/ThreadComposer.tsx +++ b/apps/mobile/src/features/threads/ThreadComposer.tsx @@ -595,7 +595,8 @@ export const ThreadComposer = function ThreadComposer(props: ThreadComposerProps const isVoiceInputPresented = voicePresentation.statusLabel !== null; const isExpanded = isFocused || settingsSheetPresentation.keepsComposerExpanded; const { setComposerEditing } = useAdaptiveWorkspaceLayout(); - const hasSidebarTabBar = useSidebarWorkspaceTabs() === "picker"; + const sidebarTabs = useSidebarWorkspaceTabs(); + const usesLargeControls = (Platform.OS === "ios" && Platform.isPad) || sidebarTabs === "picker"; const [compactRowWidth, setCompactRowWidth] = useState(0); const compactAttachmentLimit = compactRowWidth >= 500 ? 3 : 1; const compactEditor = useCompactComposerEditor(bodyText, draftMessage); @@ -846,7 +847,7 @@ export const ThreadComposer = function ThreadComposer(props: ThreadComposerProps const modelControl = ( {isExpanded ? editingAttachments : null} @@ -949,7 +950,7 @@ export const ThreadComposer = function ThreadComposer(props: ThreadComposerProps hidden={showsCompactDictation} > {modelControl} {showStopAction ? ( ) : showResumeAction ? ( ) : ( @@ -1212,7 +1213,7 @@ export const ThreadComposer = function ThreadComposer(props: ThreadComposerProps ) : ( (null); const activeUserInputRequestId = props.activePendingUserInput?.requestId ?? null; From cd5f9f655823c182c252dca83d2fdb491db8b176 Mon Sep 17 00:00:00 2001 From: Pixel Perfect Date: Sun, 25 Oct 2026 10:35:34 -0700 Subject: [PATCH 2/4] fix(mobile): keep a bottom gutter in compact iPad windows --- apps/mobile/src/features/threads/ThreadDetailScreen.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/mobile/src/features/threads/ThreadDetailScreen.tsx b/apps/mobile/src/features/threads/ThreadDetailScreen.tsx index f182207f6b4ad..2d9fe7b738d4b 100644 --- a/apps/mobile/src/features/threads/ThreadDetailScreen.tsx +++ b/apps/mobile/src/features/threads/ThreadDetailScreen.tsx @@ -115,6 +115,7 @@ import Animated, { } from "react-native-reanimated"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { useWorkspaceContentWidth } from "../layout/workspace-content-width"; +import { useAdaptiveWorkspaceLayout } from "../layout/adaptive-workspace-context"; import { useNativeWorkspaceColumnsSupported } from "../../native/NativeWorkspaceColumns"; import { useDeviceType, @@ -504,6 +505,7 @@ const COMPOSER_HEIGHT_SETTLE_MS = 220; export const ThreadDetailScreen = function ThreadDetailScreen(props: ThreadDetailScreenProps) { const usesNativeWorkspaceColumns = useNativeWorkspaceColumnsSupported(); + const { layout } = useAdaptiveWorkspaceLayout(); const deviceType = useDeviceType(); const workspace = useWorkspaceTabs(); const sidebarSearchActive = @@ -636,7 +638,9 @@ export const ThreadDetailScreen = function ThreadDetailScreen(props: ThreadDetai // The pill already adds its own gutter; iPad and Duo align its edge with the native bar. const alignedBottomInset = bottomBarInset ?? - (Platform.OS === "ios" && Platform.isPad ? Math.max(bottomSafeArea, 12) - 5 : undefined); + (Platform.OS === "ios" && Platform.isPad + ? Math.max(bottomSafeArea, 12) - (layout.usesSplitView ? 5 : 0) + : undefined); // The Duo's floating sidebar pill ends three points below the composer's usual gutter. const composerBottomInset = Math.max( 0, From e35a31a252bf6361bceb86300e814f7e4eeaeb7b Mon Sep 17 00:00:00 2001 From: Pixel Perfect Date: Sun, 25 Oct 2026 11:27:34 -0700 Subject: [PATCH 3/4] fix(mobile): preserve provider subagent feed clearance --- apps/mobile/src/features/threads/ThreadDetailScreen.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/mobile/src/features/threads/ThreadDetailScreen.tsx b/apps/mobile/src/features/threads/ThreadDetailScreen.tsx index 2d9fe7b738d4b..d35e781c8c87f 100644 --- a/apps/mobile/src/features/threads/ThreadDetailScreen.tsx +++ b/apps/mobile/src/features/threads/ThreadDetailScreen.tsx @@ -925,7 +925,7 @@ export const ThreadDetailScreen = function ThreadDetailScreen(props: ThreadDetai const composerOverlapHeight = composerHeight ?? COMPOSER_COLLAPSED_CHROME + - (deviceType === "pad" || hasSidebarTabBar ? 14 : 0) + + (!isProviderSubagent && (deviceType === "pad" || hasSidebarTabBar) ? 14 : 0) + composerBottomInset; const [collapsedUserInputRequestId, setCollapsedUserInputRequestId] = useState(null); From a36da663d3ef35113a3be85b20b65895e7ec82f6 Mon Sep 17 00:00:00 2001 From: maria-rcks Date: Tue, 27 Oct 2026 00:34:51 +0000 Subject: [PATCH 4/4] refactor(mobile): inline the composer tab sizing check --- apps/mobile/src/features/threads/ThreadComposer.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/mobile/src/features/threads/ThreadComposer.tsx b/apps/mobile/src/features/threads/ThreadComposer.tsx index 702dd7a73e908..df5aca19dec1a 100644 --- a/apps/mobile/src/features/threads/ThreadComposer.tsx +++ b/apps/mobile/src/features/threads/ThreadComposer.tsx @@ -562,8 +562,8 @@ export const ThreadComposer = function ThreadComposer(props: ThreadComposerProps const isVoiceInputPresented = voicePresentation.statusLabel !== null; const isExpanded = isFocused || settingsSheetPresentation.keepsComposerExpanded; const { setComposerEditing } = useAdaptiveWorkspaceLayout(); - const sidebarTabs = useSidebarWorkspaceTabs(); - const usesLargeControls = (Platform.OS === "ios" && Platform.isPad) || sidebarTabs === "picker"; + const usesLargeControls = + useSidebarWorkspaceTabs() === "picker" || (Platform.OS === "ios" && Platform.isPad); const [compactRowWidth, setCompactRowWidth] = useState(0); const compactAttachmentLimit = compactRowWidth >= 500 ? 3 : 1; const compactEditor = useCompactComposerEditor(bodyText, draftMessage);