diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/components/search/RecentSearches.tsx | 10 | ||||
-rw-r--r-- | src/components/search/SearchBar.tsx | 97 | ||||
-rw-r--r-- | src/components/search/SearchResults.tsx | 32 | ||||
-rw-r--r-- | src/components/search/SearchResultsBackground.tsx | 14 | ||||
-rw-r--r-- | src/screens/search/SearchScreen.tsx | 146 |
5 files changed, 130 insertions, 169 deletions
diff --git a/src/components/search/RecentSearches.tsx b/src/components/search/RecentSearches.tsx index b4cc5483..84d35cac 100644 --- a/src/components/search/RecentSearches.tsx +++ b/src/components/search/RecentSearches.tsx @@ -25,12 +25,7 @@ interface RecentSearchesProps extends TouchableOpacityProps { } const RecentSearches: React.FC<RecentSearchesProps> = (props) => { - const { - sectionTitle, - recents, - recentCategories, - screenType, - } = props; + const {sectionTitle, recents, recentCategories, screenType} = props; return ( <ScrollView style={styles.mainContainer} @@ -53,10 +48,11 @@ const RecentSearches: React.FC<RecentSearchesProps> = (props) => { const styles = StyleSheet.create({ mainContainer: { - flexGrow: 1, + flex: 1, }, contentContainer: { paddingBottom: SCREEN_HEIGHT * 0.1, + flex: 1, }, header: { paddingHorizontal: 25, diff --git a/src/components/search/SearchBar.tsx b/src/components/search/SearchBar.tsx index be0eecc7..5e3a1e64 100644 --- a/src/components/search/SearchBar.tsx +++ b/src/components/search/SearchBar.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useState} from 'react'; import { StyleSheet, TextInput, @@ -10,10 +10,10 @@ import { NativeSyntheticEvent, TextInputSubmitEditingEventData, } from 'react-native'; -import Animated from 'react-native-reanimated'; +import Animated, {interpolate} from 'react-native-reanimated'; import Icon from 'react-native-vector-icons/Feather'; import {normalize} from 'react-native-elements'; -import {SCREEN_WIDTH} from '../../utils'; +import {SCREEN_HEIGHT} from '../../utils'; const AnimatedIcon = Animated.createAnimatedComponent(Icon); @@ -27,7 +27,7 @@ const SearchBar: React.FC<SearchBarProps> = ({ onChangeText, value, onCancel, - style, + top, }) => { const handleSubmit = ( e: NativeSyntheticEvent<TextInputSubmitEditingEventData>, @@ -36,47 +36,52 @@ const SearchBar: React.FC<SearchBarProps> = ({ Keyboard.dismiss(); }; + /* + * CSS properties for width change animation. + */ + const marginRight: Animated.Node<number> = interpolate(top, { + inputRange: [-SCREEN_HEIGHT, 0], + outputRange: [0, 58], + }); + const opacity: Animated.Node<number> = interpolate(top, { + inputRange: [-SCREEN_HEIGHT, 0], + outputRange: [0, 1], + }); + return ( - <> - <View style={[styles.container, style]}> - <Animated.View style={[styles.inputContainer]}> - <AnimatedIcon - name="search" - color={'#7E7E7E'} - size={25} - style={styles.searchIcon} - /> - <TextInput - style={[styles.input]} - placeholder={'Search'} - placeholderTextColor={'#828282'} - onSubmitEditing={handleSubmit} - clearButtonMode="while-editing" - autoCapitalize="none" - autoCorrect={false} - {...{value, onChangeText, onFocus, onBlur}} - /> - </Animated.View> - <View style={styles.cancelButtonView}> - <TouchableOpacity style={styles.cancelButton} onPress={onCancel}> - <Text style={styles.cancelText}>Cancel</Text> - </TouchableOpacity> - </View> - </View> - <Text style={styles.helperText}> - Try searching for "trending on tagg" - </Text> - </> + <View style={styles.container}> + <Animated.View style={styles.inputContainer}> + <AnimatedIcon + name="search" + color={'#7E7E7E'} + size={25} + style={styles.searchIcon} + /> + <TextInput + style={[styles.input]} + placeholder={'Search'} + placeholderTextColor={'#828282'} + onSubmitEditing={handleSubmit} + clearButtonMode="while-editing" + autoCapitalize="none" + autoCorrect={false} + {...{value, onChangeText, onFocus, onBlur}} + /> + </Animated.View> + <Animated.View style={{marginRight, opacity}}> + <TouchableOpacity style={styles.cancelButton} onPress={onCancel}> + <Text style={styles.cancelText}>Cancel</Text> + </TouchableOpacity> + </Animated.View> + </View> ); }; const styles = StyleSheet.create({ container: { height: 40, + paddingHorizontal: 20, flexDirection: 'row', - justifyContent: 'center', - alignItems: 'stretch', - zIndex: 2, }, inputContainer: { flexGrow: 1, @@ -95,27 +100,15 @@ const styles = StyleSheet.create({ color: '#000', letterSpacing: normalize(0.5), }, - cancelButtonView: {width: 70, flexDirection: 'row', justifyContent: 'center'}, cancelButton: { - position: 'absolute', height: '100%', + position: 'absolute', justifyContent: 'center', - paddingHorizontal: 5, + paddingHorizontal: 8, }, cancelText: { color: '#818181', - fontWeight: '600', - }, - helperText: { - fontWeight: '400', - fontSize: 14, - lineHeight: normalize(16.71), - color: '#828282', - marginBottom: '2%', - marginHorizontal: '2.5%', - marginTop: '1%', - textAlign: 'center', - width: SCREEN_WIDTH * 0.74, + fontWeight: '500', }, }); diff --git a/src/components/search/SearchResults.tsx b/src/components/search/SearchResults.tsx index 798d3251..fbeae1d8 100644 --- a/src/components/search/SearchResults.tsx +++ b/src/components/search/SearchResults.tsx @@ -5,7 +5,6 @@ import { ScreenType, CategoryPreviewType, } from '../../types'; -import ProfilePreview from '../profile/ProfilePreview'; import {StyleSheet, View} from 'react-native'; import SearchResultsCell from './SearchResultCell'; import {useSelector} from 'react-redux'; @@ -16,30 +15,14 @@ interface SearchResultsProps { screenType: ScreenType; categories: CategoryPreviewType[]; } -const SearchResults: React.FC<SearchResultsProps> = ({ - results, - previewType, - screenType, - categories, -}) => { +const SearchResults: React.FC<SearchResultsProps> = ({results, categories}) => { /** * Added the following swicth case to make Results on Search and Recents screen a list * Flex is love */ const {user: loggedInUser} = useSelector((state: RootState) => state.user); - let containerStyle; - switch (previewType) { - case 'Search': - containerStyle = styles.containerSearch; - break; - case 'Recent': - containerStyle = styles.containerSearch; - break; - default: - containerStyle = styles.container; - } return ( - <View style={containerStyle}> + <View> {categories.map((category: CategoryPreviewType) => ( <SearchResultsCell key={category.name} @@ -58,15 +41,4 @@ const SearchResults: React.FC<SearchResultsProps> = ({ ); }; -const styles = StyleSheet.create({ - containerSearch: { - flexDirection: 'column', - flexWrap: 'wrap', - }, - container: { - flexDirection: 'row', - flexWrap: 'wrap', - }, -}); - export default SearchResults; diff --git a/src/components/search/SearchResultsBackground.tsx b/src/components/search/SearchResultsBackground.tsx index 25dcf781..2833553d 100644 --- a/src/components/search/SearchResultsBackground.tsx +++ b/src/components/search/SearchResultsBackground.tsx @@ -1,7 +1,7 @@ import React from 'react'; import {StyleSheet} from 'react-native'; import Animated, {interpolate} from 'react-native-reanimated'; -import {SCREEN_HEIGHT, SCREEN_WIDTH, StatusBarHeight} from '../../utils'; +import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; interface SearchResultsBackgroundProps { top: Animated.Value<number>; @@ -21,7 +21,8 @@ const SearchResultsBackground: React.FC<SearchResultsBackgroundProps> = ({ return ( <Animated.View style={[styles.container, {opacity: opacityBackground, top}]}> - <Animated.View style={{opacity: opacityContent}}> + <Animated.View + style={[styles.contentContainer, {opacity: opacityContent}]}> {children} </Animated.View> </Animated.View> @@ -29,14 +30,15 @@ const SearchResultsBackground: React.FC<SearchResultsBackgroundProps> = ({ }; const styles = StyleSheet.create({ container: { - flex: 1, height: SCREEN_HEIGHT, width: SCREEN_WIDTH, position: 'absolute', backgroundColor: 'white', - paddingTop: 60, - paddingBottom: 10, - zIndex: 0, + }, + contentContainer: { + flex: 1, + paddingVertical: 10, + paddingBottom: SCREEN_HEIGHT / 15, }, }); export default SearchResultsBackground; diff --git a/src/screens/search/SearchScreen.tsx b/src/screens/search/SearchScreen.tsx index e80e09aa..728510c5 100644 --- a/src/screens/search/SearchScreen.tsx +++ b/src/screens/search/SearchScreen.tsx @@ -1,7 +1,7 @@ import AsyncStorage from '@react-native-community/async-storage'; import {useFocusEffect} from '@react-navigation/native'; import React, {useEffect, useState} from 'react'; -import {Keyboard, ScrollView, StatusBar, StyleSheet, View} from 'react-native'; +import {Keyboard, ScrollView, StatusBar, StyleSheet} from 'react-native'; import Animated, {Easing, timing} from 'react-native-reanimated'; import {SafeAreaView} from 'react-native-safe-area-context'; import {useDispatch, useSelector} from 'react-redux'; @@ -54,16 +54,10 @@ const SearchScreen: React.FC = () => { const dispatch = useDispatch(); /* - * If user begins actively searching, refresh recently-searched list. - */ - useEffect(() => { - if (searching) loadRecentSearches(); - }, [searching]); - - /* * Main handler for changes in query. */ useEffect(() => { + if (!searching) return; if (!query.length) loadRecentSearches(); if (query.length < 3) { setResults(undefined); @@ -104,25 +98,16 @@ const SearchScreen: React.FC = () => { 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 handleCancel = () => { - Keyboard.dismiss(); - const topOutConfig = { - duration: 180, - toValue: -SCREEN_HEIGHT, - easing: Easing.inOut(Easing.ease), - }; - timing(top, topOutConfig).start(() => setQuery('')); - setSearching(false); - }; + // when searching state changes, run animation and reset query accordingly + useEffect(() => { + if (searching) { + timing(top, topInConfig).start(); + } else { + setQuery(''); + handleBlur(); + timing(top, topOutConfig).start(() => setResults(undefined)); + } + }, [searching]); const loadRecentlySearchedUsers = async () => { try { @@ -159,56 +144,72 @@ const SearchScreen: React.FC = () => { } }; + const topInConfig = { + duration: 180, + toValue: 0, + easing: Easing.bezier(0.31, 0.14, 0.66, 0.82), + }; + const topOutConfig = { + duration: 180, + toValue: -SCREEN_HEIGHT, + easing: Easing.inOut(Easing.ease), + }; + const handleFocus = () => { + setSearching(true); + }; + const handleBlur = () => { + Keyboard.dismiss(); + }; + const handleCancel = () => { + setSearching(false); + }; + return ( - <View style={styles.mainContainer}> - <SafeAreaView> - <StatusBar barStyle="dark-content" /> - <ScrollView - scrollEnabled={!searching} - keyboardShouldPersistTaps={'always'} - stickyHeaderIndices={[4]} - contentContainerStyle={styles.contentContainer} - showsVerticalScrollIndicator={false}> - <SearchBar - style={styles.searchBar} - onCancel={handleCancel} - onChangeText={setQuery} - onBlur={Keyboard.dismiss} - onFocus={handleFocus} - value={query} - {...{top, searching}} - /> - <SearchCategories /> - <SearchResultsBackground {...{top}}> - {results === undefined && - recents.length + recentCategories.length !== 0 ? ( - <RecentSearches - sectionTitle="Recent" - sectionButtonTitle="Clear all" - onPress={clearRecentlySearched} - screenType={ScreenType.Search} - {...{recents, recentCategories}} - /> - ) : ( - <SearchResultList - {...{results}} - keyboardVisible={keyboardVisible === 'keyboardVisibleTrue'} - previewType={'Search'} - screenType={ScreenType.Search} - /> - )} - </SearchResultsBackground> - </ScrollView> - <TabsGradient /> - </SafeAreaView> - </View> + <SafeAreaView style={styles.screenContainer}> + <StatusBar barStyle="dark-content" /> + <SearchBar + onCancel={handleCancel} + onChangeText={setQuery} + onBlur={handleBlur} + onFocus={handleFocus} + value={query} + {...{top}} + /> + <ScrollView + scrollEnabled={!searching} + keyboardShouldPersistTaps={'always'} + stickyHeaderIndices={[4]} + contentContainerStyle={styles.contentContainer} + showsVerticalScrollIndicator={false}> + <SearchCategories /> + <SearchResultsBackground {...{top}}> + {results === undefined && + recents.length + recentCategories.length !== 0 ? ( + <RecentSearches + sectionTitle="Recent" + onPress={clearRecentlySearched} + screenType={ScreenType.Search} + {...{recents, recentCategories}} + /> + ) : ( + <SearchResultList + {...{results}} + keyboardVisible={keyboardVisible === 'keyboardVisibleTrue'} + previewType={'Search'} + screenType={ScreenType.Search} + /> + )} + </SearchResultsBackground> + </ScrollView> + <TabsGradient /> + </SafeAreaView> ); }; const styles = StyleSheet.create({ - mainContainer: { + screenContainer: { + paddingTop: 15, backgroundColor: '#fff', - height: SCREEN_HEIGHT, }, contentContainer: { height: SCREEN_HEIGHT, @@ -216,9 +217,6 @@ const styles = StyleSheet.create({ paddingBottom: SCREEN_HEIGHT / 3, paddingHorizontal: '3%', }, - searchBar: { - paddingLeft: '3%', - }, header: { marginVertical: 20, zIndex: 1, |