diff options
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | src/App.native.tsx | 26 | ||||
-rw-r--r-- | src/App.web.tsx | 28 | ||||
-rw-r--r-- | src/lib/constants.ts | 107 | ||||
-rw-r--r-- | src/lib/react-query.ts | 3 | ||||
-rw-r--r-- | src/view/com/auth/onboarding/RecommendedFeeds.tsx | 70 | ||||
-rw-r--r-- | src/view/com/auth/onboarding/RecommendedFeedsItem.tsx | 11 | ||||
-rw-r--r-- | yarn.lock | 15 |
8 files changed, 108 insertions, 153 deletions
diff --git a/package.json b/package.json index baf4f2843..32629d029 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 09782a875..d43155bf3 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 ( - <ThemeProvider theme={rootStore.shell.colorMode}> - <RootSiblingParent> - <analytics.Provider> - <RootStoreProvider value={rootStore}> - <GestureHandlerRootView style={s.h100pct}> - <Shell /> - </GestureHandlerRootView> - </RootStoreProvider> - </analytics.Provider> - </RootSiblingParent> - </ThemeProvider> + <QueryClientProvider client={queryClient}> + <ThemeProvider theme={rootStore.shell.colorMode}> + <RootSiblingParent> + <analytics.Provider> + <RootStoreProvider value={rootStore}> + <GestureHandlerRootView style={s.h100pct}> + <Shell /> + </GestureHandlerRootView> + </RootStoreProvider> + </analytics.Provider> + </RootSiblingParent> + </ThemeProvider> + </QueryClientProvider> ) }) diff --git a/src/App.web.tsx b/src/App.web.tsx index 41a7189d3..a9123cc58 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<RootStoreModel | undefined>( @@ -30,18 +32,20 @@ const App = observer(function AppImpl() { } return ( - <ThemeProvider theme={rootStore.shell.colorMode}> - <RootSiblingParent> - <analytics.Provider> - <RootStoreProvider value={rootStore}> - <SafeAreaProvider> - <Shell /> - </SafeAreaProvider> - <ToastContainer /> - </RootStoreProvider> - </analytics.Provider> - </RootSiblingParent> - </ThemeProvider> + <QueryClientProvider client={queryClient}> + <ThemeProvider theme={rootStore.shell.colorMode}> + <RootSiblingParent> + <analytics.Provider> + <RootStoreProvider value={rootStore}> + <SafeAreaProvider> + <Shell /> + </SafeAreaProvider> + <ToastContainer /> + </RootStoreProvider> + </analytics.Provider> + </RootSiblingParent> + </ThemeProvider> + </QueryClientProvider> ) }) diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 94551e6ef..001cdf8c3 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 000000000..2a8f1d759 --- /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 99cdcafd0..8e29a5895 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}}> - <FlatList - data={RECOMMENDED_FEEDS} - renderItem={({item}) => <RecommendedFeedsItem {...item} />} - keyExtractor={item => item.did + item.rkey} - style={{flex: 1}} - /> + {hasFeeds ? ( + <FlatList + data={recommendedFeeds} + renderItem={({item}) => <RecommendedFeedsItem item={item} />} + keyExtractor={item => item.uri} + style={{flex: 1}} + /> + ) : isLoading ? ( + <View> + <ActivityIndicator size="large" /> + </View> + ) : ( + <ErrorMessage message="Failed to load recommended feeds" /> + )} </TitleColumnLayout> </TabletOrDesktop> <Mobile> @@ -106,12 +140,20 @@ export const RecommendedFeeds = observer(function RecommendedFeedsImpl({ pinned feeds. </Text> - <FlatList - data={RECOMMENDED_FEEDS} - renderItem={({item}) => <RecommendedFeedsItem {...item} />} - keyExtractor={item => item.did + item.rkey} - style={{flex: 1}} - /> + {hasFeeds ? ( + <FlatList + data={recommendedFeeds} + renderItem={({item}) => <RecommendedFeedsItem item={item} />} + keyExtractor={item => item.uri} + style={{flex: 1}} + /> + ) : isLoading ? ( + <View> + <ActivityIndicator size="large" /> + </View> + ) : ( + <ErrorMessage message="Failed to load recommended feeds" /> + )} <Button onPress={next} diff --git a/src/view/com/auth/onboarding/RecommendedFeedsItem.tsx b/src/view/com/auth/onboarding/RecommendedFeedsItem.tsx index e5d12273a..d130dc138 100644 --- a/src/view/com/auth/onboarding/RecommendedFeedsItem.tsx +++ b/src/view/com/auth/onboarding/RecommendedFeedsItem.tsx @@ -8,22 +8,17 @@ import {UserAvatar} from 'view/com/util/UserAvatar' import * as Toast from 'view/com/util/Toast' import {HeartIcon} from 'lib/icons' import {usePalette} from 'lib/hooks/usePalette' -import {useCustomFeed} from 'lib/hooks/useCustomFeed' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' -import {makeRecordUri} from 'lib/strings/url-helpers' import {sanitizeHandle} from 'lib/strings/handles' +import {CustomFeedModel} from 'state/models/feeds/custom-feed' export const RecommendedFeedsItem = observer(function RecommendedFeedsItemImpl({ - did, - rkey, + item, }: { - did: string - rkey: string + item: CustomFeedModel }) { const {isMobile} = useWebMediaQueries() const pal = usePalette('default') - const uri = makeRecordUri(did, 'app.bsky.feed.generator', rkey) - const item = useCustomFeed(uri) if (!item) return null const onToggle = async () => { if (item.isSaved) { diff --git a/yarn.lock b/yarn.lock index 308e3fd96..cba848b69 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6005,6 +6005,19 @@ "@svgr/plugin-svgo" "^5.5.0" loader-utils "^2.0.0" +"@tanstack/query-core@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.33.0.tgz#7756da9a75a424e521622b1d84eb55b7a2b33715" + integrity sha512-qYu73ptvnzRh6se2nyBIDHGBQvPY1XXl3yR769B7B6mIDD7s+EZhdlWHQ67JI6UOTFRaI7wupnTnwJ3gE0Mr/g== + +"@tanstack/react-query@^4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.33.0.tgz#e927b0343a6ecaa948fee59e9ca98fe561062638" + integrity sha512-97nGbmDK0/m0B86BdiXzx3EW9RcDYKpnyL2+WwyuLHEgpfThYAnXFaMMmnTDuAO4bQJXEhflumIEUfKmP7ESGA== + dependencies: + "@tanstack/query-core" "4.33.0" + use-sync-external-store "^1.2.0" + "@testing-library/jest-native@^5.4.1": version "5.4.2" resolved "https://registry.yarnpkg.com/@testing-library/jest-native/-/jest-native-5.4.2.tgz#6b0c987cc57f8d900763e763025d00d26ccbc85f" @@ -19293,7 +19306,7 @@ use-sidecar@^1.1.2: detect-node-es "^1.1.0" tslib "^2.0.0" -use-sync-external-store@^1.0.0: +use-sync-external-store@^1.0.0, use-sync-external-store@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== |