diff --git a/package.json b/package.json
index baf4f284..32629d02 100644
--- a/package.json
+++ b/package.json
@@ -53,6 +53,7 @@
"@segment/analytics-react-native": "^2.10.1",
"@segment/sovran-react-native": "^0.4.5",
"@sentry/react-native": "5.5.0",
+ "@tanstack/react-query": "^4.33.0",
"@tiptap/core": "^2.0.0-beta.220",
"@tiptap/extension-document": "^2.0.0-beta.220",
"@tiptap/extension-hard-break": "^2.0.3",
diff --git a/src/App.native.tsx b/src/App.native.tsx
index 09782a87..d43155bf 100644
--- a/src/App.native.tsx
+++ b/src/App.native.tsx
@@ -16,6 +16,8 @@ import * as notifications from 'lib/notifications/notifications'
import * as analytics from 'lib/analytics/analytics'
import * as Toast from './view/com/util/Toast'
import {handleLink} from './Navigation'
+import {QueryClientProvider} from '@tanstack/react-query'
+import {queryClient} from 'lib/react-query'
SplashScreen.preventAutoHideAsync()
@@ -51,17 +53,19 @@ const App = observer(function AppImpl() {
return null
}
return (
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
)
})
diff --git a/src/App.web.tsx b/src/App.web.tsx
index 41a7189d..a9123cc5 100644
--- a/src/App.web.tsx
+++ b/src/App.web.tsx
@@ -9,6 +9,8 @@ import {Shell} from './view/shell/index'
import {ToastContainer} from './view/com/util/Toast.web'
import {ThemeProvider} from 'lib/ThemeContext'
import {observer} from 'mobx-react-lite'
+import {QueryClientProvider} from '@tanstack/react-query'
+import {queryClient} from 'lib/react-query'
const App = observer(function AppImpl() {
const [rootStore, setRootStore] = useState(
@@ -30,18 +32,20 @@ const App = observer(function AppImpl() {
}
return (
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
)
})
diff --git a/src/lib/constants.ts b/src/lib/constants.ts
index 94551e6e..001cdf8c 100644
--- a/src/lib/constants.ts
+++ b/src/lib/constants.ts
@@ -148,110 +148,3 @@ export const HITSLOP_10 = createHitslop(10)
export const HITSLOP_20 = createHitslop(20)
export const HITSLOP_30 = createHitslop(30)
export const BACK_HITSLOP = HITSLOP_30
-
-export const RECOMMENDED_FEEDS = [
- {
- did: 'did:plc:hsqwcidfez66lwm3gxhfv5in',
- rkey: 'aaaf2pqeodmpy',
- },
- {
- did: 'did:plc:gekdk2nd47gkk3utfz2xf7cn',
- rkey: 'aaap4tbjcfe5y',
- },
- {
- did: 'did:plc:5rw2on4i56btlcajojaxwcat',
- rkey: 'aaao6g552b33o',
- },
- {
- did: 'did:plc:jfhpnnst6flqway4eaeqzj2a',
- rkey: 'for-science',
- },
- {
- did: 'did:plc:7q4nnnxawajbfaq7to5dpbsy',
- rkey: 'bsky-news',
- },
- {
- did: 'did:plc:jcoy7v3a2t4rcfdh6i4kza25',
- rkey: 'astro',
- },
- {
- did: 'did:plc:tenurhgjptubkk5zf5qhi3og',
- rkey: 'h-nba',
- },
- {
- did: 'did:plc:vpkhqolt662uhesyj6nxm7ys',
- rkey: 'devfeed',
- },
- {
- did: 'did:plc:cndfx4udwgvpjaakvxvh7wm5',
- rkey: 'flipboard-tech',
- },
- {
- did: 'did:plc:w4xbfzo7kqfes5zb7r6qv3rw',
- rkey: 'blacksky',
- },
- {
- did: 'did:plc:lptjvw6ut224kwrj7ub3sqbe',
- rkey: 'aaaotfjzjplna',
- },
- {
- did: 'did:plc:gkvpokm7ec5j5yxls6xk4e3z',
- rkey: 'formula-one',
- },
- {
- did: 'did:plc:q6gjnaw2blty4crticxkmujt',
- rkey: 'positivifeed',
- },
- {
- did: 'did:plc:l72uci4styb4jucsgcrrj5ap',
- rkey: 'aaao5dzfm36u4',
- },
- {
- did: 'did:plc:k3jkadxv5kkjgs6boyon7m6n',
- rkey: 'aaaavlyvqzst2',
- },
- {
- did: 'did:plc:nkahctfdi6bxk72umytfwghw',
- rkey: 'aaado2uvfsc6w',
- },
- {
- did: 'did:plc:epihigio3d7un7u3gpqiy5gv',
- rkey: 'aaaekwsc7zsvs',
- },
- {
- did: 'did:plc:qiknc4t5rq7yngvz7g4aezq7',
- rkey: 'aaaejxlobe474',
- },
- {
- did: 'did:plc:mlq4aycufcuolr7ax6sezpc4',
- rkey: 'aaaoudweck6uy',
- },
- {
- did: 'did:plc:rcez5hcvq3vzlu5x7xrjyccg',
- rkey: 'aaadzjxbcddzi',
- },
- {
- did: 'did:plc:lnxbuzaenlwjrncx6sc4cfdr',
- rkey: 'aaab2vesjtszc',
- },
- {
- did: 'did:plc:x3cya3wkt4n6u4ihmvpsc5if',
- rkey: 'aaacynbxwimok',
- },
- {
- did: 'did:plc:abv47bjgzjgoh3yrygwoi36x',
- rkey: 'aaagt6amuur5e',
- },
- {
- did: 'did:plc:ffkgesg3jsv2j7aagkzrtcvt',
- rkey: 'aaacjerk7gwek',
- },
- {
- did: 'did:plc:geoqe3qls5mwezckxxsewys2',
- rkey: 'aaai43yetqshu',
- },
- {
- did: 'did:plc:2wqomm3tjqbgktbrfwgvrw34',
- rkey: 'authors',
- },
-]
diff --git a/src/lib/react-query.ts b/src/lib/react-query.ts
new file mode 100644
index 00000000..2a8f1d75
--- /dev/null
+++ b/src/lib/react-query.ts
@@ -0,0 +1,3 @@
+import {QueryClient} from '@tanstack/react-query'
+
+export const queryClient = new QueryClient()
diff --git a/src/view/com/auth/onboarding/RecommendedFeeds.tsx b/src/view/com/auth/onboarding/RecommendedFeeds.tsx
index 99cdcafd..8e29a589 100644
--- a/src/view/com/auth/onboarding/RecommendedFeeds.tsx
+++ b/src/view/com/auth/onboarding/RecommendedFeeds.tsx
@@ -1,5 +1,5 @@
import React from 'react'
-import {FlatList, StyleSheet, View} from 'react-native'
+import {ActivityIndicator, FlatList, StyleSheet, View} from 'react-native'
import {observer} from 'mobx-react-lite'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {TabletOrDesktop, Mobile} from 'view/com/util/layouts/Breakpoints'
@@ -10,7 +10,10 @@ import {Button} from 'view/com/util/forms/Button'
import {RecommendedFeedsItem} from './RecommendedFeedsItem'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {usePalette} from 'lib/hooks/usePalette'
-import {RECOMMENDED_FEEDS} from 'lib/constants'
+import {useQuery} from '@tanstack/react-query'
+import {useStores} from 'state/index'
+import {CustomFeedModel} from 'state/models/feeds/custom-feed'
+import {ErrorMessage} from 'view/com/util/error/ErrorMessage'
type Props = {
next: () => void
@@ -18,8 +21,31 @@ type Props = {
export const RecommendedFeeds = observer(function RecommendedFeedsImpl({
next,
}: Props) {
+ const store = useStores()
const pal = usePalette('default')
const {isTabletOrMobile} = useWebMediaQueries()
+ const {isLoading, data: recommendedFeeds} = useQuery({
+ staleTime: Infinity, // fixed list rn, never refetch
+ queryKey: ['onboarding', 'recommended_feeds'],
+ async queryFn() {
+ try {
+ const {
+ data: {feeds},
+ success,
+ } = await store.agent.app.bsky.feed.getSuggestedFeeds()
+
+ if (!success) return
+
+ return (feeds.length ? feeds : []).map(feed => {
+ return new CustomFeedModel(store, feed)
+ })
+ } catch (e) {
+ return
+ }
+ },
+ })
+
+ const hasFeeds = recommendedFeeds && recommendedFeeds.length
const title = (
<>
@@ -86,12 +112,20 @@ export const RecommendedFeeds = observer(function RecommendedFeedsImpl({
horizontal
titleStyle={isTabletOrMobile ? undefined : {minWidth: 470}}
contentStyle={{paddingHorizontal: 0}}>
- }
- keyExtractor={item => item.did + item.rkey}
- style={{flex: 1}}
- />
+ {hasFeeds ? (
+ }
+ keyExtractor={item => item.uri}
+ style={{flex: 1}}
+ />
+ ) : isLoading ? (
+
+
+
+ ) : (
+
+ )}
@@ -106,12 +140,20 @@ export const RecommendedFeeds = observer(function RecommendedFeedsImpl({
pinned feeds.
- }
- keyExtractor={item => item.did + item.rkey}
- style={{flex: 1}}
- />
+ {hasFeeds ? (
+ }
+ keyExtractor={item => item.uri}
+ style={{flex: 1}}
+ />
+ ) : isLoading ? (
+
+
+
+ ) : (
+
+ )}