import AsyncStorage from '@react-native-community/async-storage'; import {useFocusEffect} from '@react-navigation/native'; import React, {useCallback, useEffect, useState} from 'react'; import { Keyboard, RefreshControl, ScrollView, StatusBar, StyleSheet, } from 'react-native'; import Animated, {Easing, timing} from 'react-native-reanimated'; import {useDispatch, useSelector} from 'react-redux'; import { Explore, RecentSearches, SearchBackground, SearchBar, SearchHeader, SearchResultList, SearchResultsBackground, TabsGradient, } from '../../components'; import {SEARCH_ENDPOINT, TAGG_LIGHT_BLUE} from '../../constants'; import {loadSearchResults} from '../../services'; import {loadRecentlySearched, resetScreenType} from '../../store/actions'; import {RootState} from '../../store/rootReducer'; import {ProfilePreviewType, ScreenType} from '../../types'; import {SCREEN_HEIGHT, SCREEN_WIDTH, StatusBarHeight} from '../../utils'; /** * Search Screen for user recommendations and a search * tool to allow user to find other users */ const SearchScreen: React.FC = () => { const {recentSearches} = useSelector((state: RootState) => state.taggUsers); const [query, setQuery] = useState(''); const [results, setResults] = useState | undefined>(undefined); const [recents, setRecents] = useState>( recentSearches ?? [], ); const [searching, setSearching] = useState(false); const top = Animated.useValue(-SCREEN_HEIGHT); const [refreshing, setRefreshing] = useState(false); const [keyboardVisible, setKeyboardVisible] = React.useState( 'keyboardVisible', ); useEffect(() => { const showKeyboard = () => setKeyboardVisible('keyboardVisibleTrue'); Keyboard.addListener('keyboardWillShow', showKeyboard); return () => Keyboard.removeListener('keyboardWillShow', showKeyboard); }, []); useEffect(() => { const hideKeyboard = () => setKeyboardVisible('keyboardVisibleFalse'); Keyboard.addListener('keyboardWillHide', hideKeyboard); return () => Keyboard.removeListener('keyboardWillHide', hideKeyboard); }, []); const dispatch = useDispatch(); const onRefresh = useCallback(() => { const refrestState = async () => { dispatch(loadRecentlySearched()); }; setRefreshing(true); refrestState().then(() => { setRefreshing(false); }); }, []); useEffect(() => { if (query.length < 3) { setResults(undefined); return; } (async () => { const searchResults = await loadSearchResults( `${SEARCH_ENDPOINT}?query=${query}`, ); if (query.length > 2) { const categories = searchResults?.categories; const users = searchResults?.users; const sanitizedResult = [ { title: 'categories', data: categories, }, { title: 'users', data: users, }, ]; setResults(sanitizedResult); } else { setResults(undefined); } })(); }, [query]); /** * Code under useFocusEffect gets executed every time the screen comes under focus / is being viewed by the user. * This is done to reset the users stored in our store for the Search screen. * Read more here : https://reactnavigation.org/docs/function-after-focusing-screen/ */ useFocusEffect(() => { dispatch(resetScreenType(ScreenType.Search)); }); const handleFocus = () => { const topInConfig = { duration: 180, toValue: 0, easing: Easing.bezier(0.31, 0.14, 0.66, 0.82), }; timing(top, topInConfig).start(); setSearching(true); }; const handleBlur = () => { setQuery(''); Keyboard.dismiss(); const topOutConfig = { duration: 180, toValue: -SCREEN_HEIGHT, easing: Easing.inOut(Easing.ease), }; timing(top, topOutConfig).start(); setSearching(false); }; const loadRecentlySearchedUsers = async () => { try { const asyncCache = await AsyncStorage.getItem('@recently_searched_users'); asyncCache != null ? setRecents(JSON.parse(asyncCache)) : setRecents([]); } catch (e) { console.log(e); } }; const clearRecentlySearched = async () => { try { await AsyncStorage.removeItem('@recently_searched_users'); loadRecentlySearchedUsers(); } catch (e) { console.log(e); } }; const handleUpdate = async (val: string) => { setQuery(val); loadRecentlySearchedUsers(); }; return ( }> {results === undefined && recents.length !== 0 ? ( ) : ( )} ); }; const styles = StyleSheet.create({ contentContainer: { paddingTop: StatusBarHeight, paddingBottom: SCREEN_HEIGHT / 15, }, searchBar: { paddingHorizontal: '3%', }, header: { marginVertical: 20, zIndex: 1, }, recentsHeaderContainer: { flexDirection: 'row', }, recentsHeader: { fontSize: 17, fontWeight: 'bold', flexGrow: 1, }, clear: { fontSize: 17, fontWeight: 'bold', color: TAGG_LIGHT_BLUE, }, image: { width: SCREEN_WIDTH, height: SCREEN_WIDTH, }, textContainer: { marginTop: '10%', }, headerText: { color: '#fff', fontSize: 32, fontWeight: '600', textAlign: 'center', marginBottom: '4%', marginHorizontal: '10%', }, subtext: { color: '#fff', fontSize: 16, fontWeight: '600', textAlign: 'center', marginHorizontal: '10%', }, }); export default SearchScreen;