show algos by user on profile
parent
fa4af20764
commit
760b5309e0
|
@ -1,9 +1,7 @@
|
||||||
import {makeAutoObservable} from 'mobx'
|
import {makeAutoObservable} from 'mobx'
|
||||||
import {
|
import {
|
||||||
AppBskyFeedGetBookmarkedFeeds as GetBookmarkedFeeds,
|
|
||||||
// AppBskyFeedBookmarkFeed as bookmarkedFeed,
|
|
||||||
// AppBskyFeedUnbookmarkFeed as unbookmarkFeed,
|
|
||||||
AppBskyFeedDefs as FeedDefs,
|
AppBskyFeedDefs as FeedDefs,
|
||||||
|
AppBskyFeedGetActorFeeds as GetActorFeeds,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {RootStoreModel} from '../root-store'
|
import {RootStoreModel} from '../root-store'
|
||||||
import {bundleAsync} from 'lib/async/bundle'
|
import {bundleAsync} from 'lib/async/bundle'
|
||||||
|
@ -23,7 +21,10 @@ export class ActorFeedsModel {
|
||||||
// data
|
// data
|
||||||
feeds: FeedDefs.GeneratorView[] = []
|
feeds: FeedDefs.GeneratorView[] = []
|
||||||
|
|
||||||
constructor(public rootStore: RootStoreModel) {
|
constructor(
|
||||||
|
public rootStore: RootStoreModel,
|
||||||
|
public params: GetActorFeeds.QueryParams,
|
||||||
|
) {
|
||||||
makeAutoObservable(
|
makeAutoObservable(
|
||||||
this,
|
this,
|
||||||
{
|
{
|
||||||
|
@ -69,10 +70,11 @@ export class ActorFeedsModel {
|
||||||
this._xLoading(replace)
|
this._xLoading(replace)
|
||||||
try {
|
try {
|
||||||
const res = await this.rootStore.agent.app.bsky.feed.getActorFeeds({
|
const res = await this.rootStore.agent.app.bsky.feed.getActorFeeds({
|
||||||
actor: 'did:plc:dpny6d4qwwxu5b6dp3qob5ok', // TODO: take this as input param
|
actor: this.params.actor,
|
||||||
limit: PAGE_SIZE,
|
limit: PAGE_SIZE,
|
||||||
cursor: replace ? undefined : this.loadMoreCursor,
|
cursor: replace ? undefined : this.loadMoreCursor,
|
||||||
})
|
})
|
||||||
|
console.log('res', res.data.feeds)
|
||||||
if (replace) {
|
if (replace) {
|
||||||
this._replaceAll(res)
|
this._replaceAll(res)
|
||||||
} else {
|
} else {
|
||||||
|
@ -106,12 +108,12 @@ export class ActorFeedsModel {
|
||||||
// helper functions
|
// helper functions
|
||||||
// =
|
// =
|
||||||
|
|
||||||
_replaceAll(res: GetBookmarkedFeeds.Response) {
|
_replaceAll(res: GetActorFeeds.Response) {
|
||||||
this.feeds = []
|
this.feeds = []
|
||||||
this._appendAll(res)
|
this._appendAll(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
_appendAll(res: GetBookmarkedFeeds.Response) {
|
_appendAll(res: GetActorFeeds.Response) {
|
||||||
this.loadMoreCursor = res.data.cursor
|
this.loadMoreCursor = res.data.cursor
|
||||||
this.hasMore = !!this.loadMoreCursor
|
this.hasMore = !!this.loadMoreCursor
|
||||||
this.feeds = this.feeds.concat(res.data.feeds)
|
this.feeds = this.feeds.concat(res.data.feeds)
|
||||||
|
|
|
@ -2,13 +2,20 @@ import {makeAutoObservable} from 'mobx'
|
||||||
import {RootStoreModel} from '../root-store'
|
import {RootStoreModel} from '../root-store'
|
||||||
import {ProfileModel} from '../content/profile'
|
import {ProfileModel} from '../content/profile'
|
||||||
import {PostsFeedModel} from '../feeds/posts'
|
import {PostsFeedModel} from '../feeds/posts'
|
||||||
|
import {ActorFeedsModel} from '../feeds/actor'
|
||||||
|
import {AppBskyFeedDefs} from '@atproto/api'
|
||||||
|
|
||||||
export enum Sections {
|
export enum Sections {
|
||||||
Posts = 'Posts',
|
Posts = 'Posts',
|
||||||
PostsWithReplies = 'Posts & replies',
|
PostsWithReplies = 'Posts & replies',
|
||||||
|
CustomAlgorithms = 'Algos',
|
||||||
}
|
}
|
||||||
|
|
||||||
const USER_SELECTOR_ITEMS = [Sections.Posts, Sections.PostsWithReplies]
|
const USER_SELECTOR_ITEMS = [
|
||||||
|
Sections.Posts,
|
||||||
|
Sections.PostsWithReplies,
|
||||||
|
Sections.CustomAlgorithms,
|
||||||
|
]
|
||||||
|
|
||||||
export interface ProfileUiParams {
|
export interface ProfileUiParams {
|
||||||
user: string
|
user: string
|
||||||
|
@ -22,6 +29,7 @@ export class ProfileUiModel {
|
||||||
// data
|
// data
|
||||||
profile: ProfileModel
|
profile: ProfileModel
|
||||||
feed: PostsFeedModel
|
feed: PostsFeedModel
|
||||||
|
algos: ActorFeedsModel
|
||||||
|
|
||||||
// ui state
|
// ui state
|
||||||
selectedViewIndex = 0
|
selectedViewIndex = 0
|
||||||
|
@ -43,15 +51,19 @@ export class ProfileUiModel {
|
||||||
actor: params.user,
|
actor: params.user,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
})
|
})
|
||||||
|
this.algos = new ActorFeedsModel(rootStore, {actor: params.user})
|
||||||
}
|
}
|
||||||
|
|
||||||
get currentView(): PostsFeedModel {
|
get currentView(): PostsFeedModel | ActorFeedsModel {
|
||||||
if (
|
if (
|
||||||
this.selectedView === Sections.Posts ||
|
this.selectedView === Sections.Posts ||
|
||||||
this.selectedView === Sections.PostsWithReplies
|
this.selectedView === Sections.PostsWithReplies
|
||||||
) {
|
) {
|
||||||
return this.feed
|
return this.feed
|
||||||
}
|
}
|
||||||
|
if (this.selectedView === Sections.CustomAlgorithms) {
|
||||||
|
return this.algos
|
||||||
|
}
|
||||||
throw new Error(`Invalid selector value: ${this.selectedViewIndex}`)
|
throw new Error(`Invalid selector value: ${this.selectedViewIndex}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,12 +83,17 @@ export class ProfileUiModel {
|
||||||
get selectedView() {
|
get selectedView() {
|
||||||
return this.selectorItems[this.selectedViewIndex]
|
return this.selectorItems[this.selectedViewIndex]
|
||||||
}
|
}
|
||||||
|
isGeneratorView(v: any) {
|
||||||
|
return AppBskyFeedDefs.isGeneratorView(v)
|
||||||
|
}
|
||||||
|
|
||||||
get uiItems() {
|
get uiItems() {
|
||||||
let arr: any[] = []
|
let arr: any[] = []
|
||||||
|
// if loading, return loading item to show loading spinner
|
||||||
if (this.isInitialLoading) {
|
if (this.isInitialLoading) {
|
||||||
arr = arr.concat([ProfileUiModel.LOADING_ITEM])
|
arr = arr.concat([ProfileUiModel.LOADING_ITEM])
|
||||||
} else if (this.currentView.hasError) {
|
} else if (this.currentView.hasError) {
|
||||||
|
// if error, return error item to show error message
|
||||||
arr = arr.concat([
|
arr = arr.concat([
|
||||||
{
|
{
|
||||||
_reactKey: '__error__',
|
_reactKey: '__error__',
|
||||||
|
@ -84,12 +101,16 @@ export class ProfileUiModel {
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
} else {
|
} else {
|
||||||
|
// not loading, no error, show content
|
||||||
if (
|
if (
|
||||||
this.selectedView === Sections.Posts ||
|
this.selectedView === Sections.Posts ||
|
||||||
this.selectedView === Sections.PostsWithReplies
|
this.selectedView === Sections.PostsWithReplies ||
|
||||||
|
this.selectedView === Sections.CustomAlgorithms
|
||||||
) {
|
) {
|
||||||
if (this.feed.hasContent) {
|
if (this.feed.hasContent) {
|
||||||
if (this.selectedView === Sections.Posts) {
|
if (this.selectedView === Sections.CustomAlgorithms) {
|
||||||
|
arr = this.algos.feeds
|
||||||
|
} else if (this.selectedView === Sections.Posts) {
|
||||||
arr = this.feed.nonReplyFeed
|
arr = this.feed.nonReplyFeed
|
||||||
} else {
|
} else {
|
||||||
arr = this.feed.slices.slice()
|
arr = this.feed.slices.slice()
|
||||||
|
@ -101,6 +122,7 @@ export class ProfileUiModel {
|
||||||
arr = arr.concat([ProfileUiModel.EMPTY_ITEM])
|
arr = arr.concat([ProfileUiModel.EMPTY_ITEM])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// fallback, add empty item, to show empty message
|
||||||
arr = arr.concat([ProfileUiModel.EMPTY_ITEM])
|
arr = arr.concat([ProfileUiModel.EMPTY_ITEM])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
import React from 'react'
|
||||||
|
import {StyleSheet, View} from 'react-native'
|
||||||
|
import {Text} from '../util/text/Text'
|
||||||
|
import {AppBskyFeedDefs} from '@atproto/api'
|
||||||
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
import {s} from 'lib/styles'
|
||||||
|
import {UserAvatar} from '../util/UserAvatar'
|
||||||
|
|
||||||
|
const AlgoItem = ({item}: {item: AppBskyFeedDefs.GeneratorView}) => {
|
||||||
|
const pal = usePalette('default')
|
||||||
|
return (
|
||||||
|
<View style={[styles.container]} key={item.uri}>
|
||||||
|
<View style={[styles.headerContainer]}>
|
||||||
|
<View style={[s.mr20]}>
|
||||||
|
<UserAvatar size={56} avatar={item.avatar} />
|
||||||
|
</View>
|
||||||
|
<View style={[styles.headerTextContainer]}>
|
||||||
|
<Text style={[pal.text, s.bold]}>
|
||||||
|
{item.displayName ?? 'Feed name'}
|
||||||
|
</Text>
|
||||||
|
<Text style={[pal.textLight, styles.description]}>
|
||||||
|
{item.description ??
|
||||||
|
'THIS IS A FEED DESCRIPTION, IT WILL TELL YOU WHAT THE FEED IS ABOUT. THIS IS A COOL FEED ABOUT COOL PEOPLE.'}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* TODO: this feed is like by *3* people UserAvatars and others */}
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AlgoItem
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
paddingHorizontal: 18,
|
||||||
|
paddingVertical: 20,
|
||||||
|
flexDirection: 'column',
|
||||||
|
columnGap: 36,
|
||||||
|
flex: 1,
|
||||||
|
borderTopWidth: 1,
|
||||||
|
borderTopColor: '#E5E5E5',
|
||||||
|
},
|
||||||
|
headerContainer: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
},
|
||||||
|
headerTextContainer: {
|
||||||
|
flexDirection: 'column',
|
||||||
|
columnGap: 4,
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
flex: 1,
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
},
|
||||||
|
})
|
|
@ -21,6 +21,8 @@ import {FAB} from '../com/util/fab/FAB'
|
||||||
import {s, colors} from 'lib/styles'
|
import {s, colors} from 'lib/styles'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics'
|
||||||
import {ComposeIcon2} from 'lib/icons'
|
import {ComposeIcon2} from 'lib/icons'
|
||||||
|
import {AppBskyFeedDefs} from '@atproto/api'
|
||||||
|
import AlgoItem from 'view/com/algos/AlgoItem'
|
||||||
|
|
||||||
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Profile'>
|
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Profile'>
|
||||||
export const ProfileScreen = withAuthRequired(
|
export const ProfileScreen = withAuthRequired(
|
||||||
|
@ -152,15 +154,14 @@ export const ProfileScreen = withAuthRequired(
|
||||||
)
|
)
|
||||||
} else if (item instanceof PostsFeedSliceModel) {
|
} else if (item instanceof PostsFeedSliceModel) {
|
||||||
return <FeedSlice slice={item} ignoreMuteFor={uiState.profile.did} />
|
return <FeedSlice slice={item} ignoreMuteFor={uiState.profile.did} />
|
||||||
|
} else if (item.creator) {
|
||||||
|
// TODO: this is a hack to see if it is a custom feed. fix it to something more robust
|
||||||
|
const typedItem = item as AppBskyFeedDefs.GeneratorView
|
||||||
|
return <AlgoItem item={typedItem} />
|
||||||
}
|
}
|
||||||
return <View />
|
return <View />
|
||||||
},
|
},
|
||||||
[
|
[onPressTryAgain, uiState],
|
||||||
onPressTryAgain,
|
|
||||||
uiState.profile.did,
|
|
||||||
uiState.feed.isBlocking,
|
|
||||||
uiState.feed.isBlockedBy,
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
Loading…
Reference in New Issue