From 38d78e16bffc9a25a45a4ad41caeef2c075daa26 Mon Sep 17 00:00:00 2001 From: Ansh Date: Fri, 28 Jul 2023 08:29:37 -0700 Subject: [PATCH] Search custom feeds (#1031) * paginate custom feeds * basic search * update `@atproto/api` * use search from the API * debounce search for 200ms --- .eslintrc.js | 1 + package.json | 2 +- src/state/models/discovery/feeds.ts | 19 +++++++++-- src/view/com/auth/create/Step1.tsx | 2 +- src/view/com/search/HeaderWithInput.tsx | 24 ++++++++------ src/view/screens/DiscoverFeeds.tsx | 43 +++++++++++++++++++++++++ yarn.lock | 8 ++--- 7 files changed, 81 insertions(+), 18 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 8a733a20..3de954e4 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -15,6 +15,7 @@ module.exports = { 'coverage', '*.lock', '.husky', + 'patches', ], overrides: [ { diff --git a/package.json b/package.json index 3d52305a..4bb54087 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/state/models/discovery/feeds.ts b/src/state/models/discovery/feeds.ts index c484f732..fa4054ff 100644 --- a/src/state/models/discovery/feeds.ts +++ b/src/state/models/discovery/feeds.ts @@ -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 = '' } diff --git a/src/view/com/auth/create/Step1.tsx b/src/view/com/auth/create/Step1.tsx index 5038c881..5d3dec43 100644 --- a/src/view/com/auth/create/Step1.tsx +++ b/src/view/com/auth/create/Step1.tsx @@ -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], ) diff --git a/src/view/com/search/HeaderWithInput.tsx b/src/view/com/search/HeaderWithInput.tsx index 0d65d98f..2ec079dd 100644 --- a/src/view/com/search/HeaderWithInput.tsx +++ b/src/view/com/search/HeaderWithInput.tsx @@ -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,16 +51,18 @@ export function HeaderWithInput({ return ( - - - + {showMenu ? ( + + + + ) : null} 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(false) + const [query, setQuery] = React.useState('') + 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( +