diff options
author | Ansh Nanda <anshnanda10@gmail.com> | 2023-05-15 10:42:23 -0700 |
---|---|---|
committer | Ansh Nanda <anshnanda10@gmail.com> | 2023-05-15 10:42:23 -0700 |
commit | 50108611600ae2addb3bff4f00562b02f9c35fdf (patch) | |
tree | d2c19ce838b0957556d991d87e61471ae4cd9fba /src | |
parent | 61ea37ff818ca64cec8e10b3a423ecd22dcf0141 (diff) | |
download | voidsky-50108611600ae2addb3bff4f00562b02f9c35fdf.tar.zst |
custom feed screen
Diffstat (limited to 'src')
-rw-r--r-- | src/Navigation.tsx | 2 | ||||
-rw-r--r-- | src/lib/routes/types.ts | 1 | ||||
-rw-r--r-- | src/routes.ts | 1 | ||||
-rw-r--r-- | src/state/models/feeds/algo/algo-item.ts | 20 | ||||
-rw-r--r-- | src/state/models/feeds/posts.ts | 31 | ||||
-rw-r--r-- | src/view/com/algos/AlgoItem.tsx | 24 | ||||
-rw-r--r-- | src/view/screens/CustomFeed.tsx | 50 |
7 files changed, 119 insertions, 10 deletions
diff --git a/src/Navigation.tsx b/src/Navigation.tsx index 26dc9f7ad..d4c992eb6 100644 --- a/src/Navigation.tsx +++ b/src/Navigation.tsx @@ -53,6 +53,7 @@ import {MutedAccounts} from 'view/screens/MutedAccounts' import {BlockedAccounts} from 'view/screens/BlockedAccounts' import {getRoutingInstrumentation} from 'lib/sentry' import {SavedFeeds} from './view/screens/SavedFeeds' +import {CustomFeed} from './view/screens/CustomFeed' const navigationRef = createNavigationContainerRef<AllNavigatorParams>() @@ -93,6 +94,7 @@ function commonScreens(Stack: typeof HomeTab) { <Stack.Screen name="CopyrightPolicy" component={CopyrightPolicyScreen} /> <Stack.Screen name="AppPasswords" component={AppPasswords} /> <Stack.Screen name="SavedFeeds" component={SavedFeeds} /> + <Stack.Screen name="CustomFeed" component={CustomFeed} /> <Stack.Screen name="MutedAccounts" component={MutedAccounts} /> <Stack.Screen name="BlockedAccounts" component={BlockedAccounts} /> </> diff --git a/src/lib/routes/types.ts b/src/lib/routes/types.ts index 5a4126f6a..29fadd709 100644 --- a/src/lib/routes/types.ts +++ b/src/lib/routes/types.ts @@ -21,6 +21,7 @@ export type CommonNavigatorParams = { CopyrightPolicy: undefined AppPasswords: undefined SavedFeeds: undefined + CustomFeed: {name: string; rkey: string} MutedAccounts: undefined BlockedAccounts: undefined } diff --git a/src/routes.ts b/src/routes.ts index b510f66f6..2cdaa28bb 100644 --- a/src/routes.ts +++ b/src/routes.ts @@ -15,6 +15,7 @@ export const router = new Router({ Log: '/sys/log', AppPasswords: '/settings/app-passwords', SavedFeeds: '/settings/saved-feeds', + CustomFeed: '/profile/:name/feed/:rkey', MutedAccounts: '/settings/muted-accounts', BlockedAccounts: '/settings/blocked-accounts', Support: '/support', diff --git a/src/state/models/feeds/algo/algo-item.ts b/src/state/models/feeds/algo/algo-item.ts index 88e9c0662..3dee5e2bf 100644 --- a/src/state/models/feeds/algo/algo-item.ts +++ b/src/state/models/feeds/algo/algo-item.ts @@ -29,6 +29,10 @@ export class AlgoItemModel { } } + get getUri() { + return this.data.uri + } + // public apis // = async save() { @@ -52,4 +56,20 @@ export class AlgoItemModel { this.rootStore.log.error('Failed to unsanve feed', e) } } + + // async getFeedSkeleton() { + // const res = await this.rootStore.agent.app.bsky.feed.getFeedSkeleton({ + // feed: this.data.uri, + // }) + // const skeleton = res.data.feed + // console.log('skeleton', skeleton) + // return skeleton + // } + // async getFeed() { + // const feed = await this.rootStore.agent.app.bsky.feed.getFeed({ + // feed: this.data.uri, + // }) + // console.log('feed', feed) + // return feed + // } } diff --git a/src/state/models/feeds/posts.ts b/src/state/models/feeds/posts.ts index 44cec3af7..7adc1cb1c 100644 --- a/src/state/models/feeds/posts.ts +++ b/src/state/models/feeds/posts.ts @@ -4,6 +4,7 @@ import { AppBskyFeedDefs, AppBskyFeedPost, AppBskyFeedGetAuthorFeed as GetAuthorFeed, + AppBskyFeedGetFeed as GetCustomFeed, RichText, jsonToLex, } from '@atproto/api' @@ -305,8 +306,11 @@ export class PostsFeedModel { constructor( public rootStore: RootStoreModel, - public feedType: 'home' | 'author' | 'suggested' | 'goodstuff', - params: GetTimeline.QueryParams | GetAuthorFeed.QueryParams, + public feedType: 'home' | 'author' | 'suggested' | 'goodstuff' | 'custom', + params: + | GetTimeline.QueryParams + | GetAuthorFeed.QueryParams + | GetCustomFeed.QueryParams, ) { makeAutoObservable( this, @@ -595,13 +599,15 @@ export class PostsFeedModel { // helper functions // = - async _replaceAll(res: GetTimeline.Response | GetAuthorFeed.Response) { + async _replaceAll( + res: GetTimeline.Response | GetAuthorFeed.Response | GetCustomFeed.Response, + ) { this.pollCursor = res.data.feed[0]?.post.uri return this._appendAll(res, true) } async _appendAll( - res: GetTimeline.Response | GetAuthorFeed.Response, + res: GetTimeline.Response | GetAuthorFeed.Response | GetCustomFeed.Response, replace = false, ) { this.loadMoreCursor = res.data.cursor @@ -640,7 +646,9 @@ export class PostsFeedModel { }) } - _updateAll(res: GetTimeline.Response | GetAuthorFeed.Response) { + _updateAll( + res: GetTimeline.Response | GetAuthorFeed.Response | GetCustomFeed.Response, + ) { for (const item of res.data.feed) { const existingSlice = this.slices.find(slice => slice.containsUri(item.post.uri), @@ -657,8 +665,13 @@ export class PostsFeedModel { } protected async _getFeed( - params: GetTimeline.QueryParams | GetAuthorFeed.QueryParams = {}, - ): Promise<GetTimeline.Response | GetAuthorFeed.Response> { + params: + | GetTimeline.QueryParams + | GetAuthorFeed.QueryParams + | GetCustomFeed.QueryParams, + ): Promise< + GetTimeline.Response | GetAuthorFeed.Response | GetCustomFeed.Response + > { params = Object.assign({}, this.params, params) if (this.feedType === 'suggested') { const responses = await getMultipleAuthorsPosts( @@ -680,6 +693,10 @@ export class PostsFeedModel { } } else if (this.feedType === 'home') { return this.rootStore.agent.getTimeline(params as GetTimeline.QueryParams) + } else if (this.feedType === 'custom') { + return this.rootStore.agent.app.bsky.feed.getFeed( + params as GetCustomFeed.QueryParams, + ) } else if (this.feedType === 'goodstuff') { const res = await getGoodStuff( this.rootStore.session.currentSession?.accessJwt || '', diff --git a/src/view/com/algos/AlgoItem.tsx b/src/view/com/algos/AlgoItem.tsx index e475624c5..51de89bd6 100644 --- a/src/view/com/algos/AlgoItem.tsx +++ b/src/view/com/algos/AlgoItem.tsx @@ -1,5 +1,11 @@ import React from 'react' -import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native' +import { + StyleProp, + StyleSheet, + View, + ViewStyle, + TouchableOpacity, +} from 'react-native' import {Text} from '../util/text/Text' import {usePalette} from 'lib/hooks/usePalette' import {s} from 'lib/styles' @@ -7,13 +13,25 @@ import {UserAvatar} from '../util/UserAvatar' import {Button} from '../util/forms/Button' import {observer} from 'mobx-react-lite' import {AlgoItemModel} from 'state/models/feeds/algo/algo-item' +import {useNavigation} from '@react-navigation/native' +import {NavigationProp} from 'lib/routes/types' const AlgoItem = observer( ({item, style}: {item: AlgoItemModel; style?: StyleProp<ViewStyle>}) => { const pal = usePalette('default') + const navigation = useNavigation<NavigationProp>() return ( - <View style={[styles.container, style]} key={item.data.uri}> + <TouchableOpacity + accessibilityRole="button" + style={[styles.container, style]} + onPress={() => { + navigation.navigate('CustomFeed', { + name: item.data.creator.did, + rkey: item.data.uri, + }) + }} + key={item.data.uri}> <View style={[styles.headerContainer]}> <View style={[s.mr10]}> <UserAvatar size={36} avatar={item.data.avatar} /> @@ -54,7 +72,7 @@ const AlgoItem = observer( /> </View> </View> - </View> + </TouchableOpacity> ) }, ) diff --git a/src/view/screens/CustomFeed.tsx b/src/view/screens/CustomFeed.tsx new file mode 100644 index 000000000..1d4343b29 --- /dev/null +++ b/src/view/screens/CustomFeed.tsx @@ -0,0 +1,50 @@ +import {NativeStackScreenProps} from '@react-navigation/native-stack' +import {CommonNavigatorParams} from 'lib/routes/types' +import {observer} from 'mobx-react-lite' +import React, {useEffect, useMemo, useRef} from 'react' +import {FlatList, StyleSheet, View} from 'react-native' +import {useStores} from 'state/index' +import {AlgoItemModel} from 'state/models/feeds/algo/algo-item' +import {PostsFeedModel} from 'state/models/feeds/posts' +import {withAuthRequired} from 'view/com/auth/withAuthRequired' +import {Feed} from 'view/com/posts/Feed' +import {ViewHeader} from 'view/com/util/ViewHeader' +import {Text} from 'view/com/util/text/Text' + +type Props = NativeStackScreenProps<CommonNavigatorParams, 'CustomFeed'> +export const CustomFeed = withAuthRequired( + observer(({route}: Props) => { + const rootStore = useStores() + const scrollElRef = useRef<FlatList>(null) + + const {rkey, name} = route.params + + const algoFeed: PostsFeedModel = useMemo(() => { + const feed = new PostsFeedModel(rootStore, 'custom', { + feed: rkey, + }) + feed.setup() + return feed + }, [rkey, rootStore]) + + return ( + <View style={[styles.container]}> + <ViewHeader title={'Custom Feed'} showOnDesktop /> + + <Feed + scrollElRef={scrollElRef} + testID={'test-feed'} + key="default" + feed={algoFeed} + /> + </View> + ) + }), +) + +const styles = StyleSheet.create({ + container: { + flex: 1, + height: '100%', + }, +}) |