custom feed screen
parent
61ea37ff81
commit
5010861160
|
@ -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} />
|
||||
</>
|
||||
|
|
|
@ -21,6 +21,7 @@ export type CommonNavigatorParams = {
|
|||
CopyrightPolicy: undefined
|
||||
AppPasswords: undefined
|
||||
SavedFeeds: undefined
|
||||
CustomFeed: {name: string; rkey: string}
|
||||
MutedAccounts: undefined
|
||||
BlockedAccounts: undefined
|
||||
}
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -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 || '',
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
|
@ -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%',
|
||||
},
|
||||
})
|
Loading…
Reference in New Issue