Bluesky app fork with some witchin' additions 馃挮
at main 107 lines 2.7 kB view raw
1import {type AppBskyFeedDefs, type BskyAgent} from '@atproto/api' 2 3import {PROD_DEFAULT_FEED} from '#/lib/constants' 4import {CustomFeedAPI} from './custom' 5import {FollowingFeedAPI} from './following' 6import {type FeedAPI, type FeedAPIResponse} from './types' 7 8// HACK 9// the feed API does not include any facilities for passing down 10// non-post elements. adding that is a bit of a heavy lift, and we 11// have just one temporary usecase for it: flagging when the home feed 12// falls back to discover. 13// we use this fallback marker post to drive this instead. see Feed.tsx 14// for the usage. 15// -prf 16export const FALLBACK_MARKER_POST: AppBskyFeedDefs.FeedViewPost = { 17 post: { 18 uri: 'fallback-marker-post', 19 cid: 'fake', 20 record: {}, 21 author: { 22 did: 'did:fake', 23 handle: 'fake.com', 24 }, 25 indexedAt: new Date().toISOString(), 26 }, 27} 28 29export class HomeFeedAPI implements FeedAPI { 30 agent: BskyAgent 31 following: FollowingFeedAPI 32 discover: CustomFeedAPI 33 usingDiscover = false 34 itemCursor = 0 35 userInterests?: string 36 37 constructor({ 38 userInterests, 39 agent, 40 }: { 41 userInterests?: string 42 agent: BskyAgent 43 }) { 44 this.agent = agent 45 this.following = new FollowingFeedAPI({agent}) 46 this.discover = new CustomFeedAPI({ 47 agent, 48 feedParams: {feed: PROD_DEFAULT_FEED('whats-hot')}, 49 }) 50 this.userInterests = userInterests 51 } 52 53 reset() { 54 this.following = new FollowingFeedAPI({agent: this.agent}) 55 this.discover = new CustomFeedAPI({ 56 agent: this.agent, 57 feedParams: {feed: PROD_DEFAULT_FEED('whats-hot')}, 58 userInterests: this.userInterests, 59 }) 60 this.usingDiscover = false 61 this.itemCursor = 0 62 } 63 64 async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> { 65 if (this.usingDiscover) { 66 return this.discover.peekLatest() 67 } 68 return this.following.peekLatest() 69 } 70 71 async fetch({ 72 cursor, 73 limit, 74 }: { 75 cursor: string | undefined 76 limit: number 77 }): Promise<FeedAPIResponse> { 78 if (!cursor) { 79 this.reset() 80 } 81 82 let returnCursor 83 let posts: AppBskyFeedDefs.FeedViewPost[] = [] 84 85 if (!this.usingDiscover) { 86 const res = await this.following.fetch({cursor, limit}) 87 returnCursor = res.cursor 88 posts = posts.concat(res.feed) 89 if (!returnCursor) { 90 cursor = '' 91 posts.push(FALLBACK_MARKER_POST) 92 this.usingDiscover = true 93 } 94 } 95 96 if (this.usingDiscover && !__DEV__) { 97 const res = await this.discover.fetch({cursor, limit}) 98 returnCursor = res.cursor 99 posts = posts.concat(res.feed) 100 } 101 102 return { 103 cursor: returnCursor, 104 feed: posts, 105 } 106 } 107}