authorgravatar for paul.trinko95@gmail.comPavlo Trinko <paul.trinko95@gmail.com> 2026-08-14 10:29:09+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-08-14 08:29:09+00:00
log6ae44b418a24dc021cf042cbb1e60ebeb47e160f
tree7a67bc947abca4ef3af6becd996fb4b29c036489
parent4a2f8b04bbce916be166fec96f33a7e1f0df4a9f
signature Signed by PGP key B5690EEEBB952194

refactor(mobile): name the iOS nav bar height fallback (#6589)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Julius Marminge <julius0216@outlook.com>

5 files changed, 18 insertions(+), 7 deletions(-)

apps/mobile/src/features/files/FileTreeBrowser.tsx+2-1
...@@ -8,6 +8,7 @@ import { AppText as Text } from "../../components/AppText";...@@ -8,6 +8,7 @@ import { AppText as Text } from "../../components/AppText";
8import { PierreEntryIcon } from "../../components/PierreEntryIcon";8import { PierreEntryIcon } from "../../components/PierreEntryIcon";
9import { cn } from "../../lib/cn";9import { cn } from "../../lib/cn";
10import { useThemeColor } from "../../lib/useThemeColor";10import { useThemeColor } from "../../lib/useThemeColor";
11import { IOS_NAV_BAR_HEIGHT } from "../../lib/layoutMetrics";
11import { NATIVE_LIQUID_GLASS_SUPPORTED } from "../../native/native-glass";12import { NATIVE_LIQUID_GLASS_SUPPORTED } from "../../native/native-glass";
12import {13import {
13 buildFileTree,14 buildFileTree,
...@@ -123,7 +124,7 @@ export function FileTreeBrowser(props: {...@@ -123,7 +124,7 @@ export function FileTreeBrowser(props: {
123 const insets = useSafeAreaInsets();124 const insets = useSafeAreaInsets();
124 // Native transparent-header height ≈ safe-area top + nav bar (~44). Matches the125 // Native transparent-header height ≈ safe-area top + nav bar (~44). Matches the
125 // observed adjustedContentInset bottom (~102) seen in the native trace.126 // observed adjustedContentInset bottom (~102) seen in the native trace.
126 const headerInset = NATIVE_LIQUID_GLASS_SUPPORTED ? insets.top + 44 : 0;127 const headerInset = NATIVE_LIQUID_GLASS_SUPPORTED ? insets.top + IOS_NAV_BAR_HEIGHT : 0;
127 const iconColor = String(useThemeColor("--color-icon-muted"));128 const iconColor = String(useThemeColor("--color-icon-muted"));
128 const { onPreviewFile, onSelectFile, selectedPath: controlledSelectedPath } = props;129 const { onPreviewFile, onSelectFile, selectedPath: controlledSelectedPath } = props;
129 const controlledSelectedPathRef = useRef(controlledSelectedPath);130 const controlledSelectedPathRef = useRef(controlledSelectedPath);
apps/mobile/src/features/review/ReviewSheet.tsx+5-2
...@@ -39,6 +39,7 @@ import { environmentCatalog } from "../../connection/catalog";...@@ -39,6 +39,7 @@ import { environmentCatalog } from "../../connection/catalog";
39import { useEnvironmentPresentation } from "../../state/presentation";39import { useEnvironmentPresentation } from "../../state/presentation";
40import { useAtomCommand } from "../../state/use-atom-command";40import { useAtomCommand } from "../../state/use-atom-command";
41import { useThemeColor } from "../../lib/useThemeColor";41import { useThemeColor } from "../../lib/useThemeColor";
42import { IOS_NAV_BAR_HEIGHT } from "../../lib/layoutMetrics";
42import { useThreadDraftForThread } from "../../state/use-thread-composer-state";43import { useThreadDraftForThread } from "../../state/use-thread-composer-state";
43import { EnvironmentConnectionNotice } from "../connection/EnvironmentConnectionNotice";44import { EnvironmentConnectionNotice } from "../connection/EnvironmentConnectionNotice";
44import {45import {
...@@ -277,9 +278,11 @@ function ReviewFileNavigator({...@@ -277,9 +278,11 @@ function ReviewFileNavigator({
277 // The nested native header is translucent; start the list below it so278 // The nested native header is translucent; start the list below it so
278 // the scroll-edge effect can sample the content (same treatment as279 // the scroll-edge effect can sample the content (same treatment as
279 // FileTreeBrowser in the Files pane).280 // FileTreeBrowser in the Files pane).
280 paddingTop: Platform.OS === "ios" ? insets.top + 44 + 8 : 8,281 paddingTop: Platform.OS === "ios" ? insets.top + IOS_NAV_BAR_HEIGHT + 8 : 8,
281 }}282 }}
282 scrollIndicatorInsets={Platform.OS === "ios" ? { top: insets.top + 44 } : undefined}283 scrollIndicatorInsets={
284 Platform.OS === "ios" ? { top: insets.top + IOS_NAV_BAR_HEIGHT } : undefined
285 }
283 renderItem={renderFile}286 renderItem={renderFile}
284 />287 />
285 );288 );
apps/mobile/src/features/threads/ThreadDetailScreen.tsx+2-1
...@@ -57,6 +57,7 @@ import type { ComposerEditorHandle } from "../../components/ComposerEditor";...@@ -57,6 +57,7 @@ import type { ComposerEditorHandle } from "../../components/ComposerEditor";
57import type { StatusTone } from "../../components/StatusPill";57import type { StatusTone } from "../../components/StatusPill";
58import type { DraftComposerImageAttachment } from "../../lib/composerImages";58import type { DraftComposerImageAttachment } from "../../lib/composerImages";
59import { CHAT_CONTENT_MAX_WIDTH, type LayoutVariant } from "../../lib/layout";59import { CHAT_CONTENT_MAX_WIDTH, type LayoutVariant } from "../../lib/layout";
60import { IOS_NAV_BAR_HEIGHT } from "../../lib/layoutMetrics";
60import { scopedThreadKey } from "../../lib/scopedEntities";61import { scopedThreadKey } from "../../lib/scopedEntities";
61import type {62import type {
62 PendingApproval,63 PendingApproval,
...@@ -249,7 +250,7 @@ export const ThreadDetailScreen = memo(function ThreadDetailScreen(props: Thread...@@ -249,7 +250,7 @@ export const ThreadDetailScreen = memo(function ThreadDetailScreen(props: Thread
249 }250 }
250 }, []);251 }, []);
251 const windowHeight = useWindowDimensions().height;252 const windowHeight = useWindowDimensions().height;
252 const navigationHeaderHeight = useContext(HeaderHeightContext) || insets.top + 44;253 const navigationHeaderHeight = useContext(HeaderHeightContext) || insets.top + IOS_NAV_BAR_HEIGHT;
253 const agentLabel = `${props.selectedThread.modelSelection.instanceId} agent`;254 const agentLabel = `${props.selectedThread.modelSelection.instanceId} agent`;
254 const selectedThreadKey = scopedThreadKey(props.environmentId, props.selectedThread.id);255 const selectedThreadKey = scopedThreadKey(props.environmentId, props.selectedThread.id);
255 const composerEditorRef = useRef<ComposerEditorHandle>(null);256 const composerEditorRef = useRef<ComposerEditorHandle>(null);
apps/mobile/src/features/threads/ThreadFeed.tsx+3-2
...@@ -47,6 +47,7 @@ import ImageViewing from "react-native-image-viewing";...@@ -47,6 +47,7 @@ import ImageViewing from "react-native-image-viewing";
47import { useSafeAreaInsets } from "react-native-safe-area-context";47import { useSafeAreaInsets } from "react-native-safe-area-context";
48import Animated, { FadeIn, FadeInUp, type SharedValue } from "react-native-reanimated";48import Animated, { FadeIn, FadeInUp, type SharedValue } from "react-native-reanimated";
49import { useThemeColor } from "../../lib/useThemeColor";49import { useThemeColor } from "../../lib/useThemeColor";
50import { IOS_NAV_BAR_HEIGHT } from "../../lib/layoutMetrics";
50import { useFontFamily } from "../../lib/useFontFamily";51import { useFontFamily } from "../../lib/useFontFamily";
51import { scopedThreadKey } from "../../lib/scopedEntities";52import { scopedThreadKey } from "../../lib/scopedEntities";
52import { copyTextWithHaptic } from "../../lib/copyTextWithHaptic";53import { copyTextWithHaptic } from "../../lib/copyTextWithHaptic";
...@@ -1396,7 +1397,7 @@ export const ThreadFeed = memo(function ThreadFeed(props: ThreadFeedProps) {...@@ -1396,7 +1397,7 @@ export const ThreadFeed = memo(function ThreadFeed(props: ThreadFeedProps) {
1396 const userBubbleMaxWidth = contentWidth * 0.85;1397 const userBubbleMaxWidth = contentWidth * 0.85;
1397 const reviewCommentBubbleWidth = Math.min(Math.max(280, contentWidth * 0.85), contentWidth);1398 const reviewCommentBubbleWidth = Math.min(Math.max(280, contentWidth * 0.85), contentWidth);
1398 const insets = useSafeAreaInsets();1399 const insets = useSafeAreaInsets();
1399 const topContentInset = props.contentTopInset ?? insets.top + 44;1400 const topContentInset = props.contentTopInset ?? insets.top + IOS_NAV_BAR_HEIGHT;
1400 const bottomContentInset = props.contentBottomInset ?? 18;1401 const bottomContentInset = props.contentBottomInset ?? 18;
1401 const usesNativeAutomaticInsets =1402 const usesNativeAutomaticInsets =
1402 props.usesAutomaticContentInsets === true && Platform.OS === "ios";1403 props.usesAutomaticContentInsets === true && Platform.OS === "ios";
...@@ -1409,7 +1410,7 @@ export const ThreadFeed = memo(function ThreadFeed(props: ThreadFeedProps) {...@@ -1409,7 +1410,7 @@ export const ThreadFeed = memo(function ThreadFeed(props: ThreadFeedProps) {
1409 // header-providing screen) and fall back to the standard iOS bar height.1410 // header-providing screen) and fall back to the standard iOS bar height.
1410 const navigationHeaderHeight = useContext(HeaderHeightContext);1411 const navigationHeaderHeight = useContext(HeaderHeightContext);
1411 const anchorTopInset = usesNativeAutomaticInsets1412 const anchorTopInset = usesNativeAutomaticInsets
1412 ? navigationHeaderHeight || insets.top + 441413 ? navigationHeaderHeight || insets.top + IOS_NAV_BAR_HEIGHT
1413 : topContentInset;1414 : topContentInset;
14141415
1415 const iconSubtleColor = useThemeColor("--color-icon-subtle");1416 const iconSubtleColor = useThemeColor("--color-icon-subtle");
apps/mobile/src/lib/layoutMetrics.ts+6-1
...@@ -5,7 +5,12 @@ export const HOME_HORIZONTAL_INSET = 20;...@@ -5,7 +5,12 @@ export const HOME_HORIZONTAL_INSET = 20;
5export const IPAD_HOME_TITLE_OFFSET = 10;5export const IPAD_HOME_TITLE_OFFSET = 10;
66
7/**7/**
8 * Height of the app's own header chrome below the safe-area inset, on every8 * Height of the native iOS navigation bar below the safe-area inset, used as
9 * a fallback when the measured HeaderHeightContext is unavailable.
10 */
11export const IOS_NAV_BAR_HEIGHT = 44;
12
13/* Height of the app's own header chrome below the safe-area inset, on every
9 * platform (matches the `min-h-12` AndroidScreenHeader). Distinct from the14 * platform (matches the `min-h-12` AndroidScreenHeader). Distinct from the
10 * 44pt native iOS navigation bar.15 * 44pt native iOS navigation bar.
11 */16 */