about summary refs log tree commit diff
path: root/src/state/models/post-thread-view.ts
diff options
context:
space:
mode:
authorPaul Frazee <pfrazee@gmail.com>2022-07-22 11:18:47 -0500
committerPaul Frazee <pfrazee@gmail.com>2022-07-22 11:18:47 -0500
commit0ec0ba996f05876d78039509e0ea61528c5faeec (patch)
tree1184d8adc886033c312def5b8326a8eda1d8c921 /src/state/models/post-thread-view.ts
parentcc8a1702043cfbd783f4caa61ab9eb8aeb421072 (diff)
downloadvoidsky-0ec0ba996f05876d78039509e0ea61528c5faeec.tar.zst
Implement like and repost
Diffstat (limited to 'src/state/models/post-thread-view.ts')
-rw-r--r--src/state/models/post-thread-view.ts76
1 files changed, 67 insertions, 9 deletions
diff --git a/src/state/models/post-thread-view.ts b/src/state/models/post-thread-view.ts
index 3c3b8d92d..ef3a49e9e 100644
--- a/src/state/models/post-thread-view.ts
+++ b/src/state/models/post-thread-view.ts
@@ -2,6 +2,7 @@ import {makeAutoObservable, runInAction} from 'mobx'
 import {bsky, AdxUri} from '@adxp/mock-api'
 import _omit from 'lodash.omit'
 import {RootStoreModel} from './root-store'
+import * as apilib from '../lib/api'
 
 function* reactKeyGenerator(): Generator<string> {
   let counter = 0
@@ -10,6 +11,15 @@ function* reactKeyGenerator(): Generator<string> {
   }
 }
 
+export class PostThreadViewPostMyStateModel {
+  hasLiked: boolean = false
+  hasReposted: boolean = false
+
+  constructor() {
+    makeAutoObservable(this)
+  }
+}
+
 export class PostThreadViewPostModel implements bsky.PostThreadView.Post {
   // ui state
   _reactKey: string = ''
@@ -30,12 +40,20 @@ export class PostThreadViewPostModel implements bsky.PostThreadView.Post {
   repostCount: number = 0
   likeCount: number = 0
   indexedAt: string = ''
+  myState = new PostThreadViewPostMyStateModel()
 
-  constructor(reactKey: string, v?: bsky.PostThreadView.Post) {
-    makeAutoObservable(this)
+  constructor(
+    public rootStore: RootStoreModel,
+    reactKey: string,
+    v?: bsky.PostThreadView.Post,
+  ) {
+    makeAutoObservable(this, {rootStore: false})
     this._reactKey = reactKey
     if (v) {
-      Object.assign(this, _omit(v, 'parent', 'replies')) // copy everything but the replies and the parent
+      Object.assign(this, _omit(v, 'parent', 'replies', 'myState')) // replies and parent are handled via assignTreeModels
+      if (v.myState) {
+        Object.assign(this.myState, v.myState)
+      }
     }
   }
 
@@ -44,6 +62,7 @@ export class PostThreadViewPostModel implements bsky.PostThreadView.Post {
     if (v.parent) {
       // TODO: validate .record
       const parentModel = new PostThreadViewPostModel(
+        this.rootStore,
         keyGen.next().value,
         v.parent,
       )
@@ -58,7 +77,11 @@ export class PostThreadViewPostModel implements bsky.PostThreadView.Post {
       const replies = []
       for (const item of v.replies) {
         // TODO: validate .record
-        const itemModel = new PostThreadViewPostModel(keyGen.next().value, item)
+        const itemModel = new PostThreadViewPostModel(
+          this.rootStore,
+          keyGen.next().value,
+          item,
+        )
         itemModel._depth = this._depth + 1
         if (item.replies) {
           itemModel.assignTreeModels(keyGen, item)
@@ -68,10 +91,41 @@ export class PostThreadViewPostModel implements bsky.PostThreadView.Post {
       this.replies = replies
     }
   }
+
+  async toggleLike() {
+    if (this.myState.hasLiked) {
+      await apilib.unlike(this.rootStore.api, 'alice.com', this.uri)
+      runInAction(() => {
+        this.likeCount--
+        this.myState.hasLiked = false
+      })
+    } else {
+      await apilib.like(this.rootStore.api, 'alice.com', this.uri)
+      runInAction(() => {
+        this.likeCount++
+        this.myState.hasLiked = true
+      })
+    }
+  }
+
+  async toggleRepost() {
+    if (this.myState.hasReposted) {
+      await apilib.unrepost(this.rootStore.api, 'alice.com', this.uri)
+      runInAction(() => {
+        this.repostCount--
+        this.myState.hasReposted = false
+      })
+    } else {
+      await apilib.repost(this.rootStore.api, 'alice.com', this.uri)
+      runInAction(() => {
+        this.repostCount++
+        this.myState.hasReposted = true
+      })
+    }
+  }
 }
-const UNLOADED_THREAD = new PostThreadViewPostModel('')
 
-export class PostThreadViewModel implements bsky.PostThreadView.Response {
+export class PostThreadViewModel {
   // state
   isLoading = false
   isRefreshing = false
@@ -81,7 +135,7 @@ export class PostThreadViewModel implements bsky.PostThreadView.Response {
   params: bsky.PostThreadView.Params
 
   // data
-  thread: PostThreadViewPostModel = UNLOADED_THREAD
+  thread?: PostThreadViewPostModel
 
   constructor(
     public rootStore: RootStoreModel,
@@ -99,7 +153,7 @@ export class PostThreadViewModel implements bsky.PostThreadView.Response {
   }
 
   get hasContent() {
-    return this.thread !== UNLOADED_THREAD
+    return typeof this.thread !== 'undefined'
   }
 
   get hasError() {
@@ -177,7 +231,11 @@ export class PostThreadViewModel implements bsky.PostThreadView.Response {
   private _replaceAll(res: bsky.PostThreadView.Response) {
     // TODO: validate .record
     const keyGen = reactKeyGenerator()
-    const thread = new PostThreadViewPostModel(keyGen.next().value, res.thread)
+    const thread = new PostThreadViewPostModel(
+      this.rootStore,
+      keyGen.next().value,
+      res.thread,
+    )
     thread._isHighlightedPost = true
     thread.assignTreeModels(keyGen, res.thread)
     this.thread = thread