about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/state/models/feeds/algo/algo-item.ts48
-rw-r--r--src/view/screens/CustomFeed.tsx14
2 files changed, 52 insertions, 10 deletions
diff --git a/src/state/models/feeds/algo/algo-item.ts b/src/state/models/feeds/algo/algo-item.ts
index 41fe6a976..0eaeebd39 100644
--- a/src/state/models/feeds/algo/algo-item.ts
+++ b/src/state/models/feeds/algo/algo-item.ts
@@ -1,4 +1,4 @@
-import {AppBskyFeedDefs} from '@atproto/api'
+import {AppBskyFeedDefs, AtUri} from '@atproto/api'
 import {makeAutoObservable} from 'mobx'
 import {RootStoreModel} from 'state/models/root-store'
 
@@ -38,12 +38,32 @@ export class AlgoItemModel {
   }
 
   get isLiked() {
-    return this.data.viewer?.liked
+    return this.data.viewer?.like
   }
 
-  set toggleLiked(value: boolean) {
+  private toggleLiked(s?: string) {
     if (this.data.viewer) {
-      this.data.viewer.liked = value
+      if (this.data.viewer.like) {
+        this.data.viewer.like = undefined
+      } else {
+        this.data.viewer.like = s
+      }
+    }
+  }
+
+  private incrementLike() {
+    if (this.data.likeCount) {
+      this.data.likeCount += 1
+    } else {
+      this.data.likeCount = 1
+    }
+  }
+
+  private decrementLike() {
+    if (this.data.likeCount) {
+      this.data.likeCount -= 1
+    } else {
+      this.data.likeCount = 0
     }
   }
 
@@ -73,8 +93,7 @@ export class AlgoItemModel {
 
   async like() {
     try {
-      this.toggleLiked = true
-      await this.rootStore.agent.app.bsky.feed.like.create(
+      const res = await this.rootStore.agent.app.bsky.feed.like.create(
         {
           repo: this.rootStore.me.did,
         },
@@ -83,14 +102,29 @@ export class AlgoItemModel {
             uri: this.data.uri,
             cid: this.data.cid,
           },
-          createdAt: new Date().toString(),
+          createdAt: new Date().toISOString(),
         },
       )
+      this.toggleLiked(res.uri)
+      this.incrementLike()
     } catch (e: any) {
       this.rootStore.log.error('Failed to like feed', e)
     }
   }
 
+  async unlike() {
+    try {
+      await this.rootStore.agent.app.bsky.feed.like.delete({
+        repo: this.rootStore.me.did,
+        rkey: new AtUri(this.data.uri).rkey,
+      })
+      this.toggleLiked()
+      this.decrementLike()
+    } catch (e: any) {
+      this.rootStore.log.error('Failed to unlike feed', e)
+    }
+  }
+
   static async getView(store: RootStoreModel, uri: string) {
     const res = await store.agent.app.bsky.feed.getFeedGenerator({
       feed: uri,
diff --git a/src/view/screens/CustomFeed.tsx b/src/view/screens/CustomFeed.tsx
index 070db8c07..be6261ac2 100644
--- a/src/view/screens/CustomFeed.tsx
+++ b/src/view/screens/CustomFeed.tsx
@@ -1,6 +1,6 @@
 import {NativeStackScreenProps} from '@react-navigation/native-stack'
 import {usePalette} from 'lib/hooks/usePalette'
-import {HeartIcon} from 'lib/icons'
+import {HeartIcon, HeartIconSolid} from 'lib/icons'
 import {CommonNavigatorParams} from 'lib/routes/types'
 import {colors, s} from 'lib/styles'
 import {observer} from 'mobx-react-lite'
@@ -74,13 +74,21 @@ export const CustomFeed = withAuthRequired(
               <TouchableOpacity
                 accessibilityRole="button"
                 onPress={() => {
-                  currentFeed?.like()
+                  if (currentFeed?.isLiked) {
+                    currentFeed?.unlike()
+                  } else {
+                    currentFeed?.like()
+                  }
                 }}
                 style={[styles.likeButton]}>
                 <Text style={[pal.text, s.semiBold]}>
                   {currentFeed?.data.likeCount}
                 </Text>
-                <HeartIcon strokeWidth={3} size={18} style={styles.liked} />
+                {currentFeed?.isLiked ? (
+                  <HeartIconSolid size={18} style={styles.liked} />
+                ) : (
+                  <HeartIcon strokeWidth={3} size={18} style={styles.liked} />
+                )}
               </TouchableOpacity>
             </View>
           </View>