about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.eslintrc.js1
-rw-r--r--package.json2
-rw-r--r--src/state/models/discovery/feeds.ts19
-rw-r--r--src/view/com/auth/create/Step1.tsx2
-rw-r--r--src/view/com/search/HeaderWithInput.tsx24
-rw-r--r--src/view/screens/DiscoverFeeds.tsx43
-rw-r--r--yarn.lock8
7 files changed, 81 insertions, 18 deletions
diff --git a/.eslintrc.js b/.eslintrc.js
index 8a733a20c..3de954e43 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 3d52305ae..4bb540878 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 c484f7328..fa4054ff0 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 5038c8819..5d3dec430 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 0d65d98fd..2ec079dde 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 (
     <View style={[pal.view, pal.border, styles.header]}>
-      <TouchableOpacity
-        testID="viewHeaderBackOrMenuBtn"
-        onPress={onPressMenu}
-        hitSlop={MENU_HITSLOP}
-        style={styles.headerMenuBtn}
-        accessibilityRole="button"
-        accessibilityLabel="Menu"
-        accessibilityHint="Access navigation links and settings">
-        <FontAwesomeIcon icon="bars" size={18} color={pal.colors.textLight} />
-      </TouchableOpacity>
+      {showMenu ? (
+        <TouchableOpacity
+          testID="viewHeaderBackOrMenuBtn"
+          onPress={onPressMenu}
+          hitSlop={MENU_HITSLOP}
+          style={styles.headerMenuBtn}
+          accessibilityRole="button"
+          accessibilityLabel="Menu"
+          accessibilityHint="Access navigation links and settings">
+          <FontAwesomeIcon icon="bars" size={18} color={pal.colors.textLight} />
+        </TouchableOpacity>
+      ) : null}
       <View
         style={[
           {backgroundColor: pal.colors.backgroundLight},
diff --git a/src/view/screens/DiscoverFeeds.tsx b/src/view/screens/DiscoverFeeds.tsx
index b6a6744db..e7b685ebc 100644
--- a/src/view/screens/DiscoverFeeds.tsx
+++ b/src/view/screens/DiscoverFeeds.tsx
@@ -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]}
diff --git a/yarn.lock b/yarn.lock
index 4217fb1be..fe1296aca 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -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" "*"