Skip to content

Commit

Permalink
Improve the search and search components of the Feed screen. (#59)
Browse files Browse the repository at this point in the history
* created a filter option

* updated the ui and added the sort by options

* made it use the users follower list with UseSearch

* resolved all comments

* added back the original structure
  • Loading branch information
Dprof-in-tech authored Aug 28, 2024
1 parent 328b450 commit 439422b
Show file tree
Hide file tree
Showing 5 changed files with 255 additions and 82 deletions.
103 changes: 103 additions & 0 deletions apps/mobile/src/components/Filter/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import {NDKKind} from '@nostr-dev-kit/ndk';
import React from 'react';
import {
Modal,
Pressable,
ScrollView,
Text,
useWindowDimensions,
View,
ViewStyle,
} from 'react-native';

import {useStyles} from '../../hooks';
import stylesheet from './styles';

interface IFilterMenuProps {
visible: boolean;
onClose: () => void;
kinds: NDKKind[];
setKinds: (kinds: NDKKind[]) => void;
onSortChange: (sortBy: string) => void;
activeSortBy: string;
}

const NDK_KIND_OPTIONS = [
{label: 'Text', value: NDKKind.Text},
{label: 'Channel Creation', value: NDKKind.ChannelCreation},
{label: 'Group Chat', value: NDKKind.GroupChat},
{label: 'Channel Message', value: NDKKind.ChannelMessage},
{label: 'Metadata', value: NDKKind.Metadata},
];

const SORT_OPTIONS = [
{label: 'Time', value: 'time'},
{label: 'For You', value: 'forYou'},
{label: 'Trending', value: 'trending'},
];

const FilterMenu: React.FC<IFilterMenuProps> = ({
visible,
onClose,
kinds,
setKinds,
onSortChange,
activeSortBy,
}) => {
const styles = useStyles(stylesheet);
const {width} = useWindowDimensions();

const containerStyle = [
styles.container,
{width: width > 768 ? '45%' : '90%'} as ViewStyle, // 45% for web, 90% for mobile
];

const toggleKindSelection = (kind: NDKKind) => {
if (kinds.includes(kind)) {
setKinds(kinds.filter((k) => k !== kind));
} else {
setKinds([...kinds, kind]);
}
};

return (
<Modal visible={visible} transparent={true} animationType="slide">
<View style={styles.modalContainer}>
<View style={containerStyle}>
<ScrollView>
<Text style={styles.sectionTitle}>Sort By</Text>
<View style={styles.rowContainer}>
{SORT_OPTIONS.map((option) => (
<Pressable
key={option.value}
style={[styles.button, activeSortBy === option.value && styles.activeButton]}
onPress={() => onSortChange(option.value)}
>
<Text style={styles.buttonText}>{option.label}</Text>
</Pressable>
))}
</View>

<Text style={styles.sectionTitle}>Filter By Type</Text>
<View style={styles.container}>
{NDK_KIND_OPTIONS.map((option) => (
<Pressable
key={option.value}
style={[styles.button, kinds.includes(option.value) && styles.activeButton]}
onPress={() => toggleKindSelection(option.value)}
>
<Text style={styles.buttonText}>{option.label}</Text>
</Pressable>
))}
</View>
</ScrollView>
<Pressable onPress={onClose} style={styles.closeButton}>
<Text style={styles.closeButtonText}>Close</Text>
</Pressable>
</View>
</View>
</Modal>
);
};

export default FilterMenu;
66 changes: 66 additions & 0 deletions apps/mobile/src/components/Filter/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import {StyleSheet} from 'react-native';

import {Spacing, ThemedStyleSheet, Typography} from '../../styles';

export default ThemedStyleSheet((theme) => ({
modalContainer: {
flex: 2,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0, 0, 0, 0.5)',
},
container: {
padding: Spacing.pagePadding,
backgroundColor: theme.colors.surface,
borderRadius: 12,
shadowColor: '#000',
shadowOffset: {width: 0, height: 2},
shadowOpacity: 0.8,
shadowRadius: 2,
elevation: 5,
},
rowContainer: {
flexDirection: 'row',
flexWrap: 'wrap', // Allow wrapping if items overflow
justifyContent: 'space-between', // Adjust spacing between items
},
button: {
paddingVertical: Spacing.small,
paddingHorizontal: Spacing.large,
backgroundColor: theme.colors.surface,
borderRadius: 8,
borderWidth: StyleSheet.hairlineWidth,
borderColor: theme.colors.divider,
marginBottom: Spacing.small,
marginRight: Spacing.small, // Add spacing between items
justifyContent: 'center',
alignItems: 'center',
},
activeButton: {
backgroundColor: theme.colors.primary, // Active button background color
},
buttonText: {
color: theme.colors.text,
...Typography.medium,
},
closeButton: {
paddingVertical: Spacing.small,
paddingHorizontal: Spacing.large,
backgroundColor: theme.colors.primary,
borderRadius: 8,
marginTop: Spacing.small,
},
closeButtonText: {
color: theme.colors.onPrimary,
textAlign: 'center',
...Typography.medium,
},
sectionTitle: {
paddingVertical: Spacing.medium,
paddingHorizontal: Spacing.pagePadding,
backgroundColor: theme.colors.background,
color: theme.colors.text,
fontSize: 18,
...Typography.bold,
},
}));
61 changes: 52 additions & 9 deletions apps/mobile/src/components/search/index.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,58 @@
import {NDKKind} from '@nostr-dev-kit/ndk';
import React from 'react';
import {TextInput, View} from 'react-native';
import useSearch from 'afk_nostr_sdk/src/hooks/search/useSearch'; // Import useSearch
import React, {useEffect, useState} from 'react';
import {Pressable, Text, TextInput, View} from 'react-native';
import Svg, {Path} from 'react-native-svg';

