about summary refs log tree commit diff
path: root/src/state/models/feed-view.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/state/models/feed-view.ts')
-rw-r--r--src/state/models/feed-view.ts98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/state/models/feed-view.ts b/src/state/models/feed-view.ts
new file mode 100644
index 000000000..1fc507a70
--- /dev/null
+++ b/src/state/models/feed-view.ts
@@ -0,0 +1,98 @@
+import {makeAutoObservable, runInAction} from 'mobx'
+import {bsky} from '@adxp/mock-api'
+import {RootStoreModel} from './root-store'
+
+export class FeedViewItemModel implements bsky.FeedView.FeedItem {
+  key: string = ''
+  uri: string = ''
+  author: bsky.FeedView.User = {did: '', name: '', displayName: ''}
+  repostedBy?: bsky.FeedView.User
+  record: Record<string, unknown> = {}
+  embed?:
+    | bsky.FeedView.RecordEmbed
+    | bsky.FeedView.ExternalEmbed
+    | bsky.FeedView.UnknownEmbed
+  replyCount: number = 0
+  repostCount: number = 0
+  likeCount: number = 0
+  indexedAt: string = ''
+
+  constructor(key: string, v: bsky.FeedView.FeedItem) {
+    makeAutoObservable(this)
+    this.key = key
+    Object.assign(this, v)
+  }
+}
+
+export class FeedViewModel implements bsky.FeedView.Response {
+  state = 'idle'
+  error = ''
+  params: bsky.FeedView.Params
+  feed: FeedViewItemModel[] = []
+
+  constructor(public rootStore: RootStoreModel, params: bsky.FeedView.Params) {
+    makeAutoObservable(
+      this,
+      {rootStore: false, params: false},
+      {autoBind: true},
+    )
+    this.params = params
+  }
+
+  get hasContent() {
+    return this.feed.length !== 0
+  }
+
+  get hasError() {
+    return this.error !== ''
+  }
+
+  get isLoading() {
+    return this.state === 'loading'
+  }
+
+  get isEmpty() {
+    return !this.hasContent && !this.hasError && !this.isLoading
+  }
+
+  async fetch() {
+    if (this.hasContent) {
+      await this.updateContent()
+    } else {
+      await this.initialLoad()
+    }
+  }
+
+  async initialLoad() {
+    this.state = 'loading'
+    this.error = ''
+    try {
+      const res = (await this.rootStore.api.mainPds.view(
+        'blueskyweb.xyz:FeedView',
+        this.params,
+      )) as bsky.FeedView.Response
+      this._replaceAll(res)
+      runInAction(() => {
+        this.state = 'idle'
+      })
+    } catch (e: any) {
+      runInAction(() => {
+        this.state = 'error'
+        this.error = `Failed to load feed: ${e.toString()}`
+      })
+    }
+  }
+
+  async updateContent() {
+    // TODO: refetch and update items
+  }
+
+  private _replaceAll(res: bsky.FeedView.Response) {
+    this.feed.length = 0
+    let counter = 0
+    for (const item of res.feed) {
+      // TODO: validate .record
+      this.feed.push(new FeedViewItemModel(`item-${counter++}`, item))
+    }
+  }
+}