about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEric Bailey <git@esb.lol>2024-04-25 15:29:06 -0500
committerGitHub <noreply@github.com>2024-04-25 21:29:06 +0100
commitec376960347a6255f1ec12c1758797ac30c073ff (patch)
tree69676999d62dd48d9150c2ed4d1bb3febc822ba5
parent282ad4b17d7cfde9ae4743a0f909124dfc309960 (diff)
downloadvoidsky-ec376960347a6255f1ec12c1758797ac30c073ff.tar.zst
[Session] Drill `getAgent` into feed APIs (#3701)
* Update to desired post-feed usage

* Drill agent into feed apis

* Thread getAgent instead

---------

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
-rw-r--r--src/lib/api/feed/author.ts21
-rw-r--r--src/lib/api/feed/custom.ts28
-rw-r--r--src/lib/api/feed/following.ts14
-rw-r--r--src/lib/api/feed/home.ts27
-rw-r--r--src/lib/api/feed/likes.ts21
-rw-r--r--src/lib/api/feed/list.ts21
-rw-r--r--src/lib/api/feed/merge.ts89
-rw-r--r--src/state/queries/post-feed.ts46
8 files changed, 202 insertions, 65 deletions
diff --git a/src/lib/api/feed/author.ts b/src/lib/api/feed/author.ts
index 57db061b3..85601d068 100644
--- a/src/lib/api/feed/author.ts
+++ b/src/lib/api/feed/author.ts
@@ -1,15 +1,28 @@
 import {
   AppBskyFeedDefs,
   AppBskyFeedGetAuthorFeed as GetAuthorFeed,
+  BskyAgent,
 } from '@atproto/api'
+
 import {FeedAPI, FeedAPIResponse} from './types'
-import {getAgent} from '#/state/session'
 
 export class AuthorFeedAPI implements FeedAPI {
-  constructor(public params: GetAuthorFeed.QueryParams) {}
+  getAgent: () => BskyAgent
+  params: GetAuthorFeed.QueryParams
+
+  constructor({
+    getAgent,
+    feedParams,
+  }: {
+    getAgent: () => BskyAgent
+    feedParams: GetAuthorFeed.QueryParams
+  }) {
+    this.getAgent = getAgent
+    this.params = feedParams
+  }
 
   async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
-    const res = await getAgent().getAuthorFeed({
+    const res = await this.getAgent().getAuthorFeed({
       ...this.params,
       limit: 1,
     })
@@ -23,7 +36,7 @@ export class AuthorFeedAPI implements FeedAPI {
     cursor: string | undefined
     limit: number
   }): Promise<FeedAPIResponse> {
-    const res = await getAgent().getAuthorFeed({
+    const res = await this.getAgent().getAuthorFeed({
       ...this.params,
       cursor,
       limit,
diff --git a/src/lib/api/feed/custom.ts b/src/lib/api/feed/custom.ts
index bd30d58ac..75182c41f 100644
--- a/src/lib/api/feed/custom.ts
+++ b/src/lib/api/feed/custom.ts
@@ -2,18 +2,30 @@ import {
   AppBskyFeedDefs,
   AppBskyFeedGetFeed as GetCustomFeed,
   AtpAgent,
+  BskyAgent,
 } from '@atproto/api'
 
 import {getContentLanguages} from '#/state/preferences/languages'
-import {getAgent} from '#/state/session'
 import {FeedAPI, FeedAPIResponse} from './types'
 
 export class CustomFeedAPI implements FeedAPI {
-  constructor(public params: GetCustomFeed.QueryParams) {}
+  getAgent: () => BskyAgent
+  params: GetCustomFeed.QueryParams
+
+  constructor({
+    getAgent,
+    feedParams,
+  }: {
+    getAgent: () => BskyAgent
+    feedParams: GetCustomFeed.QueryParams
+  }) {
+    this.getAgent = getAgent
+    this.params = feedParams
+  }
 
   async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
     const contentLangs = getContentLanguages().join(',')
-    const res = await getAgent().app.bsky.feed.getFeed(
+    const res = await this.getAgent().app.bsky.feed.getFeed(
       {
         ...this.params,
         limit: 1,
@@ -31,15 +43,19 @@ export class CustomFeedAPI implements FeedAPI {
     limit: number
   }): Promise<FeedAPIResponse> {
     const contentLangs = getContentLanguages().join(',')
-    const agent = getAgent()
+    const agent = this.getAgent()
     const res = agent.session
-      ? await getAgent().app.bsky.feed.getFeed(
+      ? await this.getAgent().app.bsky.feed.getFeed(
           {
             ...this.params,
             cursor,
             limit,
           },
-          {headers: {'Accept-Language': contentLangs}},
+          {
+            headers: {
+              'Accept-Language': contentLangs,
+            },
+          },
         )
       : await loggedOutFetch({...this.params, cursor, limit})
     if (res.success) {
diff --git a/src/lib/api/feed/following.ts b/src/lib/api/feed/following.ts
index 24389b5ed..36c376554 100644
--- a/src/lib/api/feed/following.ts
+++ b/src/lib/api/feed/following.ts
@@ -1,12 +1,16 @@
-import {AppBskyFeedDefs} from '@atproto/api'
+import {AppBskyFeedDefs, BskyAgent} from '@atproto/api'
+
 import {FeedAPI, FeedAPIResponse} from './types'
-import {getAgent} from '#/state/session'
 
 export class FollowingFeedAPI implements FeedAPI {
-  constructor() {}
+  getAgent: () => BskyAgent
+
+  constructor({getAgent}: {getAgent: () => BskyAgent}) {
+    this.getAgent = getAgent
+  }
 
   async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
-    const res = await getAgent().getTimeline({
+    const res = await this.getAgent().getTimeline({
       limit: 1,
     })
     return res.data.feed[0]
@@ -19,7 +23,7 @@ export class FollowingFeedAPI implements FeedAPI {
     cursor: string | undefined
     limit: number
   }): Promise<FeedAPIResponse> {
-    const res = await getAgent().getTimeline({
+    const res = await this.getAgent().getTimeline({
       cursor,
       limit,
     })
diff --git a/src/lib/api/feed/home.ts b/src/lib/api/feed/home.ts
index 436a66d07..4a5308346 100644
--- a/src/lib/api/feed/home.ts
+++ b/src/lib/api/feed/home.ts
@@ -1,8 +1,9 @@
-import {AppBskyFeedDefs} from '@atproto/api'
-import {FeedAPI, FeedAPIResponse} from './types'
-import {FollowingFeedAPI} from './following'
-import {CustomFeedAPI} from './custom'
+import {AppBskyFeedDefs, BskyAgent} from '@atproto/api'
+
 import {PROD_DEFAULT_FEED} from '#/lib/constants'
+import {CustomFeedAPI} from './custom'
+import {FollowingFeedAPI} from './following'
+import {FeedAPI, FeedAPIResponse} from './types'
 
 // HACK
 // the feed API does not include any facilities for passing down
@@ -26,19 +27,27 @@ export const FALLBACK_MARKER_POST: AppBskyFeedDefs.FeedViewPost = {
 }
 
 export class HomeFeedAPI implements FeedAPI {
+  getAgent: () => BskyAgent
   following: FollowingFeedAPI
   discover: CustomFeedAPI
   usingDiscover = false
   itemCursor = 0
 
-  constructor() {
-    this.following = new FollowingFeedAPI()
-    this.discover = new CustomFeedAPI({feed: PROD_DEFAULT_FEED('whats-hot')})
+  constructor({getAgent}: {getAgent: () => BskyAgent}) {
+    this.getAgent = getAgent
+    this.following = new FollowingFeedAPI({getAgent})
+    this.discover = new CustomFeedAPI({
+      getAgent,
+      feedParams: {feed: PROD_DEFAULT_FEED('whats-hot')},
+    })
   }
 
   reset() {
-    this.following = new FollowingFeedAPI()
-    this.discover = new CustomFeedAPI({feed: PROD_DEFAULT_FEED('whats-hot')})
+    this.following = new FollowingFeedAPI({getAgent: this.getAgent})
+    this.discover = new CustomFeedAPI({
+      getAgent: this.getAgent,
+      feedParams: {feed: PROD_DEFAULT_FEED('whats-hot')},
+    })
     this.usingDiscover = false
     this.itemCursor = 0
   }
diff --git a/src/lib/api/feed/likes.ts b/src/lib/api/feed/likes.ts
index 2b0afdf11..1729ee05c 100644
--- a/src/lib/api/feed/likes.ts
+++ b/src/lib/api/feed/likes.ts
@@ -1,15 +1,28 @@
 import {
   AppBskyFeedDefs,
   AppBskyFeedGetActorLikes as GetActorLikes,
+  BskyAgent,
 } from '@atproto/api'
+
 import {FeedAPI, FeedAPIResponse} from './types'
-import {getAgent} from '#/state/session'
 
 export class LikesFeedAPI implements FeedAPI {
-  constructor(public params: GetActorLikes.QueryParams) {}
+  getAgent: () => BskyAgent
+  params: GetActorLikes.QueryParams
+
+  constructor({
+    getAgent,
+    feedParams,
+  }: {
+    getAgent: () => BskyAgent
+    feedParams: GetActorLikes.QueryParams
+  }) {
+    this.getAgent = getAgent
+    this.params = feedParams
+  }
 
   async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
-    const res = await getAgent().getActorLikes({
+    const res = await this.getAgent().getActorLikes({
       ...this.params,
       limit: 1,
     })
@@ -23,7 +36,7 @@ export class LikesFeedAPI implements FeedAPI {
     cursor: string | undefined
     limit: number
   }): Promise<FeedAPIResponse> {
-    const res = await getAgent().getActorLikes({
+    const res = await this.getAgent().getActorLikes({
       ...this.params,
       cursor,
       limit,
diff --git a/src/lib/api/feed/list.ts b/src/lib/api/feed/list.ts
index 19f2ff177..004685b99 100644
--- a/src/lib/api/feed/list.ts
+++ b/src/lib/api/feed/list.ts
@@ -1,15 +1,28 @@
 import {
   AppBskyFeedDefs,
   AppBskyFeedGetListFeed as GetListFeed,
+  BskyAgent,
 } from '@atproto/api'
+
 import {FeedAPI, FeedAPIResponse} from './types'
-import {getAgent} from '#/state/session'
 
 export class ListFeedAPI implements FeedAPI {
-  constructor(public params: GetListFeed.QueryParams) {}
+  getAgent: () => BskyAgent
+  params: GetListFeed.QueryParams
+
+  constructor({
+    getAgent,
+    feedParams,
+  }: {
+    getAgent: () => BskyAgent
+    feedParams: GetListFeed.QueryParams
+  }) {
+    this.getAgent = getAgent
+    this.params = feedParams
+  }
 
   async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
-    const res = await getAgent().app.bsky.feed.getListFeed({
+    const res = await this.getAgent().app.bsky.feed.getListFeed({
       ...this.params,
       limit: 1,
     })
@@ -23,7 +36,7 @@ export class ListFeedAPI implements FeedAPI {
     cursor: string | undefined
     limit: number
   }): Promise<FeedAPIResponse> {
-    const res = await getAgent().app.bsky.feed.getListFeed({
+    const res = await this.getAgent().app.bsky.feed.getListFeed({
       ...this.params,
       cursor,
       limit,
diff --git a/src/lib/api/feed/merge.ts b/src/lib/api/feed/merge.ts
index 28bf143cb..c85de0306 100644
--- a/src/lib/api/feed/merge.ts
+++ b/src/lib/api/feed/merge.ts
@@ -1,31 +1,51 @@
-import {AppBskyFeedDefs, AppBskyFeedGetTimeline} from '@atproto/api'
+import {AppBskyFeedDefs, AppBskyFeedGetTimeline, BskyAgent} from '@atproto/api'
 import shuffle from 'lodash.shuffle'
-import {timeout} from 'lib/async/timeout'
+
+import {getContentLanguages} from '#/state/preferences/languages'
+import {FeedParams} from '#/state/queries/post-feed'
 import {bundleAsync} from 'lib/async/bundle'
+import {timeout} from 'lib/async/timeout'
 import {feedUriToHref} from 'lib/strings/url-helpers'
 import {FeedTuner} from '../feed-manip'
-import {FeedAPI, FeedAPIResponse, ReasonFeedSource} from './types'
-import {FeedParams} from '#/state/queries/post-feed'
 import {FeedTunerFn} from '../feed-manip'
-import {getAgent} from '#/state/session'
-import {getContentLanguages} from '#/state/preferences/languages'
+import {FeedAPI, FeedAPIResponse, ReasonFeedSource} from './types'
 
 const REQUEST_WAIT_MS = 500 // 500ms
 const POST_AGE_CUTOFF = 60e3 * 60 * 24 // 24hours
 
 export class MergeFeedAPI implements FeedAPI {
+  getAgent: () => BskyAgent
+  params: FeedParams
+  feedTuners: FeedTunerFn[]
   following: MergeFeedSource_Following
   customFeeds: MergeFeedSource_Custom[] = []
   feedCursor = 0
   itemCursor = 0
   sampleCursor = 0
 
-  constructor(public params: FeedParams, public feedTuners: FeedTunerFn[]) {
-    this.following = new MergeFeedSource_Following(this.feedTuners)
+  constructor({
+    getAgent,
+    feedParams,
+    feedTuners,
+  }: {
+    getAgent: () => BskyAgent
+    feedParams: FeedParams
+    feedTuners: FeedTunerFn[]
+  }) {
+    this.getAgent = getAgent
+    this.params = feedParams
+    this.feedTuners = feedTuners
+    this.following = new MergeFeedSource_Following({
+      getAgent: this.getAgent,
+      feedTuners: this.feedTuners,
+    })
   }
 
   reset() {
-    this.following = new MergeFeedSource_Following(this.feedTuners)
+    this.following = new MergeFeedSource_Following({
+      getAgent: this.getAgent,
+      feedTuners: this.feedTuners,
+    })
     this.customFeeds = []
     this.feedCursor = 0
     this.itemCursor = 0
@@ -33,7 +53,12 @@ export class MergeFeedAPI implements FeedAPI {
     if (this.params.mergeFeedSources) {
       this.customFeeds = shuffle(
         this.params.mergeFeedSources.map(
-          feedUri => new MergeFeedSource_Custom(feedUri, this.feedTuners),
+          feedUri =>
+            new MergeFeedSource_Custom({
+              getAgent: this.getAgent,
+              feedUri,
+              feedTuners: this.feedTuners,
+            }),
         ),
       )
     } else {
@@ -42,7 +67,7 @@ export class MergeFeedAPI implements FeedAPI {
   }
 
   async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
-    const res = await getAgent().getTimeline({
+    const res = await this.getAgent().getTimeline({
       limit: 1,
     })
     return res.data.feed[0]
@@ -136,12 +161,23 @@ export class MergeFeedAPI implements FeedAPI {
 }
 
 class MergeFeedSource {
+  getAgent: () => BskyAgent
+  feedTuners: FeedTunerFn[]
   sourceInfo: ReasonFeedSource | undefined
   cursor: string | undefined = undefined
   queue: AppBskyFeedDefs.FeedViewPost[] = []
   hasMore = true
 
-  constructor(public feedTuners: FeedTunerFn[]) {}
+  constructor({
+    getAgent,
+    feedTuners,
+  }: {
+    getAgent: () => BskyAgent
+    feedTuners: FeedTunerFn[]
+  }) {
+    this.getAgent = getAgent
+    this.feedTuners = feedTuners
+  }
 
   get numReady() {
     return this.queue.length
@@ -203,7 +239,7 @@ class MergeFeedSource_Following extends MergeFeedSource {
     cursor: string | undefined,
     limit: number,
   ): Promise<AppBskyFeedGetTimeline.Response> {
-    const res = await getAgent().getTimeline({cursor, limit})
+    const res = await this.getAgent().getTimeline({cursor, limit})
     // run the tuner pre-emptively to ensure better mixing
     const slices = this.tuner.tune(res.data.feed, {
       dryRun: false,
@@ -215,10 +251,25 @@ class MergeFeedSource_Following extends MergeFeedSource {
 }
 
 class MergeFeedSource_Custom extends MergeFeedSource {
+  getAgent: () => BskyAgent
   minDate: Date
+  feedUri: string
 
-  constructor(public feedUri: string, public feedTuners: FeedTunerFn[]) {
-    super(feedTuners)
+  constructor({
+    getAgent,
+    feedUri,
+    feedTuners,
+  }: {
+    getAgent: () => BskyAgent
+    feedUri: string
+    feedTuners: FeedTunerFn[]
+  }) {
+    super({
+      getAgent,
+      feedTuners,
+    })
+    this.getAgent = getAgent
+    this.feedUri = feedUri
     this.sourceInfo = {
       $type: 'reasonFeedSource',
       uri: feedUri,
@@ -233,13 +284,17 @@ class MergeFeedSource_Custom extends MergeFeedSource {
   ): Promise<AppBskyFeedGetTimeline.Response> {
     try {
       const contentLangs = getContentLanguages().join(',')
-      const res = await getAgent().app.bsky.feed.getFeed(
+      const res = await this.getAgent().app.bsky.feed.getFeed(
         {
           cursor,
           limit,
           feed: this.feedUri,
         },
-        {headers: {'Accept-Language': contentLangs}},
+        {
+          headers: {
+            'Accept-Language': contentLangs,
+          },
+        },
       )
       // NOTE
       // some custom feeds fail to enforce the pagination limit
diff --git a/src/state/queries/post-feed.ts b/src/state/queries/post-feed.ts
index 3453a7764..2d5c0d4b4 100644
--- a/src/state/queries/post-feed.ts
+++ b/src/state/queries/post-feed.ts
@@ -135,11 +135,14 @@ export function usePostFeedQuery(
     queryKey: RQKEY(feedDesc, params),
     async queryFn({pageParam}: {pageParam: RQPageParam}) {
       logger.debug('usePostFeedQuery', {feedDesc, cursor: pageParam?.cursor})
-
       const {api, cursor} = pageParam
         ? pageParam
         : {
-            api: createApi(feedDesc, params || {}, feedTuners),
+            api: createApi({
+              feedDesc,
+              feedParams: params || {},
+              feedTuners,
+            }),
             cursor: undefined,
           }
 
@@ -365,34 +368,45 @@ export async function pollLatest(page: FeedPage | undefined) {
   return false
 }
 
-function createApi(
-  feedDesc: FeedDescriptor,
-  params: FeedParams,
-  feedTuners: FeedTunerFn[],
-) {
+function createApi({
+  feedDesc,
+  feedParams,
+  feedTuners,
+}: {
+  feedDesc: FeedDescriptor
+  feedParams: FeedParams
+  feedTuners: FeedTunerFn[]
+}) {
   if (feedDesc === 'home') {
-    if (params.mergeFeedEnabled) {
-      return new MergeFeedAPI(params, feedTuners)
+    if (feedParams.mergeFeedEnabled) {
+      return new MergeFeedAPI({
+        getAgent,
+        feedParams,
+        feedTuners,
+      })
     } else {
-      return new HomeFeedAPI()
+      return new HomeFeedAPI({getAgent})
     }
   } else if (feedDesc === 'following') {
-    return new FollowingFeedAPI()
+    return new FollowingFeedAPI({getAgent})
   } else if (feedDesc.startsWith('author')) {
     const [_, actor, filter] = feedDesc.split('|')
-    return new AuthorFeedAPI({actor, filter})
+    return new AuthorFeedAPI({getAgent, feedParams: {actor, filter}})
   } else if (feedDesc.startsWith('likes')) {
     const [_, actor] = feedDesc.split('|')
-    return new LikesFeedAPI({actor})
+    return new LikesFeedAPI({getAgent, feedParams: {actor}})
   } else if (feedDesc.startsWith('feedgen')) {
     const [_, feed] = feedDesc.split('|')
-    return new CustomFeedAPI({feed})
+    return new CustomFeedAPI({
+      getAgent,
+      feedParams: {feed},
+    })
   } else if (feedDesc.startsWith('list')) {
     const [_, list] = feedDesc.split('|')
-    return new ListFeedAPI({list})
+    return new ListFeedAPI({getAgent, feedParams: {list}})
   } else {
     // shouldnt happen
-    return new FollowingFeedAPI()
+    return new FollowingFeedAPI({getAgent})
   }
 }