import {useStyles} from '../../hooks';
import FilterMenu from '../Filter';
import stylesheet from './styles';

interface ISearchComponent {
searchQuery?: string;
searchQuery: string;
setSearchQuery: (search: string) => void;
kinds?: NDKKind[];
setKinds?: (kinds: NDKKind[]) => void;
isOpenFilter?: boolean;
setIsOpenFilter?: (isOpen: boolean) => void;
contactList: string[];
}
const SearchComponent = ({searchQuery, setSearchQuery}: ISearchComponent) => {
// const [searchQuery, setSearchQuery] = useState('');

const SearchComponent: React.FC<ISearchComponent> = ({
searchQuery,
setSearchQuery,
kinds = [],
setKinds = () => {},
contactList,
}) => {
const styles = useStyles(stylesheet);
const [debouncedQuery, setDebouncedQuery] = useState(searchQuery);
const [isOpenFilter, setIsOpenFilter] = useState(false);
const [activeSortBy, setActiveSortBy] = useState<string>('');

const handleSortChange = (sortBy: string) => {
setActiveSortBy(sortBy);
};

useEffect(() => {
const handler = setTimeout(() => {
setSearchQuery(debouncedQuery || '');
}, 300);

return () => {
clearTimeout(handler);
};
}, [debouncedQuery, setSearchQuery]);

const handleChangeText = (text: string) => {
setSearchQuery(text);
setDebouncedQuery(text);
};

const {data, isLoading, isError} = useSearch({
search: searchQuery,
kinds,
authors: contactList,
sortBy: activeSortBy,
});

return (
<View style={styles.container}>
<View style={styles.iconContainer}>
Expand All @@ -41,11 +72,23 @@ const SearchComponent = ({searchQuery, setSearchQuery}: ISearchComponent) => {
</View>
<TextInput
style={styles.input}
value={searchQuery}
value={debouncedQuery}
onChangeText={handleChangeText}
placeholder="Search"
clearButtonMode="always"
/>
<Pressable onPress={() => setIsOpenFilter(true)}>
<Text style={styles.input}>Filter</Text>
</Pressable>

<FilterMenu
visible={isOpenFilter}
onClose={() => setIsOpenFilter(false)}
kinds={kinds}
setKinds={setKinds}
onSortChange={handleSortChange}
activeSortBy={activeSortBy}
/>
</View>
);
};
Expand Down
Loading

0 comments on commit 439422b

Please sign in to comment.