Search custom feeds (#1031)

* paginate custom feeds

* basic search

* update `@atproto/api`

* use search from the API

* debounce search for 200ms
zio/stable
Ansh 2023-07-28 08:29:37 -07:00 committed by GitHub
parent 8e9b8b6b36
commit 38d78e16bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 81 additions and 18 deletions

View File

@ -15,6 +15,7 @@ module.exports = {
'coverage',
'*.lock',
'.husky',
'patches',
],
overrides: [
{

View File

@ -24,7 +24,7 @@
"e2e:run": "detox test --configuration ios.sim.debug --take-screenshots all"
},
"dependencies": {
"@atproto/api": "^0.4.2",
"@atproto/api": "^0.4.3",
"@bam.tech/react-native-image-resizer": "^3.0.4",
"@braintree/sanitize-url": "^6.0.2",
"@expo/html-elements": "^0.4.2",

View File

@ -82,6 +82,21 @@ export class FeedsDiscoveryModel {
this._xIdle()
})
search = async (query: string) => {
this._xLoading(false)
try {
const results =
await this.rootStore.agent.app.bsky.unspecced.getPopularFeedGenerators({
limit: DEFAULT_LIMIT,
query: query,
})
this._replaceAll(results)
} catch (e: any) {
this._xIdle(e)
}
this._xIdle()
}
clear() {
this.isLoading = false
this.isRefreshing = false
@ -93,9 +108,9 @@ export class FeedsDiscoveryModel {
// state transitions
// =
_xLoading() {
_xLoading(isRefreshing = true) {
this.isLoading = true
this.isRefreshing = true
this.isRefreshing = isRefreshing
this.error = ''
}

View File

@ -37,7 +37,7 @@ export const Step1 = observer(({model}: {model: CreateAccountModel}) => {
}, [setIsDefaultSelected, model])
const fetchServiceDescription = React.useMemo(
() => debounce(() => model.fetchServiceDescription(), 1e3),
() => debounce(() => model.fetchServiceDescription(), 1e3), // debouce for 1 second (1e3 = 1000ms)
[model],
)

View File

@ -21,6 +21,7 @@ interface Props {
onPressClearQuery: () => void
onPressCancelSearch: () => void
onSubmitQuery: () => void
showMenu?: boolean
}
export function HeaderWithInput({
isInputFocused,
@ -30,6 +31,7 @@ export function HeaderWithInput({
onPressClearQuery,
onPressCancelSearch,
onSubmitQuery,
showMenu = true,
}: Props) {
const store = useStores()
const theme = useTheme()
@ -49,6 +51,7 @@ export function HeaderWithInput({
return (
<View style={[pal.view, pal.border, styles.header]}>
{showMenu ? (
<TouchableOpacity
testID="viewHeaderBackOrMenuBtn"
onPress={onPressMenu}
@ -59,6 +62,7 @@ export function HeaderWithInput({
accessibilityHint="Access navigation links and settings">
<FontAwesomeIcon icon="bars" size={18} color={pal.colors.textLight} />
</TouchableOpacity>
) : null}
<View
style={[
{backgroundColor: pal.colors.backgroundLight},

View File

@ -14,6 +14,8 @@ import {isDesktopWeb} from 'platform/detection'
import {usePalette} from 'lib/hooks/usePalette'
import {s} from 'lib/styles'
import {CustomFeedModel} from 'state/models/feeds/custom-feed'
import {HeaderWithInput} from 'view/com/search/HeaderWithInput'
import debounce from 'lodash.debounce'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'DiscoverFeeds'>
export const DiscoverFeedsScreen = withAuthRequired(
@ -22,6 +24,37 @@ export const DiscoverFeedsScreen = withAuthRequired(
const pal = usePalette('default')
const feeds = React.useMemo(() => new FeedsDiscoveryModel(store), [store])
// search stuff
const [isInputFocused, setIsInputFocused] = React.useState<boolean>(false)
const [query, setQuery] = React.useState<string>('')
const debouncedSearchFeeds = React.useMemo(
() => debounce(() => feeds.search(query), 200), // debouce for 200 ms
[feeds, query],
)
const onChangeQuery = React.useCallback(
(text: string) => {
setQuery(text)
if (text.length > 1) {
debouncedSearchFeeds()
} else {
feeds.refresh()
}
},
[debouncedSearchFeeds, feeds],
)
const onPressClearQuery = React.useCallback(() => {
setQuery('')
feeds.refresh()
}, [feeds])
const onPressCancelSearch = React.useCallback(() => {
setIsInputFocused(false)
setQuery('')
feeds.refresh()
}, [feeds])
const onSubmitQuery = React.useCallback(() => {
feeds.search(query)
}, [feeds, query])
useFocusEffect(
React.useCallback(() => {
store.shell.setMinimalShellMode(false)
@ -68,6 +101,16 @@ export const DiscoverFeedsScreen = withAuthRequired(
<CenteredView style={[styles.container, pal.view]}>
<View style={[isDesktopWeb && styles.containerDesktop, pal.border]}>
<ViewHeader title="Discover Feeds" showOnDesktop />
<HeaderWithInput
isInputFocused={isInputFocused}
query={query}
setIsInputFocused={setIsInputFocused}
onChangeQuery={onChangeQuery}
onPressClearQuery={onPressClearQuery}
onPressCancelSearch={onPressCancelSearch}
onSubmitQuery={onSubmitQuery}
showMenu={false}
/>
</View>
<FlatList
style={[!isDesktopWeb && s.flex1]}

View File

@ -40,10 +40,10 @@
tlds "^1.234.0"
typed-emitter "^2.1.0"
"@atproto/api@^0.4.2":
version "0.4.2"
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.4.2.tgz#7790eb049f72437e7454c8ecc29a5ef4201c1ade"
integrity sha512-bwaT+kIJp6wpzlHc1Rus3yi29GKlwvYp4wOWAFmcyYT4qH2ZlE6NfElgi6QwdQD285EhiIKYTv7CAMRp/QO7DQ==
"@atproto/api@^0.4.3":
version "0.4.3"
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.4.3.tgz#d7e478bf7009df2adaf1ac6051eb3e3fea185c90"
integrity sha512-8LdREwmoA58YQDrLS0rohd7cHokhoiXfyYEeNtNlkdO0w/2QpkUCQ1PgPBP2kIRM9PhOEkKp7W3Sn8Te9Qq8jg==
dependencies:
"@atproto/common-web" "*"
"@atproto/uri" "*"