History

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

Pavlo Trinko committed 3 months ago

Commit 6ae44b41 parent 4a2f8b05 files · +18 −7Browse files

Unified · Split

5 files
  1. apps/mobile/src/features/files/FileTreeBrowser.tsx +2 −1
  2. apps/mobile/src/features/review/ReviewSheet.tsx +5 −2
  3. apps/mobile/src/features/threads/ThreadDetailScreen.tsx +2 −1
  4. apps/mobile/src/features/threads/ThreadFeed.tsx +3 −2
  5. apps/mobile/src/lib/layoutMetrics.ts +6 −1
apps/mobile/src/features/files/FileTreeBrowser.tsx+2−1
@@ -8,6 +8,7 @@ import { AppText as Text } from "../../components/AppText"; · 7 unmodified lines
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: { · 109 unmodified lines
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"; · 38 unmodified lines
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({ · 232 unmodified lines
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"; · 56 unmodified lines
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 · 186 unmodified lines
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"; · 46 unmodified lines
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) { · 1343 unmodified lines
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) { · 6 unmodified lines
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;
1414 1415
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; · 4 unmodified lines
5export const IPAD_HOME_TITLE_OFFSET = 10;5export const IPAD_HOME_TITLE_OFFSET = 10;
6 6
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 */