Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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