From 7f02dbbff3b152567a5786ce40741f2813e07b2d Mon Sep 17 00:00:00 2001 From: Andrew Bierman <94939237+andrew-bierman@users.noreply.github.com> Date: Sun, 26 Apr 2026 17:47:20 -0600 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=90=9B=20fix:=20add=20contentInsetAdj?= =?UTF-8?q?ustmentBehavior=3D"automatic"=20to=20all=20LargeTitleHeader=20s?= =?UTF-8?q?creens?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All 19 screens using LargeTitleHeader were missing this prop on their main scroll component, causing content to render behind the transparent native header on iOS. Fixes the overlap bug found on SeasonSuggestions. --- .claude/scheduled_tasks.lock | 1 + apps/expo/app/(app)/current-pack/[id].tsx | 1 + apps/expo/app/(app)/gear-inventory.tsx | 2 +- apps/expo/app/(app)/pack-categories/[id].tsx | 2 +- apps/expo/app/(app)/pack-stats/[id].tsx | 2 +- apps/expo/app/(app)/recent-packs.tsx | 2 +- apps/expo/app/(app)/shared-packs.tsx | 2 +- apps/expo/app/(app)/shopping-list.tsx | 2 +- apps/expo/app/(app)/trail-conditions.tsx | 1 + apps/expo/app/(app)/weather-alerts.tsx | 2 +- apps/expo/app/(app)/weight-analysis/[id].tsx | 1 + apps/expo/features/ai/screens/ReportedContentScreen.tsx | 1 + apps/expo/features/catalog/screens/CatalogItemsScreen.tsx | 1 + apps/expo/features/feed/screens/FeedScreen.tsx | 1 + apps/expo/features/guides/screens/GuidesListScreen.tsx | 1 + .../features/pack-templates/screens/PackTemplateListScreen.tsx | 1 + apps/expo/features/packs/screens/PackListScreen.tsx | 1 + apps/expo/features/trips/screens/TripListScreen.tsx | 1 + apps/expo/features/weather/screens/LocationsScreen.tsx | 1 + apps/expo/features/wildlife/screens/WildlifeScreen.tsx | 1 + 20 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 .claude/scheduled_tasks.lock diff --git a/.claude/scheduled_tasks.lock b/.claude/scheduled_tasks.lock new file mode 100644 index 0000000000..b1c5a73747 --- /dev/null +++ b/.claude/scheduled_tasks.lock @@ -0,0 +1 @@ +{"sessionId":"6cde7465-5bfc-4ba4-88ef-122130ee32fd","pid":83477,"acquiredAt":1776531548866} \ No newline at end of file diff --git a/apps/expo/app/(app)/current-pack/[id].tsx b/apps/expo/app/(app)/current-pack/[id].tsx index b7412516ca..161c92b34a 100644 --- a/apps/expo/app/(app)/current-pack/[id].tsx +++ b/apps/expo/app/(app)/current-pack/[id].tsx @@ -141,6 +141,7 @@ export default function CurrentPackScreen() { className="flex-1" contentContainerStyle={{ paddingBottom: 32 }} removeClippedSubviews={false} + contentInsetAdjustmentBehavior="automatic" > - + {t('packs.itemsInInventory', { count: items?.length })} diff --git a/apps/expo/app/(app)/pack-categories/[id].tsx b/apps/expo/app/(app)/pack-categories/[id].tsx index 4f8f97b771..e0699ae3bc 100644 --- a/apps/expo/app/(app)/pack-categories/[id].tsx +++ b/apps/expo/app/(app)/pack-categories/[id].tsx @@ -65,7 +65,7 @@ export default function PackCategoriesScreen() { <> {categories.length ? ( - + {t('packs.organizeGear')} diff --git a/apps/expo/app/(app)/pack-stats/[id].tsx b/apps/expo/app/(app)/pack-stats/[id].tsx index 85809d1af3..c2460fa50b 100644 --- a/apps/expo/app/(app)/pack-stats/[id].tsx +++ b/apps/expo/app/(app)/pack-stats/[id].tsx @@ -33,7 +33,7 @@ export default function PackStatsScreen() { {weightHistory || CATEGORY_DISTRIBUTION ? ( - + {/* Weight History Section */} {WEIGHT_HISTORY && ( diff --git a/apps/expo/app/(app)/recent-packs.tsx b/apps/expo/app/(app)/recent-packs.tsx index 8c0fc21734..e420436c33 100644 --- a/apps/expo/app/(app)/recent-packs.tsx +++ b/apps/expo/app/(app)/recent-packs.tsx @@ -61,7 +61,7 @@ export default function RecentPacksScreen() { {recentPacks.length ? ( - + {t('packs.recentlyUpdated')} diff --git a/apps/expo/app/(app)/shared-packs.tsx b/apps/expo/app/(app)/shared-packs.tsx index bc6132c563..c100b5b055 100644 --- a/apps/expo/app/(app)/shared-packs.tsx +++ b/apps/expo/app/(app)/shared-packs.tsx @@ -181,7 +181,7 @@ export default function SharedPacksScreen() { return ( <> - + {t('packs.collaborateOnPacks')} diff --git a/apps/expo/app/(app)/shopping-list.tsx b/apps/expo/app/(app)/shopping-list.tsx index f0f2c25381..da5e04ad42 100644 --- a/apps/expo/app/(app)/shopping-list.tsx +++ b/apps/expo/app/(app)/shopping-list.tsx @@ -170,7 +170,7 @@ export default function ShoppingListScreen() { return ( <> - + diff --git a/apps/expo/app/(app)/trail-conditions.tsx b/apps/expo/app/(app)/trail-conditions.tsx index dded885c76..5cb0b88261 100644 --- a/apps/expo/app/(app)/trail-conditions.tsx +++ b/apps/expo/app/(app)/trail-conditions.tsx @@ -186,6 +186,7 @@ export default function TrailConditionsScreen() { ListFooterComponent={listFooter} ListEmptyComponent={listEmptyComponent} contentContainerClassName="pb-4" + contentInsetAdjustmentBehavior="automatic" /> {/* Submit Report Modal */} diff --git a/apps/expo/app/(app)/weather-alerts.tsx b/apps/expo/app/(app)/weather-alerts.tsx index fffe578cb3..de72385ef2 100644 --- a/apps/expo/app/(app)/weather-alerts.tsx +++ b/apps/expo/app/(app)/weather-alerts.tsx @@ -135,7 +135,7 @@ export default function WeatherAlertsScreen() { return ( - + item.id.toString()} contentContainerClassName="p-4" + contentInsetAdjustmentBehavior="automatic" renderItem={({ item }) => ( diff --git a/apps/expo/features/catalog/screens/CatalogItemsScreen.tsx b/apps/expo/features/catalog/screens/CatalogItemsScreen.tsx index 4fe67890bf..e7a3dc89a9 100644 --- a/apps/expo/features/catalog/screens/CatalogItemsScreen.tsx +++ b/apps/expo/features/catalog/screens/CatalogItemsScreen.tsx @@ -223,6 +223,7 @@ function CatalogItemsScreen() { onEndReached={loadMore} onEndReachedThreshold={0.5} contentContainerStyle={{ flexGrow: 1, padding: 16 }} + contentInsetAdjustmentBehavior="automatic" ListFooterComponent={ <> diff --git a/apps/expo/features/feed/screens/FeedScreen.tsx b/apps/expo/features/feed/screens/FeedScreen.tsx index 0b50985786..43067d4019 100644 --- a/apps/expo/features/feed/screens/FeedScreen.tsx +++ b/apps/expo/features/feed/screens/FeedScreen.tsx @@ -106,6 +106,7 @@ export const FeedScreen = () => { renderItem={renderItem} keyExtractor={(item) => String(item.id)} contentContainerStyle={{ paddingHorizontal: 16, paddingTop: 8, paddingBottom: 24 }} + contentInsetAdjustmentBehavior="automatic" refreshControl={} onEndReached={handleLoadMore} onEndReachedThreshold={0.3} diff --git a/apps/expo/features/guides/screens/GuidesListScreen.tsx b/apps/expo/features/guides/screens/GuidesListScreen.tsx index 928a52746c..847b9a7538 100644 --- a/apps/expo/features/guides/screens/GuidesListScreen.tsx +++ b/apps/expo/features/guides/screens/GuidesListScreen.tsx @@ -216,6 +216,7 @@ export const GuidesListScreen = () => { renderItem={renderGuide} ListHeaderComponent={listHeader} contentContainerStyle={{ paddingHorizontal: 16, flexGrow: 1 }} + contentInsetAdjustmentBehavior="automatic" refreshControl={ item.id} + contentInsetAdjustmentBehavior="automatic" renderItem={({ item }) => ( diff --git a/apps/expo/features/packs/screens/PackListScreen.tsx b/apps/expo/features/packs/screens/PackListScreen.tsx index 5985ffcd80..6f5759ff20 100644 --- a/apps/expo/features/packs/screens/PackListScreen.tsx +++ b/apps/expo/features/packs/screens/PackListScreen.tsx @@ -219,6 +219,7 @@ export function PackListScreen() { data={filteredPacks} keyExtractor={(pack) => pack.id} stickyHeaderIndices={[0]} + contentInsetAdjustmentBehavior="automatic" renderItem={({ item: pack }) => ( trip.id} ListHeaderComponent={} + contentInsetAdjustmentBehavior="automatic" renderItem={({ item: trip }) => ( diff --git a/apps/expo/features/weather/screens/LocationsScreen.tsx b/apps/expo/features/weather/screens/LocationsScreen.tsx index 62db89a680..20e4bfc5ff 100644 --- a/apps/expo/features/weather/screens/LocationsScreen.tsx +++ b/apps/expo/features/weather/screens/LocationsScreen.tsx @@ -190,6 +190,7 @@ function LocationsScreen() { paddingBottom: insets.bottom + 16, flexGrow: showEmptyState ? 1 : undefined, }} + contentInsetAdjustmentBehavior="automatic" refreshControl={ handleHistoryItemPress(item)} /> )} contentContainerStyle={{ paddingBottom: 24 }} + contentInsetAdjustmentBehavior="automatic" /> ) : ( From 5bbe29281bc2a0908883b00e442b53e87f5be187 Mon Sep 17 00:00:00 2001 From: Andrew Bierman <94939237+andrew-bierman@users.noreply.github.com> Date: Sun, 26 Apr 2026 21:44:57 -0600 Subject: [PATCH 2/3] fix: remove redundant SafeAreaView top insets conflicting with contentInsetAdjustmentBehavior MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PackItemDetailScreen: edges={['bottom']} — regular stack header already offsets content - current-pack, weight-analysis, trail-conditions: strip manual paddingTop/insets since contentInsetAdjustmentBehavior=automatic handles nav bar offset --- .claude/scheduled_tasks.lock | 1 - apps/expo/app/(app)/current-pack/[id].tsx | 12 ++++-------- apps/expo/app/(app)/trail-conditions.tsx | 5 ++--- apps/expo/app/(app)/weight-analysis/[id].tsx | 12 ++++-------- .../features/packs/screens/PackItemDetailScreen.tsx | 8 ++++---- 5 files changed, 14 insertions(+), 24 deletions(-) delete mode 100644 .claude/scheduled_tasks.lock diff --git a/.claude/scheduled_tasks.lock b/.claude/scheduled_tasks.lock deleted file mode 100644 index b1c5a73747..0000000000 --- a/.claude/scheduled_tasks.lock +++ /dev/null @@ -1 +0,0 @@ -{"sessionId":"6cde7465-5bfc-4ba4-88ef-122130ee32fd","pid":83477,"acquiredAt":1776531548866} \ No newline at end of file diff --git a/apps/expo/app/(app)/current-pack/[id].tsx b/apps/expo/app/(app)/current-pack/[id].tsx index 161c92b34a..1289d4a8fc 100644 --- a/apps/expo/app/(app)/current-pack/[id].tsx +++ b/apps/expo/app/(app)/current-pack/[id].tsx @@ -15,8 +15,8 @@ import { getRelativeTime } from 'expo-app/lib/utils/getRelativeTime'; import type { PackItem } from 'expo-app/types'; import { useLocalSearchParams } from 'expo-router'; import type React from 'react'; -import { Platform, ScrollView, View } from 'react-native'; -import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context'; +import { ScrollView, View } from 'react-native'; +import { SafeAreaView } from 'react-native-safe-area-context'; function WeightCard({ title, @@ -132,10 +132,9 @@ export default function CurrentPackScreen() { const pack = usePackDetailsFromStore(params.id as string); const uniqueCategories = computeCategorySummaries(pack); - const insets = useSafeAreaInsets(); return ( - + - + diff --git a/apps/expo/app/(app)/trail-conditions.tsx b/apps/expo/app/(app)/trail-conditions.tsx index 5cb0b88261..244c35f623 100644 --- a/apps/expo/app/(app)/trail-conditions.tsx +++ b/apps/expo/app/(app)/trail-conditions.tsx @@ -7,7 +7,7 @@ import type { TrailConditionReport, TrailSurface } from 'expo-app/features/trail import { useTranslation } from 'expo-app/lib/hooks/useTranslation'; import { useMemo, useState } from 'react'; import { FlatList, Modal, Pressable, ScrollView, View } from 'react-native'; -import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context'; +import { SafeAreaView } from 'react-native-safe-area-context'; type SurfaceFilter = TrailSurface | 'all'; @@ -40,7 +40,6 @@ export default function TrailConditionsScreen() { const [selectedSurface, setSelectedSurface] = useState('all'); const { data: reports, isLoading, error } = useTrailConditionReports(); const { t } = useTranslation(); - const insets = useSafeAreaInsets(); const SURFACE_FILTERS: FilterItem[] = useMemo( () => [ @@ -160,7 +159,7 @@ export default function TrailConditionsScreen() { ); return ( - + ( diff --git a/apps/expo/app/(app)/weight-analysis/[id].tsx b/apps/expo/app/(app)/weight-analysis/[id].tsx index fa4da289c1..1027fa5bce 100644 --- a/apps/expo/app/(app)/weight-analysis/[id].tsx +++ b/apps/expo/app/(app)/weight-analysis/[id].tsx @@ -6,8 +6,8 @@ import { usePackWeightAnalysis } from 'expo-app/features/packs/hooks/usePackWeig import { cn } from 'expo-app/lib/cn'; import { useTranslation } from 'expo-app/lib/hooks/useTranslation'; import { useLocalSearchParams } from 'expo-router'; -import { Platform, ScrollView, View } from 'react-native'; -import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context'; +import { ScrollView, View } from 'react-native'; +import { SafeAreaView } from 'react-native-safe-area-context'; function WeightCard({ title, @@ -45,10 +45,9 @@ export default function WeightAnalysisScreen() { const { data, items } = usePackWeightAnalysis(packId as string); const preferredWeightUnit = userStore.preferredWeightUnit.peek() ?? 'g'; - const insets = useSafeAreaInsets(); return ( - + - + + @@ -60,7 +60,7 @@ export function ItemDetailScreen() { // Error state for non-owned packs if (!isOwnedByUser && isError) { return ( - + @@ -86,7 +86,7 @@ export function ItemDetailScreen() { if (!isDefined(item)) { return ( - + @@ -134,7 +134,7 @@ export function ItemDetailScreen() { }; return ( - + From 568962b78f274076bbae4ba88ed1feecb3da4be6 Mon Sep 17 00:00:00 2001 From: Ibrahim Isa Jajere Date: Tue, 28 Apr 2026 12:03:07 +0100 Subject: [PATCH 3/3] fix(expo): handle Android extra padding, bottom insets and iOS hidden / overlapping header in multiple screens --- apps/expo/app/(app)/current-pack/[id].tsx | 2 +- apps/expo/app/(app)/gear-inventory.tsx | 2 +- apps/expo/app/(app)/pack-categories/[id].tsx | 2 +- apps/expo/app/(app)/pack-stats/[id].tsx | 5 +- apps/expo/app/(app)/recent-packs.tsx | 5 +- apps/expo/app/(app)/shared-packs.tsx | 5 +- apps/expo/app/(app)/shopping-list.tsx | 5 +- apps/expo/app/(app)/trail-conditions.tsx | 2 +- apps/expo/app/(app)/weather-alerts.tsx | 2 +- apps/expo/app/(app)/weight-analysis/[id].tsx | 2 +- .../LargeTitleHeaderOverlapFixIOS.tsx | 9 +- .../ai/screens/ReportedContentScreen.tsx | 252 +++++++++--------- .../packs/screens/PackDetailScreen.tsx | 2 +- .../features/packs/screens/PackListScreen.tsx | 217 +++++++-------- .../features/trips/screens/TripListScreen.tsx | 5 +- .../weather/screens/LocationsScreen.tsx | 238 +++++++++-------- 16 files changed, 380 insertions(+), 375 deletions(-) diff --git a/apps/expo/app/(app)/current-pack/[id].tsx b/apps/expo/app/(app)/current-pack/[id].tsx index 1289d4a8fc..db114c3fe7 100644 --- a/apps/expo/app/(app)/current-pack/[id].tsx +++ b/apps/expo/app/(app)/current-pack/[id].tsx @@ -134,7 +134,7 @@ export default function CurrentPackScreen() { const uniqueCategories = computeCategorySummaries(pack); return ( - + + diff --git a/apps/expo/app/(app)/pack-categories/[id].tsx b/apps/expo/app/(app)/pack-categories/[id].tsx index e0699ae3bc..4f8f97b771 100644 --- a/apps/expo/app/(app)/pack-categories/[id].tsx +++ b/apps/expo/app/(app)/pack-categories/[id].tsx @@ -65,7 +65,7 @@ export default function PackCategoriesScreen() { <> {categories.length ? ( - + {t('packs.organizeGear')} diff --git a/apps/expo/app/(app)/pack-stats/[id].tsx b/apps/expo/app/(app)/pack-stats/[id].tsx index c2460fa50b..3277f6d134 100644 --- a/apps/expo/app/(app)/pack-stats/[id].tsx +++ b/apps/expo/app/(app)/pack-stats/[id].tsx @@ -7,6 +7,7 @@ import { computeCategorySummaries } from 'expo-app/features/packs/utils'; import { useTranslation } from 'expo-app/lib/hooks/useTranslation'; import { useLocalSearchParams } from 'expo-router'; import { ScrollView, View } from 'react-native'; +import { SafeAreaView } from 'react-native-safe-area-context'; export default function PackStatsScreen() { const params = useLocalSearchParams(); @@ -30,7 +31,7 @@ export default function PackStatsScreen() { })); return ( - + {weightHistory || CATEGORY_DISTRIBUTION ? ( @@ -157,6 +158,6 @@ export default function PackStatsScreen() { {t('packs.noStatsAvailable')} )} - + ); } diff --git a/apps/expo/app/(app)/recent-packs.tsx b/apps/expo/app/(app)/recent-packs.tsx index e420436c33..20fa2db13a 100644 --- a/apps/expo/app/(app)/recent-packs.tsx +++ b/apps/expo/app/(app)/recent-packs.tsx @@ -6,6 +6,7 @@ import { useColorScheme } from 'expo-app/lib/hooks/useColorScheme'; import { useTranslation } from 'expo-app/lib/hooks/useTranslation'; import { getRelativeTime } from 'expo-app/lib/utils/getRelativeTime'; import { Image, ScrollView, View } from 'react-native'; +import { SafeAreaView } from 'react-native-safe-area-context'; function RecentPackCard({ pack }: { pack: Pack }) { const { colors } = useColorScheme(); @@ -58,7 +59,7 @@ export default function RecentPacksScreen() { const { t } = useTranslation(); return ( - + {recentPacks.length ? ( @@ -81,6 +82,6 @@ export default function RecentPacksScreen() { )} - + ); } diff --git a/apps/expo/app/(app)/shared-packs.tsx b/apps/expo/app/(app)/shared-packs.tsx index c100b5b055..76ab6cf6ed 100644 --- a/apps/expo/app/(app)/shared-packs.tsx +++ b/apps/expo/app/(app)/shared-packs.tsx @@ -8,6 +8,7 @@ import { import { cn } from 'expo-app/lib/cn'; import { useTranslation } from 'expo-app/lib/hooks/useTranslation'; import { ScrollView, View } from 'react-native'; +import { SafeAreaView } from 'react-native-safe-area-context'; // Mock data for shared packs const SHARED_PACKS = [ @@ -179,7 +180,7 @@ function SharedPackCard({ pack }: { pack: (typeof SHARED_PACKS)[0] }) { export default function SharedPacksScreen() { const { t } = useTranslation(); return ( - <> + @@ -210,6 +211,6 @@ export default function SharedPacksScreen() { {t('packs.sharingBenefit3')} - + ); } diff --git a/apps/expo/app/(app)/shopping-list.tsx b/apps/expo/app/(app)/shopping-list.tsx index da5e04ad42..931afdd7e4 100644 --- a/apps/expo/app/(app)/shopping-list.tsx +++ b/apps/expo/app/(app)/shopping-list.tsx @@ -8,6 +8,7 @@ import { useTranslation } from 'expo-app/lib/hooks/useTranslation'; import type { TranslationKeys } from 'expo-app/lib/i18n/types'; import { useState } from 'react'; import { Pressable, ScrollView, View } from 'react-native'; +import { SafeAreaView } from 'react-native-safe-area-context'; // Mock data for shopping list const SHOPPING_LIST = [ @@ -168,7 +169,7 @@ export default function ShoppingListScreen() { }); return ( - <> + @@ -251,6 +252,6 @@ export default function ShoppingListScreen() { • Compare prices across multiple retailers before purchasing - + ); } diff --git a/apps/expo/app/(app)/trail-conditions.tsx b/apps/expo/app/(app)/trail-conditions.tsx index 244c35f623..984a7cf2f3 100644 --- a/apps/expo/app/(app)/trail-conditions.tsx +++ b/apps/expo/app/(app)/trail-conditions.tsx @@ -159,7 +159,7 @@ export default function TrailConditionsScreen() { ); return ( - + ( diff --git a/apps/expo/app/(app)/weather-alerts.tsx b/apps/expo/app/(app)/weather-alerts.tsx index de72385ef2..c02838c9a4 100644 --- a/apps/expo/app/(app)/weather-alerts.tsx +++ b/apps/expo/app/(app)/weather-alerts.tsx @@ -133,7 +133,7 @@ export default function WeatherAlertsScreen() { const { alerts, loading, error, activeLocation } = useWeatherAlerts(); return ( - + diff --git a/apps/expo/app/(app)/weight-analysis/[id].tsx b/apps/expo/app/(app)/weight-analysis/[id].tsx index 1027fa5bce..01978d9fd1 100644 --- a/apps/expo/app/(app)/weight-analysis/[id].tsx +++ b/apps/expo/app/(app)/weight-analysis/[id].tsx @@ -47,7 +47,7 @@ export default function WeightAnalysisScreen() { const preferredWeightUnit = userStore.preferredWeightUnit.peek() ?? 'g'; return ( - + { if (Platform.OS === 'android') { @@ -10,14 +9,8 @@ export const LargeTitleHeaderOverlapFixIOS = ({ children }: { children?: React.R } } - const insets = useSafeAreaInsets(); - return ( - + {children} {!children && } diff --git a/apps/expo/features/ai/screens/ReportedContentScreen.tsx b/apps/expo/features/ai/screens/ReportedContentScreen.tsx index 56ced1108e..b7e98df99d 100644 --- a/apps/expo/features/ai/screens/ReportedContentScreen.tsx +++ b/apps/expo/features/ai/screens/ReportedContentScreen.tsx @@ -34,145 +34,147 @@ export default function ReportedContentScreen() { - - setSelectedFilter('pending')} - /> - setSelectedFilter('reviewed')} - /> - setSelectedFilter('dismissed')} - /> - setSelectedFilter('all')} - /> - + item.id.toString()} + contentContainerClassName="p-4" + contentInsetAdjustmentBehavior="automatic" + ListHeaderComponent={ + + setSelectedFilter('pending')} + /> + setSelectedFilter('reviewed')} + /> + setSelectedFilter('dismissed')} + /> + setSelectedFilter('all')} + /> + + } + ListEmptyComponent={ + isLoading ? ( + + + + ) : error ? ( + + + {t('ai.reportedContent.errorLoading')} + + + ) : ( + + + + {t('ai.reportedContent.noReportsFound')} + + + ) + } + renderItem={({ item }) => ( + + + {item.user.firstName} + + {new Date(item.createdAt).toLocaleDateString()} + + - {isLoading ? ( - - - - ) : error ? ( - - - {t('ai.reportedContent.errorLoading')} - - - ) : filteredData?.length === 0 ? ( - - - - {t('ai.reportedContent.noReportsFound')} - - - ) : ( - item.id.toString()} - contentContainerClassName="p-4" - contentInsetAdjustmentBehavior="automatic" - renderItem={({ item }) => ( - - - {item.user.firstName} - - {new Date(item.createdAt).toLocaleDateString()} + {/* Report reason badge */} + + + + {t( + reportReasonTranslationKeys[ + item.reason as keyof typeof reportReasonTranslationKeys + ], + )} + - {/* Report reason badge */} - - - - {t( - reportReasonTranslationKeys[ - item.reason as keyof typeof reportReasonTranslationKeys - ], - )} - - + {/* User Query Section */} + + + {t('ai.reportedContent.userQuery')} + + + {item.userQuery} + - {/* User Query Section */} - - - {t('ai.reportedContent.userQuery')} - - - {item.userQuery} - + {/* AI Response Section */} + + + {t('ai.reportedContent.aiResponse')} + + + {item.aiResponse} + - {/* AI Response Section */} + {/* User Comment Section - only show if there is a comment */} + {item.userComment && ( - {t('ai.reportedContent.aiResponse')} + {t('ai.reportedContent.userComment')} - - {item.aiResponse} - - - - {/* User Comment Section - only show if there is a comment */} - {item.userComment && ( - - - {t('ai.reportedContent.userComment')} + + + {item.userComment} - - - {item.userComment} - - - )} + + )} - {item.status === 'pending' ? ( - - - - - ) : ( - - - {item.status === 'resolved' - ? t('ai.reportedContent.resolved') - : t('ai.reportedContent.dismissed')} - - - )} - - )} - /> - )} + {item.status === 'pending' ? ( + + + + + ) : ( + + + {item.status === 'resolved' + ? t('ai.reportedContent.resolved') + : t('ai.reportedContent.dismissed')} + + + )} + + )} + /> ); } diff --git a/apps/expo/features/packs/screens/PackDetailScreen.tsx b/apps/expo/features/packs/screens/PackDetailScreen.tsx index 0ed7252c7f..dcb9fe8757 100644 --- a/apps/expo/features/packs/screens/PackDetailScreen.tsx +++ b/apps/expo/features/packs/screens/PackDetailScreen.tsx @@ -453,7 +453,7 @@ export function PackDetailScreen() { } return ( - + {pack.image && ( diff --git a/apps/expo/features/packs/screens/PackListScreen.tsx b/apps/expo/features/packs/screens/PackListScreen.tsx index 6f5759ff20..0236d0c2b2 100644 --- a/apps/expo/features/packs/screens/PackListScreen.tsx +++ b/apps/expo/features/packs/screens/PackListScreen.tsx @@ -30,6 +30,7 @@ import { TouchableOpacity, View, } from 'react-native'; +import { SafeAreaView } from 'react-native-safe-area-context'; import { useAllPacks } from '../hooks/useAllPacks'; import { usePacks } from '../hooks/usePacks'; import type { Pack, PackCategory, PackInStore } from '../types'; @@ -186,118 +187,120 @@ export function PackListScreen() { }; return ( - - - {searchValue ? ( - - ) : ( - - {t('packs.searchPacks')} + + + + {searchValue ? ( + + ) : ( + + {t('packs.searchPacks')} + + )} + + ), + }} + rightView={() => } + /> + + pack.id} + stickyHeaderIndices={[0]} + contentInsetAdjustmentBehavior="automatic" + renderItem={({ item: pack }) => ( + + + + )} + refreshControl={ + selectedTypeIndex === ALL_PACKS_INDEX ? ( + + ) : undefined + } + ListHeaderComponent={ + + {!isAuthenticated && } + {isAuthenticated && ( + + { + setSelectedTypeIndex(index); + }} + /> )} - - ), - }} - rightView={() => } - /> - - pack.id} - stickyHeaderIndices={[0]} - contentInsetAdjustmentBehavior="automatic" - renderItem={({ item: pack }) => ( - - - - )} - refreshControl={ - selectedTypeIndex === ALL_PACKS_INDEX ? ( - - ) : undefined - } - ListHeaderComponent={ - - {!isAuthenticated && } - {isAuthenticated && ( - - { - setSelectedTypeIndex(index); - }} - /> + + + {filterOptions.map(renderFilterChip)} + - )} - - - {filterOptions.map(renderFilterChip)} - + {selectedTypeIndex === USER_PACKS_INDEX && ( + + + {filteredPacks?.length || 0} {filteredPacks?.length === 1 ? 'pack' : 'packs'} + + + )} - {selectedTypeIndex === USER_PACKS_INDEX && ( - - - {filteredPacks?.length || 0} {filteredPacks?.length === 1 ? 'pack' : 'packs'} + } + ListEmptyComponent={ + selectedTypeIndex === ALL_PACKS_INDEX ? ( + renderAllPacksEmptyState() + ) : ( + + + + + + {t('packs.noPacksFound')} - - )} - - } - ListEmptyComponent={ - selectedTypeIndex === ALL_PACKS_INDEX ? ( - renderAllPacksEmptyState() - ) : ( - - - - - - {t('packs.noPacksFound')} - - - {activeFilter === 'all' - ? "You haven't created or found any public packs yet." - : `You don't have any ${activeFilter} packs.`} - - - - {t('packs.createNewPack')} + + {activeFilter === 'all' + ? "You haven't created or found any public packs yet." + : `You don't have any ${activeFilter} packs.`} - - - ) - } - ListFooterComponent={} - contentContainerStyle={{ flexGrow: 1 }} - /> - + + + {t('packs.createNewPack')} + + + + ) + } + ListFooterComponent={} + contentContainerStyle={{ flexGrow: 1 }} + /> + + ); } diff --git a/apps/expo/features/trips/screens/TripListScreen.tsx b/apps/expo/features/trips/screens/TripListScreen.tsx index c1819ec677..0eb9b8d38a 100644 --- a/apps/expo/features/trips/screens/TripListScreen.tsx +++ b/apps/expo/features/trips/screens/TripListScreen.tsx @@ -9,6 +9,7 @@ import { asNonNullableRef } from 'expo-app/lib/utils/asNonNullableRef'; import { Link, useRouter } from 'expo-router'; import { useCallback, useMemo, useRef, useState } from 'react'; import { FlatList, Pressable, ScrollView, Text, TouchableOpacity, View } from 'react-native'; +import { SafeAreaView } from 'react-native-safe-area-context'; import { TripCard } from '../components/TripCard'; import { useTrips } from '../hooks'; import type { Trip } from '../types'; @@ -148,7 +149,7 @@ export function TripsListScreen() { }; return ( - <> + } contentContainerStyle={{ flexGrow: 1 }} /> - + ); } diff --git a/apps/expo/features/weather/screens/LocationsScreen.tsx b/apps/expo/features/weather/screens/LocationsScreen.tsx index 20e4bfc5ff..1c48d033b2 100644 --- a/apps/expo/features/weather/screens/LocationsScreen.tsx +++ b/apps/expo/features/weather/screens/LocationsScreen.tsx @@ -1,5 +1,6 @@ import { Button, LargeTitleHeader, Text } from '@packrat/ui/nativewindui'; import { Icon } from 'expo-app/components/Icon'; +import { LargeTitleHeaderOverlapFixIOS } from 'expo-app/components/LargeTitleHeaderOverlapFixIOS'; import { SearchInput } from 'expo-app/components/SearchInput'; import { withAuthWall } from 'expo-app/features/auth/hocs'; import { useColorScheme } from 'expo-app/lib/hooks/useColorScheme'; @@ -11,7 +12,6 @@ import { ActivityIndicator, Alert, Keyboard, - Platform, Pressable, RefreshControl, ScrollView, @@ -117,134 +117,136 @@ function LocationsScreen() { const showLocationsList = filteredLocations.length > 0; return ( - - ( - - - - )} - /> - - - setIsSearchFocused(true)} - onBlur={() => { - // Only unfocus if search is empty - if (searchQuery.length === 0) { - setIsSearchFocused(false); - } - }} + + + ( + + + + )} /> - - - {showNoSearchResults && ( - - - {t('weather.searchResults')} - - - - - {t('weather.noLocationsMatch', { query: searchQuery })} + + + setIsSearchFocused(true)} + onBlur={() => { + // Only unfocus if search is empty + if (searchQuery.length === 0) { + setIsSearchFocused(false); + } + }} + /> + + + {showNoSearchResults && ( + + + {t('weather.searchResults')} - - - {t('weather.clearSearch')} - - - {t('weather.addNewLocation')} - + + + + {t('weather.noLocationsMatch', { query: searchQuery })} + + + + {t('weather.clearSearch')} + + + {t('weather.addNewLocation')} + + + + )} + + {isLoading ? ( + + + {t('weather.loadingWeatherData')} - - )} + ) : ( + + } + keyboardShouldPersistTaps="handled" + > + {showLocationsList && ( + <> + {showSearchResults && ( + + + {filteredLocations.length}{' '} + {filteredLocations.length === 1 ? t('weather.result') : t('weather.results')} + + + )} - {isLoading ? ( - - - {t('weather.loadingWeatherData')} - - ) : ( - - } - keyboardShouldPersistTaps="handled" - > - {showLocationsList && ( - <> - {showSearchResults && ( - - {filteredLocations.length}{' '} - {filteredLocations.length === 1 ? t('weather.result') : t('weather.results')} + + {t('weather.longPressForOptions')} - )} - - - {t('weather.longPressForOptions')} + {filteredLocations.map((location) => ( + handleLocationPress(location.id)} + onSetActive={() => handleSetActive(location.id)} + onRemove={() => handleRemoveLocation(location.id)} + /> + ))} + + )} + + {showEmptyState && ( + + + + {t('weather.noSavedLocations')} + + + {t('weather.noSavedLocationsDesc')} + - - {filteredLocations.map((location) => ( - handleLocationPress(location.id)} - onSetActive={() => handleSetActive(location.id)} - onRemove={() => handleRemoveLocation(location.id)} - /> - ))} - - )} - - {showEmptyState && ( - - - - {t('weather.noSavedLocations')} - - - {t('weather.noSavedLocationsDesc')} - - - - )} - - )} + )} + + )} + ); }