Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/expo/app/(app)/ai-chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as Burnt from 'burnt';
import { fetch as expoFetch } from 'expo/fetch';
import { AiChatHeader } from 'expo-app/components/ai-chatHeader';
import { Icon } from 'expo-app/components/Icon';
import { TextInput } from 'expo-app/components/TextInput';
import { featureFlags } from 'expo-app/config';
import { aiModeAtom, localModelStatusAtom } from 'expo-app/features/ai/atoms/aiModeAtoms';
import {
Expand Down Expand Up @@ -34,7 +35,6 @@ import {
type NativeSyntheticEvent,
Platform,
ScrollView,
TextInput,
type TextInputContentSizeChangeEventData,
type TextStyle,
TouchableOpacity,
Expand Down
2 changes: 1 addition & 1 deletion apps/expo/app/(app)/messages/chat.android.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import { Portal } from '@rn-primitives/portal';
import { FlashList } from '@shopify/flash-list';
import { Icon } from 'expo-app/components/Icon';
import { TextInput } from 'expo-app/components/TextInput';
import { cn } from 'expo-app/lib/cn';
import { useColorScheme } from 'expo-app/lib/hooks/useColorScheme';
import { router, Stack } from 'expo-router';
Expand All @@ -19,7 +20,6 @@ import {
type NativeSyntheticEvent,
Platform,
Pressable,
TextInput,
type TextInputContentSizeChangeEventData,
type TextStyle,
View,
Expand Down
3 changes: 2 additions & 1 deletion apps/expo/app/(app)/messages/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
} from '@packrat/ui/nativewindui';
import { FlashList } from '@shopify/flash-list';
import { Icon } from 'expo-app/components/Icon';
import { TextInput } from 'expo-app/components/TextInput';
import { cn } from 'expo-app/lib/cn';
import { useColorScheme } from 'expo-app/lib/hooks/useColorScheme';
import { BlurView } from 'expo-blur';
Expand All @@ -21,7 +22,6 @@ import {
type NativeSyntheticEvent,
Platform,
Pressable,
TextInput,
type TextInputContentSizeChangeEventData,
type TextStyle,
View,
Expand Down Expand Up @@ -354,6 +354,7 @@ function ChatBubble({
}) {
const contextMenuRef = React.useRef<ContextMenuMethods>(null);
const contextMenuRef2 = React.useRef<ContextMenuMethods>(null);

const { colors } = useColorScheme();
const rootStyle = useAnimatedStyle(() => {
return {
Expand Down
13 changes: 0 additions & 13 deletions apps/expo/app/(app)/textinputdebug.tsx

This file was deleted.

3 changes: 2 additions & 1 deletion apps/expo/app/(app)/trip/location-search.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { clientEnvs } from '@packrat/env/expo-client';
import { ActivityIndicator, Button, SearchInput } from '@packrat/ui/nativewindui';
import { ActivityIndicator, Button } from '@packrat/ui/nativewindui';
import { SearchInput } from 'expo-app/components/SearchInput';
import { useTranslation } from 'expo-app/lib/hooks/useTranslation';
import Constants from 'expo-constants';
import { useRouter } from 'expo-router';
Expand Down
5 changes: 5 additions & 0 deletions apps/expo/app/auth/one-time-password.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { ActivityIndicator, AlertAnchor, Button, Text, TextField } from '@packra
import { useHeaderHeight } from '@react-navigation/elements';
import { useAuthActions } from 'expo-app/features/auth/hooks/useAuthActions';
import { useColorScheme } from 'expo-app/lib/hooks/useColorScheme';
import { useKeyboardHideBlur } from 'expo-app/lib/hooks/useKeyboardHideBlur';
import { useTranslation } from 'expo-app/lib/hooks/useTranslation';
import { asNonNullableRef } from 'expo-app/lib/utils/asNonNullableRef';
import { router, Stack, useLocalSearchParams } from 'expo-router';
import * as React from 'react';
import {
Expand Down Expand Up @@ -252,6 +254,9 @@ function OTPField({
const { colors } = useColorScheme();
const inputRef = React.useRef<TextInput>(null);

// Apply keyboard hide blur fix
useKeyboardHideBlur(asNonNullableRef(inputRef));

function onKeyPress({ nativeEvent }: NativeSyntheticEvent<TextInputKeyPressEventData>) {
if (nativeEvent.key === 'Backspace' && value === '') {
KeyboardController.setFocusTo('prev');
Expand Down
29 changes: 29 additions & 0 deletions apps/expo/components/SearchInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { assertPresent } from '@packrat/guards';
import { SearchInput as NativeWindUISearchInput } from '@packrat/ui/nativewindui';
import { useKeyboardHideBlur } from 'expo-app/lib/hooks/useKeyboardHideBlur';
import { asNonNullableRef } from 'expo-app/lib/utils/asNonNullableRef';
import { forwardRef, useImperativeHandle, useRef } from 'react';

/**
* Enhanced SearchInput component that automatically handles keyboard hide blur fix.
* Drop-in replacement for NativeWindUI's SearchInput with built-in Android keyboard behavior fix.
*/
export const SearchInput = forwardRef<
React.ComponentRef<typeof NativeWindUISearchInput>,
React.ComponentProps<typeof NativeWindUISearchInput>
>((props, ref) => {
const searchInputRef = useRef<React.ComponentRef<typeof NativeWindUISearchInput>>(null);

// Apply keyboard hide blur fix
useKeyboardHideBlur(asNonNullableRef(searchInputRef));

// Forward ref methods to the internal ref
useImperativeHandle(ref, () => {
assertPresent(searchInputRef.current);
return searchInputRef.current;
}, []);

return <NativeWindUISearchInput ref={searchInputRef} {...props} />;
});

SearchInput.displayName = 'SearchInput';
26 changes: 26 additions & 0 deletions apps/expo/components/TextInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { assertPresent } from '@packrat/guards';
import { useKeyboardHideBlur } from 'expo-app/lib/hooks/useKeyboardHideBlur';
import { asNonNullableRef } from 'expo-app/lib/utils/asNonNullableRef';
import { forwardRef, useImperativeHandle, useRef } from 'react';
import { TextInput as RNTextInput, type TextInputProps } from 'react-native';

/**
* Enhanced TextInput component that automatically handles keyboard hide blur fix.
* Drop-in replacement for React Native's TextInput with built-in Android keyboard behavior fix.
*/
export const TextInput = forwardRef<RNTextInput, TextInputProps>((props, ref) => {
const textInputRef = useRef<RNTextInput>(null);

// Apply keyboard hide blur fix
useKeyboardHideBlur(asNonNullableRef(textInputRef));

// Forward ref methods to the internal ref
useImperativeHandle(ref, () => {
assertPresent(textInputRef.current);
return textInputRef.current;
}, []);

return <RNTextInput ref={textInputRef} {...props} />;
});

TextInput.displayName = 'TextInput';
8 changes: 6 additions & 2 deletions apps/expo/features/ai-packs/screens/AIPacksScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,21 @@ import {
} from '@packrat/ui/nativewindui';
import { useForm } from '@tanstack/react-form';
import { Icon } from 'expo-app/components/Icon';
import { TextInput } from 'expo-app/components/TextInput';
import { PackCard } from 'expo-app/features/packs/components/PackCard';
import { useColorScheme } from 'expo-app/lib/hooks/useColorScheme';
import { useTranslation } from 'expo-app/lib/hooks/useTranslation';
import { useRouter } from 'expo-router';
import { useRef, useState } from 'react';
import { Modal, Platform, ScrollView, TextInput, TouchableOpacity, View } from 'react-native';
import { Modal, Platform, ScrollView, TouchableOpacity, View } from 'react-native';
import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';
import { useGeneratePacks } from '../hooks/useGeneratedPacks';

export function AIPacksScreen() {
const { colors } = useColorScheme();
const { t } = useTranslation();
const alertRef = useRef<AlertMethods>(null);

const { mutateAsync: generatePacks, isPending, generatedPacksFromStore } = useGeneratePacks();
const [packsModalVisible, setPacksModalVisible] = useState(false);
const router = useRouter();
Expand Down Expand Up @@ -61,7 +63,9 @@ export function AIPacksScreen() {
const handleGeneratePacks = () => {
alertRef.current?.alert({
title: t('ai.generatePacksButton'),
message: t('ai.generatePacksConfirm', { count: form.getFieldValue('count') }),
message: t('ai.generatePacksConfirm', {
count: form.getFieldValue('count'),
}),
materialIcon: { name: 'information-outline', color: colors.primary },
buttons: [
{ text: t('common.cancel'), style: 'cancel' },
Expand Down
4 changes: 3 additions & 1 deletion apps/expo/features/ai/components/ReportModal.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Button, Text } from '@packrat/ui/nativewindui';
import { Icon } from 'expo-app/components/Icon';
import { TextInput } from 'expo-app/components/TextInput';
import { cn } from 'expo-app/lib/cn';
import { useColorScheme } from 'expo-app/lib/hooks/useColorScheme';
import { useTranslation } from 'expo-app/lib/hooks/useTranslation';
import { useState } from 'react';
import { Modal, ScrollView, TextInput, TouchableOpacity, View } from 'react-native';
import { Modal, ScrollView, TouchableOpacity, View } from 'react-native';
import { KeyboardStickyView } from 'react-native-keyboard-controller';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useReportContent } from '../hooks/useReportContent';
Expand Down Expand Up @@ -35,6 +36,7 @@ export function ReportModal({
const { t } = useTranslation();
const [selectedReason, setSelectedReason] = useState<ReportReason | null>(null);
const [comment, setComment] = useState('');

const reportContentMutation = useReportContent();
const insets = useSafeAreaInsets();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Button, SearchInput, Text } from '@packrat/ui/nativewindui';
import { Button, Text } from '@packrat/ui/nativewindui';
import { searchValueAtom } from 'expo-app/atoms/itemListAtoms';
import { CategoriesFilter } from 'expo-app/components/CategoriesFilter';
import { Icon } from 'expo-app/components/Icon';
import { SearchInput } from 'expo-app/components/SearchInput';
import { HorizontalCatalogItemCard } from 'expo-app/features/packs/components/HorizontalCatalogItemCard';
import { useColorScheme } from 'expo-app/lib/hooks/useColorScheme';
import { useTranslation } from 'expo-app/lib/hooks/useTranslation';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Button, Text } from '@packrat/ui/nativewindui';
import { useQueryClient } from '@tanstack/react-query';
import * as Burnt from 'burnt';
import { Icon } from 'expo-app/components/Icon';
import { TextInput } from 'expo-app/components/TextInput';
import { useCreatePackItem, usePackDetailsFromStore } from 'expo-app/features/packs';
import { useColorScheme } from 'expo-app/lib/hooks/useColorScheme';
import { useTranslation } from 'expo-app/lib/hooks/useTranslation';
Expand All @@ -17,7 +18,6 @@ import {
Platform,
ScrollView,
Switch,
TextInput,
TouchableOpacity,
View,
} from 'react-native';
Expand Down
3 changes: 2 additions & 1 deletion apps/expo/features/catalog/screens/PackSelectionScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Button, SearchInput, Text } from '@packrat/ui/nativewindui';
import { Button, Text } from '@packrat/ui/nativewindui';
import { Icon } from 'expo-app/components/Icon';
import { SearchInput } from 'expo-app/components/SearchInput';
import { useDetailedPacks } from 'expo-app/features/packs';
import { useColorScheme } from 'expo-app/lib/hooks/useColorScheme';
import { useTranslation } from 'expo-app/lib/hooks/useTranslation';
Expand Down
11 changes: 2 additions & 9 deletions apps/expo/features/feed/screens/CreatePostScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
import { ActivityIndicator, Button, Text } from '@packrat/ui/nativewindui';
import { Icon } from 'expo-app/components/Icon';
import { TextInput } from 'expo-app/components/TextInput';
import { uploadImage } from 'expo-app/features/packs/utils/uploadImage';
import { useColorScheme } from 'expo-app/lib/hooks/useColorScheme';
import { useTranslation } from 'expo-app/lib/hooks/useTranslation';
import * as ImagePicker from 'expo-image-picker';
import { nanoid } from 'nanoid';
import { useCallback, useState } from 'react';
import {
Alert,
Image,
Pressable,
ScrollView,
TextInput,
TouchableOpacity,
View,
} from 'react-native';
import { Alert, Image, Pressable, ScrollView, TouchableOpacity, View } from 'react-native';
import { useCreatePost } from '../hooks';

interface SelectedPhoto {
Expand Down
5 changes: 3 additions & 2 deletions apps/expo/features/feed/screens/PostDetailScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ActivityIndicator, Text } from '@packrat/ui/nativewindui';
import { Icon } from 'expo-app/components/Icon';
import { TextInput } from 'expo-app/components/TextInput';
import { useColorScheme } from 'expo-app/lib/hooks/useColorScheme';
import { useTranslation } from 'expo-app/lib/hooks/useTranslation';
import { useCallback, useRef, useState } from 'react';
Expand All @@ -9,9 +10,9 @@ import {
Image,
KeyboardAvoidingView,
Platform,
type TextInput as RNTextInput,
ScrollView,
StyleSheet,
TextInput,
TouchableOpacity,
View,
} from 'react-native';
Expand All @@ -35,7 +36,7 @@ export const PostDetailScreen = ({ post, currentUserId }: PostDetailScreenProps)
const { t } = useTranslation();
const { colors } = useColorScheme();
const [commentText, setCommentText] = useState('');
const inputRef = useRef<TextInput>(null);
const inputRef = useRef<RNTextInput>(null);

const {
data: commentsData,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
import { Text } from '@packrat/ui/nativewindui';
import { TextInput } from 'expo-app/components/TextInput';
import { useTranslation } from 'expo-app/lib/hooks/useTranslation';
import { useState } from 'react';
import {
Alert,
KeyboardAvoidingView,
Platform,
Pressable,
ScrollView,
TextInput,
View,
} from 'react-native';
import { Alert, KeyboardAvoidingView, Platform, Pressable, ScrollView, View } from 'react-native';
import { useSubmitTrailConditionReport } from '../hooks/useSubmitTrailConditionReport';
import type { OverallCondition, TrailSurface, WaterCrossingDifficulty } from '../types';

Expand Down
3 changes: 2 additions & 1 deletion apps/expo/features/weather/screens/LocationSearchScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { SearchInput, Text } from '@packrat/ui/nativewindui';
import { Text } from '@packrat/ui/nativewindui';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { Icon } from 'expo-app/components/Icon';
import { SearchInput } from 'expo-app/components/SearchInput';
import { cn } from 'expo-app/lib/cn';
import { useColorScheme } from 'expo-app/lib/hooks/useColorScheme';
import { useTranslation } from 'expo-app/lib/hooks/useTranslation';
Expand Down
3 changes: 2 additions & 1 deletion apps/expo/features/weather/screens/LocationsScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Button, LargeTitleHeader, SearchInput, Text } from '@packrat/ui/nativewindui';
import { Button, LargeTitleHeader, Text } from '@packrat/ui/nativewindui';
import { Icon } from 'expo-app/components/Icon';
import { SearchInput } from 'expo-app/components/SearchInput';
import { withAuthWall } from 'expo-app/features/auth/hocs';
import { cn } from 'expo-app/lib/cn';
import { useColorScheme } from 'expo-app/lib/hooks/useColorScheme';
Expand Down
3 changes: 2 additions & 1 deletion apps/expo/features/wildlife/screens/IdentificationScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { useActionSheet } from '@expo/react-native-action-sheet';
import { ActivityIndicator, Button, Text } from '@packrat/ui/nativewindui';
import { appAlert } from 'expo-app/app/_layout';
import { Icon } from 'expo-app/components/Icon';
import { TextInput } from 'expo-app/components/TextInput';
import { useImagePicker } from 'expo-app/features/packs/hooks/useImagePicker';
import { useColorScheme } from 'expo-app/lib/hooks/useColorScheme';
import { useTranslation } from 'expo-app/lib/hooks/useTranslation';
import { Stack, useRouter } from 'expo-router';
import { useEffect, useRef, useState } from 'react';
import { Image, ScrollView, TextInput, View } from 'react-native';
import { Image, ScrollView, View } from 'react-native';
import { SpeciesCard } from '../components/SpeciesCard';
import { useWildlifeHistory } from '../hooks/useWildlifeHistory';
import { useWildlifeIdentification } from '../hooks/useWildlifeIdentification';
Expand Down
27 changes: 27 additions & 0 deletions apps/expo/lib/hooks/useKeyboardHideBlur.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useEffect } from 'react';
import { Keyboard } from 'react-native';

/**
* Hook that automatically blurs a text input when the keyboard is hidden.
* Useful for fixing keyboard behavior issues on Android.
*
* @param textInputRef - Ref to the TextInput or SearchInput component
*/
export function useKeyboardHideBlur(textInputRef: React.RefObject<{ blur?: () => void }>) {
useEffect(() => {
const keyboardDidHideCallback = () => {
if (textInputRef.current?.blur) {
textInputRef.current.blur();
}
};

const keyboardDidHideSubscription = Keyboard.addListener(
'keyboardDidHide',
keyboardDidHideCallback,
);

return () => {
keyboardDidHideSubscription?.remove();
};
}, [textInputRef]);
}
Loading
Loading