about summary refs log tree commit diff
path: root/src/state
diff options
context:
space:
mode:
Diffstat (limited to 'src/state')
-rw-r--r--src/state/models/lists/likes.ts135
-rw-r--r--src/state/models/lists/reposted-by.ts136
-rw-r--r--src/state/queries/post-liked-by.ts32
-rw-r--r--src/state/queries/post-reposted-by.ts32
4 files changed, 64 insertions, 271 deletions
diff --git a/src/state/models/lists/likes.ts b/src/state/models/lists/likes.ts
deleted file mode 100644
index df20f09db..000000000
--- a/src/state/models/lists/likes.ts
+++ /dev/null
@@ -1,135 +0,0 @@
-import {makeAutoObservable, runInAction} from 'mobx'
-import {AtUri} from '@atproto/api'
-import {AppBskyFeedGetLikes as GetLikes} from '@atproto/api'
-import {RootStoreModel} from '../root-store'
-import {cleanError} from 'lib/strings/errors'
-import {bundleAsync} from 'lib/async/bundle'
-import * as apilib from 'lib/api/index'
-import {logger} from '#/logger'
-
-const PAGE_SIZE = 30
-
-export type LikeItem = GetLikes.Like
-
-export class LikesModel {
-  // state
-  isLoading = false
-  isRefreshing = false
-  hasLoaded = false
-  error = ''
-  resolvedUri = ''
-  params: GetLikes.QueryParams
-  hasMore = true
-  loadMoreCursor?: string
-
-  // data
-  uri: string = ''
-  likes: LikeItem[] = []
-
-  constructor(public rootStore: RootStoreModel, params: GetLikes.QueryParams) {
-    makeAutoObservable(
-      this,
-      {
-        rootStore: false,
-        params: false,
-      },
-      {autoBind: true},
-    )
-    this.params = params
-  }
-
-  get hasContent() {
-    return this.uri !== ''
-  }
-
-  get hasError() {
-    return this.error !== ''
-  }
-
-  get isEmpty() {
-    return this.hasLoaded && !this.hasContent
-  }
-
-  // public api
-  // =
-
-  async refresh() {
-    return this.loadMore(true)
-  }
-
-  loadMore = bundleAsync(async (replace: boolean = false) => {
-    if (!replace && !this.hasMore) {
-      return
-    }
-    this._xLoading(replace)
-    try {
-      if (!this.resolvedUri) {
-        await this._resolveUri()
-      }
-      const params = Object.assign({}, this.params, {
-        uri: this.resolvedUri,
-        limit: PAGE_SIZE,
-        cursor: replace ? undefined : this.loadMoreCursor,
-      })
-      const res = await this.rootStore.agent.getLikes(params)
-      if (replace) {
-        this._replaceAll(res)
-      } else {
-        this._appendAll(res)
-      }
-      this._xIdle()
-    } catch (e: any) {
-      this._xIdle(e)
-    }
-  })
-
-  // state transitions
-  // =
-
-  _xLoading(isRefreshing = false) {
-    this.isLoading = true
-    this.isRefreshing = isRefreshing
-    this.error = ''
-  }
-
-  _xIdle(err?: any) {
-    this.isLoading = false
-    this.isRefreshing = false
-    this.hasLoaded = true
-    this.error = cleanError(err)
-    if (err) {
-      logger.error('Failed to fetch likes', {error: err})
-    }
-  }
-
-  // helper functions
-  // =
-
-  async _resolveUri() {
-    const urip = new AtUri(this.params.uri)
-    if (!urip.host.startsWith('did:')) {
-      try {
-        urip.host = await apilib.resolveName(this.rootStore, urip.host)
-      } catch (e: any) {
-        this.error = e.toString()
-      }
-    }
-    runInAction(() => {
-      this.resolvedUri = urip.toString()
-    })
-  }
-
-  _replaceAll(res: GetLikes.Response) {
-    this.likes = []
-    this._appendAll(res)
-  }
-
-  _appendAll(res: GetLikes.Response) {
-    this.loadMoreCursor = res.data.cursor
-    this.hasMore = !!this.loadMoreCursor
-    this.rootStore.me.follows.hydrateMany(
-      res.data.likes.map(like => like.actor),
-    )
-    this.likes = this.likes.concat(res.data.likes)
-  }
-}
diff --git a/src/state/models/lists/reposted-by.ts b/src/state/models/lists/reposted-by.ts
deleted file mode 100644
index c5058558a..000000000
--- a/src/state/models/lists/reposted-by.ts
+++ /dev/null
@@ -1,136 +0,0 @@
-import {makeAutoObservable, runInAction} from 'mobx'
-import {AtUri} from '@atproto/api'
-import {
-  AppBskyFeedGetRepostedBy as GetRepostedBy,
-  AppBskyActorDefs,
-} from '@atproto/api'
-import {RootStoreModel} from '../root-store'
-import {bundleAsync} from 'lib/async/bundle'
-import {cleanError} from 'lib/strings/errors'
-import * as apilib from 'lib/api/index'
-import {logger} from '#/logger'
-
-const PAGE_SIZE = 30
-
-export type RepostedByItem = AppBskyActorDefs.ProfileViewBasic
-
-export class RepostedByModel {
-  // state
-  isLoading = false
-  isRefreshing = false
-  hasLoaded = false
-  error = ''
-  resolvedUri = ''
-  params: GetRepostedBy.QueryParams
-  hasMore = true
-  loadMoreCursor?: string
-
-  // data
-  uri: string = ''
-  repostedBy: RepostedByItem[] = []
-
-  constructor(
-    public rootStore: RootStoreModel,
-    params: GetRepostedBy.QueryParams,
-  ) {
-    makeAutoObservable(
-      this,
-      {
-        rootStore: false,
-        params: false,
-      },
-      {autoBind: true},
-    )
-    this.params = params
-  }
-
-  get hasContent() {
-    return this.uri !== ''
-  }
-
-  get hasError() {
-    return this.error !== ''
-  }
-
-  get isEmpty() {
-    return this.hasLoaded && !this.hasContent
-  }
-
-  // public api
-  // =
-
-  async refresh() {
-    return this.loadMore(true)
-  }
-
-  loadMore = bundleAsync(async (replace: boolean = false) => {
-    this._xLoading(replace)
-    try {
-      if (!this.resolvedUri) {
-        await this._resolveUri()
-      }
-      const params = Object.assign({}, this.params, {
-        uri: this.resolvedUri,
-        limit: PAGE_SIZE,
-        cursor: replace ? undefined : this.loadMoreCursor,
-      })
-      const res = await this.rootStore.agent.getRepostedBy(params)
-      if (replace) {
-        this._replaceAll(res)
-      } else {
-        this._appendAll(res)
-      }
-      this._xIdle()
-    } catch (e: any) {
-      this._xIdle(e)
-    }
-  })
-
-  // state transitions
-  // =
-
-  _xLoading(isRefreshing = false) {
-    this.isLoading = true
-    this.isRefreshing = isRefreshing
-    this.error = ''
-  }
-
-  _xIdle(err?: any) {
-    this.isLoading = false
-    this.isRefreshing = false
-    this.hasLoaded = true
-    this.error = cleanError(err)
-    if (err) {
-      logger.error('Failed to fetch reposted by view', {error: err})
-    }
-  }
-
-  // helper functions
-  // =
-
-  async _resolveUri() {
-    const urip = new AtUri(this.params.uri)
-    if (!urip.host.startsWith('did:')) {
-      try {
-        urip.host = await apilib.resolveName(this.rootStore, urip.host)
-      } catch (e: any) {
-        this.error = e.toString()
-      }
-    }
-    runInAction(() => {
-      this.resolvedUri = urip.toString()
-    })
-  }
-
-  _replaceAll(res: GetRepostedBy.Response) {
-    this.repostedBy = []
-    this._appendAll(res)
-  }
-
-  _appendAll(res: GetRepostedBy.Response) {
-    this.loadMoreCursor = res.data.cursor
-    this.hasMore = !!this.loadMoreCursor
-    this.repostedBy = this.repostedBy.concat(res.data.repostedBy)
-    this.rootStore.me.follows.hydrateMany(res.data.repostedBy)
-  }
-}
diff --git a/src/state/queries/post-liked-by.ts b/src/state/queries/post-liked-by.ts
new file mode 100644
index 000000000..78ce9f60a
--- /dev/null
+++ b/src/state/queries/post-liked-by.ts
@@ -0,0 +1,32 @@
+import {AppBskyFeedGetLikes} from '@atproto/api'
+import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
+import {useSession} from '../session'
+
+const PAGE_SIZE = 30
+type RQPageParam = string | undefined
+
+export const RQKEY = (resolvedUri: string) => ['post-liked-by', resolvedUri]
+
+export function usePostLikedByQuery(resolvedUri: string | undefined) {
+  const {agent} = useSession()
+  return useInfiniteQuery<
+    AppBskyFeedGetLikes.OutputSchema,
+    Error,
+    InfiniteData<AppBskyFeedGetLikes.OutputSchema>,
+    QueryKey,
+    RQPageParam
+  >({
+    queryKey: RQKEY(resolvedUri || ''),
+    async queryFn({pageParam}: {pageParam: RQPageParam}) {
+      const res = await agent.getLikes({
+        uri: resolvedUri || '',
+        limit: PAGE_SIZE,
+        cursor: pageParam,
+      })
+      return res.data
+    },
+    initialPageParam: undefined,
+    getNextPageParam: lastPage => lastPage.cursor,
+    enabled: !!resolvedUri,
+  })
+}
diff --git a/src/state/queries/post-reposted-by.ts b/src/state/queries/post-reposted-by.ts
new file mode 100644
index 000000000..15cb377b4
--- /dev/null
+++ b/src/state/queries/post-reposted-by.ts
@@ -0,0 +1,32 @@
+import {AppBskyFeedGetRepostedBy} from '@atproto/api'
+import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
+import {useSession} from '../session'
+
+const PAGE_SIZE = 30
+type RQPageParam = string | undefined
+
+export const RQKEY = (resolvedUri: string) => ['post-reposted-by', resolvedUri]
+
+export function usePostRepostedByQuery(resolvedUri: string | undefined) {
+  const {agent} = useSession()
+  return useInfiniteQuery<
+    AppBskyFeedGetRepostedBy.OutputSchema,
+    Error,
+    InfiniteData<AppBskyFeedGetRepostedBy.OutputSchema>,
+    QueryKey,
+    RQPageParam
+  >({
+    queryKey: RQKEY(resolvedUri || ''),
+    async queryFn({pageParam}: {pageParam: RQPageParam}) {
+      const res = await agent.getRepostedBy({
+        uri: resolvedUri || '',
+        limit: PAGE_SIZE,
+        cursor: pageParam,
+      })
+      return res.data
+    },
+    initialPageParam: undefined,
+    getNextPageParam: lastPage => lastPage.cursor,
+    enabled: !!resolvedUri,
+  })
+}