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, SearchResults, SearchResultsBackground, TabsGradient, } from '../../components'; import {SEARCH_ENDPOINT, TAGG_TEXT_LIGHT_BLUE} from '../../constants'; import {loadRecentlySearched, resetScreenType} from '../../store/actions'; import {RootState} from '../../store/rootReducer'; import {ProfilePreviewType, ScreenType, UserType} from '../../types'; import {SCREEN_HEIGHT, SCREEN_WIDTH, StatusBarHeight} from '../../utils'; const NO_USER: UserType = { userId: '', username: '', }; /** * Search Screen for user recommendations and a search * tool to allow user to find other users */ const SearchScreen: React.FC = () => { const {recentSearches, explores} = useSelector( (state: RootState) => state.taggUsers, ); const [query, setQuery] = useState(''); const [results, setResults] = useState>([]); const [recents, setRecents] = useState>( recentSearches ?? [], ); const [searching, setSearching] = useState(false); const top = Animated.useValue(-SCREEN_HEIGHT); const [user, setUser] = useState(NO_USER); const [refreshing, setRefreshing] = useState(false); const dispatch = useDispatch(); const onRefresh = useCallback(() => { const refrestState = async () => { dispatch(loadRecentlySearched()); }; setRefreshing(true); refrestState().then(() => { setRefreshing(false); }); }, []); useEffect(() => { if (query.length < 3) { setResults([]); return; } const loadResults = async (q: string) => { try { const token = await AsyncStorage.getItem('token'); if (!token) { setUser(NO_USER); return; } const response = await fetch(`${SEARCH_ENDPOINT}?query=${q}`, { method: 'GET', headers: { Authorization: 'Token ' + token, }, }); const status = response.status; if (status === 200) { let searchResults = await response.json(); setResults(searchResults); return; } setResults([]); } catch (error) { console.log(error); setResults([]); } }; loadResults(query); }, [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 = () => { 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.length === 0 && 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_TEXT_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;