diff options
| -rw-r--r-- | src/components/AppMenu.tsx | 25 | ||||
| -rw-r--r-- | src/screens/AppList.tsx | 61 |
2 files changed, 42 insertions, 44 deletions
diff --git a/src/components/AppMenu.tsx b/src/components/AppMenu.tsx index ebc6dae..bd6632f 100644 --- a/src/components/AppMenu.tsx +++ b/src/components/AppMenu.tsx @@ -1,17 +1,11 @@ -import { - Text, - View, - Modal, - TouchableOpacity, - Pressable, - TouchableNativeFeedback, -} from 'react-native'; +import {Text, View, Modal, TouchableOpacity, Pressable} from 'react-native'; import {AppDetail} from 'react-native-launcher-kit/typescript/Interfaces/InstalledApps'; import {useFavorites} from '../hooks/useFavorites'; import React, {useState} from 'react'; // @ts-expect-error No declaration file import IntentLauncher from '@angelkrak/react-native-intent-launcher'; import {useStableCallback} from '../hooks/useStableCallback'; +import {TouchableNativeFeedback} from 'react-native-gesture-handler'; export const AppMenu: React.FC<React.PropsWithChildren<{app: AppDetail}>> = ({ app, @@ -63,19 +57,16 @@ export const AppMenu: React.FC<React.PropsWithChildren<{app: AppDetail}>> = ({ return ( <> - <TouchableNativeFeedback - onPress={openApp} - onLongPress={openContextMenu} - delayPressIn={100}> + <TouchableNativeFeedback onPress={openApp} onLongPress={openContextMenu}> {children} </TouchableNativeFeedback> <Modal visible={isOpen} transparent={true} - animationType="none" + animationType="fade" onRequestClose={closeContextMenu}> - <TouchableOpacity className="flex-1" onPress={closeContextMenu}> + <Pressable className="flex-1" onPress={closeContextMenu}> <View className="flex justify-center items-center h-full"> <View className="bg-[#181818] border border-[#222] w-2/3"> <Text className="text-slate-500 text-xs text-center border-b border-slate-500"> @@ -83,18 +74,18 @@ export const AppMenu: React.FC<React.PropsWithChildren<{app: AppDetail}>> = ({ </Text> {menuItems.map((menuItem) => ( - <Pressable + <TouchableOpacity key={menuItem.label} onPress={menuItem.onPress} className="py-3 px-4 border-b border-[#222] last:border-b-0 last:border-transparent"> <Text className="text-lg text-gray-300"> {menuItem.label} </Text> - </Pressable> + </TouchableOpacity> ))} </View> </View> - </TouchableOpacity> + </Pressable> </Modal> </> ); diff --git a/src/screens/AppList.tsx b/src/screens/AppList.tsx index 5af2c55..03c1caa 100644 --- a/src/screens/AppList.tsx +++ b/src/screens/AppList.tsx @@ -1,56 +1,63 @@ import {matchSorter} from 'match-sorter'; -import React, {useEffect, useMemo, useRef, useState} from 'react'; -import { - ScrollView, - Text, - TextInput, - TouchableHighlight, - View, -} from 'react-native'; +import React, { + ComponentProps, + useEffect, + useMemo, + useRef, + useState, +} from 'react'; +import {Pressable, ScrollView, Text, TextInput, View} from 'react-native'; import Icon from 'react-native-vector-icons/MaterialIcons'; import {AppMenu} from '../components/AppMenu'; import {useInstalledApps} from '../hooks/useInstalledApps'; -import {AppDetail} from 'react-native-launcher-kit/typescript/Interfaces/InstalledApps'; import {useStableCallback} from '../hooks/useStableCallback'; +import {TouchableHighlight} from 'react-native-gesture-handler'; -const AppListItem: React.FC<{app: AppDetail}> = React.memo(({app}) => { - return ( - <AppMenu app={app}> - <View className="p-2"> - <Text className="text-base">{app.label}</Text> - <Text className="text-xs text-gray-600">{app.packageName}</Text> - </View> - </AppMenu> - ); -}); +const AppListItem: React.FC<ComponentProps<typeof AppMenu>> = React.memo( + ({app, ...props}) => { + return ( + <AppMenu app={app} {...props}> + <View className="p-2"> + <Text className="text-base">{app.label}</Text> + <Text className="text-xs text-gray-600">{app.packageName}</Text> + </View> + </AppMenu> + ); + }, +); export const AppList: React.FC<{active: boolean}> = React.memo(({active}) => { const {apps} = useInstalledApps(); const textInputRef = useRef<TextInput>(null); const [searchText, setSearchText] = useState(''); - const clearSearchInput = useStableCallback(() => { - setSearchText(''); + const focusInput = useStableCallback(() => { if (active) TextInput.State.focusTextInput(textInputRef.current ?? undefined); }); + const clearSearchInput = useStableCallback(() => { + setSearchText(''); + focusInput(); + }); + const filteredApps = useMemo(() => { if (searchText === '') return apps; return matchSorter(apps, searchText, {keys: ['label', 'packageName']}); }, [apps, searchText]); - // Autofocus + // Autofocus when active useEffect(() => { - if (!textInputRef.current) return; - if (active) TextInput.State.focusTextInput(textInputRef.current); - }, [active]); + active && focusInput(); + }, [active, focusInput]); return ( <View className="px-2"> <View className="flex justify-between flex-row items-center gap-2 px-2 border-b border-slate-800"> - <Icon name="search" size={21} color="#666" className="py-2" /> + <Pressable onPress={focusInput} accessible={false}> + <Icon name="search" size={21} color="#666" className="py-2" /> + </Pressable> <TextInput ref={textInputRef} autoFocus={false} @@ -62,7 +69,7 @@ export const AppList: React.FC<{active: boolean}> = React.memo(({active}) => { <TouchableHighlight underlayColor="#222" onPress={clearSearchInput} - className="p-2"> + className="p-2 rounded-full"> <Icon name="close" size={17} color="#666" /> </TouchableHighlight> </View> |
