mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import {makeAutoObservable} from 'mobx'
2import {AppBskyActorGetSuggestions as GetSuggestions} from '@atproto/api'
3import {RootStoreModel} from './root-store'
4
5export type SuggestedActor = GetSuggestions.Actor & {
6 _reactKey: string
7}
8
9export class SuggestedActorsViewModel {
10 // state
11 isLoading = false
12 isRefreshing = false
13 hasLoaded = false
14 error = ''
15
16 // data
17 suggestions: SuggestedActor[] = []
18
19 constructor(public rootStore: RootStoreModel) {
20 makeAutoObservable(
21 this,
22 {
23 rootStore: false,
24 },
25 {autoBind: true},
26 )
27 }
28
29 get hasContent() {
30 return this.suggestions.length > 0
31 }
32
33 get hasError() {
34 return this.error !== ''
35 }
36
37 get isEmpty() {
38 return this.hasLoaded && !this.hasContent
39 }
40
41 // public api
42 // =
43
44 async setup() {
45 await this._fetch()
46 }
47
48 async refresh() {
49 await this._fetch(true)
50 }
51
52 // state transitions
53 // =
54
55 private _xLoading(isRefreshing = false) {
56 this.isLoading = true
57 this.isRefreshing = isRefreshing
58 this.error = ''
59 }
60
61 private _xIdle(err?: any) {
62 this.isLoading = false
63 this.isRefreshing = false
64 this.hasLoaded = true
65 this.error = err ? err.toString() : ''
66 if (err) {
67 this.rootStore.log.error('Failed to fetch suggested actors', err)
68 }
69 }
70
71 // loader functions
72 // =
73
74 private async _fetch(isRefreshing = false) {
75 this.suggestions.length = 0
76 this._xLoading(isRefreshing)
77 let cursor
78 let res
79 try {
80 do {
81 res = await this.rootStore.api.app.bsky.actor.getSuggestions({
82 limit: 20,
83 cursor,
84 })
85 this._appendAll(res)
86 cursor = res.data.cursor
87 } while (
88 cursor &&
89 res.data.actors.length === 20 &&
90 this.suggestions.length < 20
91 )
92 this._xIdle()
93 } catch (e: any) {
94 this._xIdle(e)
95 }
96 }
97
98 private _appendAll(res: GetSuggestions.Response) {
99 for (const item of res.data.actors) {
100 if (item.did === this.rootStore.me.did) {
101 continue // skip self
102 }
103 if (item.myState?.follow) {
104 continue // skip already-followed users
105 }
106 this._append({
107 _reactKey: `item-${this.suggestions.length}`,
108 ...item,
109 })
110 }
111 }
112
113 private _append(item: SuggestedActor) {
114 this.suggestions.push(item)
115 }
116}