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/lib/api.ts38
-rw-r--r--src/state/models/feed-view.ts55
-rw-r--r--src/state/models/me.ts2
-rw-r--r--src/state/models/notifications-view.ts4
-rw-r--r--src/state/models/post-thread-view.ts49
-rw-r--r--src/state/models/profile-ui.ts2
-rw-r--r--src/state/models/votes-view.ts (renamed from src/state/models/liked-by-view.ts)38
7 files changed, 132 insertions, 56 deletions
diff --git a/src/state/lib/api.ts b/src/state/lib/api.ts
index 3d2d26a56..efaac5c7b 100644
--- a/src/state/lib/api.ts
+++ b/src/state/lib/api.ts
@@ -50,21 +50,45 @@ export async function post(
   )
 }
 
-export async function like(store: RootStoreModel, uri: string, cid: string) {
-  return await store.api.app.bsky.feed.like.create(
+export async function upvote(store: RootStoreModel, uri: string, cid: string) {
+  return await store.api.app.bsky.feed.vote.create(
     {did: store.me.did || ''},
     {
       subject: {uri, cid},
+      direction: 'up',
       createdAt: new Date().toISOString(),
     },
   )
 }
 
-export async function unlike(store: RootStoreModel, likeUri: string) {
-  const likeUrip = new AtUri(likeUri)
-  return await store.api.app.bsky.feed.like.delete({
-    did: likeUrip.hostname,
-    rkey: likeUrip.rkey,
+export async function unupvote(store: RootStoreModel, upvoteUri: string) {
+  const urip = new AtUri(upvoteUri)
+  return await store.api.app.bsky.feed.vote.delete({
+    did: urip.hostname,
+    rkey: urip.rkey,
+  })
+}
+
+export async function downvote(
+  store: RootStoreModel,
+  uri: string,
+  cid: string,
+) {
+  return await store.api.app.bsky.feed.vote.create(
+    {did: store.me.did || ''},
+    {
+      subject: {uri, cid},
+      direction: 'down',
+      createdAt: new Date().toISOString(),
+    },
+  )
+}
+
+export async function undownvote(store: RootStoreModel, downvoteUri: string) {
+  const urip = new AtUri(downvoteUri)
+  return await store.api.app.bsky.feed.vote.delete({
+    did: urip.hostname,
+    rkey: urip.rkey,
   })
 }
 
diff --git a/src/state/models/feed-view.ts b/src/state/models/feed-view.ts
index 9505ad556..392f9d215 100644
--- a/src/state/models/feed-view.ts
+++ b/src/state/models/feed-view.ts
@@ -6,7 +6,8 @@ import * as apilib from '../lib/api'
 
 export class FeedItemMyStateModel {
   repost?: string
-  like?: string
+  upvote?: string
+  downvote?: string
 
   constructor() {
     makeAutoObservable(this)
@@ -29,7 +30,8 @@ export class FeedItemModel implements GetTimeline.FeedItem {
     | GetTimeline.UnknownEmbed
   replyCount: number = 0
   repostCount: number = 0
-  likeCount: number = 0
+  upvoteCount: number = 0
+  downvoteCount: number = 0
   indexedAt: string = ''
   myState = new FeedItemMyStateModel()
 
@@ -52,26 +54,53 @@ export class FeedItemModel implements GetTimeline.FeedItem {
     this.embed = v.embed
     this.replyCount = v.replyCount
     this.repostCount = v.repostCount
-    this.likeCount = v.likeCount
+    this.upvoteCount = v.upvoteCount
+    this.downvoteCount = v.downvoteCount
     this.indexedAt = v.indexedAt
     if (v.myState) {
-      this.myState.like = v.myState.like
+      this.myState.upvote = v.myState.upvote
+      this.myState.downvote = v.myState.downvote
       this.myState.repost = v.myState.repost
     }
   }
 
-  async toggleLike() {
-    if (this.myState.like) {
-      await apilib.unlike(this.rootStore, this.myState.like)
+  async _clearVotes() {
+    if (this.myState.upvote) {
+      await apilib.unupvote(this.rootStore, this.myState.upvote)
       runInAction(() => {
-        this.likeCount--
-        this.myState.like = undefined
+        this.upvoteCount--
+        this.myState.upvote = undefined
       })
-    } else {
-      const res = await apilib.like(this.rootStore, this.uri, this.cid)
+    }
+    if (this.myState.downvote) {
+      await apilib.undownvote(this.rootStore, this.myState.downvote)
+      runInAction(() => {
+        this.downvoteCount--
+        this.myState.downvote = undefined
+      })
+    }
+  }
+
+  async toggleUpvote() {
+    const wasntUpvoted = !this.myState.upvote
+    await this._clearVotes()
+    if (wasntUpvoted) {
+      const res = await apilib.upvote(this.rootStore, this.uri, this.cid)
+      runInAction(() => {
+        this.upvoteCount++
+        this.myState.upvote = res.uri
+      })
+    }
+  }
+
+  async toggleDownvote() {
+    const wasntDownvoted = !this.myState.downvote
+    await this._clearVotes()
+    if (wasntDownvoted) {
+      const res = await apilib.downvote(this.rootStore, this.uri, this.cid)
       runInAction(() => {
-        this.likeCount++
-        this.myState.like = res.uri
+        this.downvoteCount++
+        this.myState.downvote = res.uri
       })
     }
   }
diff --git a/src/state/models/me.ts b/src/state/models/me.ts
index 7a94d63ac..70f45097d 100644
--- a/src/state/models/me.ts
+++ b/src/state/models/me.ts
@@ -26,7 +26,7 @@ export class MeModel {
       this.did = sess.data.did || ''
       this.handle = sess.data.handle
       const profile = await this.rootStore.api.app.bsky.actor.getProfile({
-        user: this.did,
+        actor: this.did,
       })
       runInAction(() => {
         if (profile?.data) {
diff --git a/src/state/models/notifications-view.ts b/src/state/models/notifications-view.ts
index 8d8eede05..7b1508a19 100644
--- a/src/state/models/notifications-view.ts
+++ b/src/state/models/notifications-view.ts
@@ -57,8 +57,8 @@ export class NotificationsViewItemModel implements GroupedNotification {
     }
   }
 
-  get isLike() {
-    return this.reason === 'like'
+  get isUpvote() {
+    return this.reason === 'vote'
   }
 
   get isRepost() {
diff --git a/src/state/models/post-thread-view.ts b/src/state/models/post-thread-view.ts
index 0fc0dadbb..7a735de03 100644
--- a/src/state/models/post-thread-view.ts
+++ b/src/state/models/post-thread-view.ts
@@ -13,8 +13,9 @@ function* reactKeyGenerator(): Generator<string> {
 }
 
 export class PostThreadViewPostMyStateModel {
-  like?: string
   repost?: string
+  upvote?: string
+  downvote?: string
 
   constructor() {
     makeAutoObservable(this)
@@ -40,7 +41,8 @@ export class PostThreadViewPostModel implements GetPostThread.Post {
   replyCount: number = 0
   replies?: PostThreadViewPostModel[]
   repostCount: number = 0
-  likeCount: number = 0
+  upvoteCount: number = 0
+  downvoteCount: number = 0
   indexedAt: string = ''
   myState = new PostThreadViewPostMyStateModel()
 
@@ -105,18 +107,43 @@ export class PostThreadViewPostModel implements GetPostThread.Post {
     }
   }
 
-  async toggleLike() {
-    if (this.myState.like) {
-      await apilib.unlike(this.rootStore, this.myState.like)
+  async _clearVotes() {
+    if (this.myState.upvote) {
+      await apilib.unupvote(this.rootStore, this.myState.upvote)
       runInAction(() => {
-        this.likeCount--
-        this.myState.like = undefined
+        this.upvoteCount--
+        this.myState.upvote = undefined
       })
-    } else {
-      const res = await apilib.like(this.rootStore, this.uri, this.cid)
+    }
+    if (this.myState.downvote) {
+      await apilib.undownvote(this.rootStore, this.myState.downvote)
+      runInAction(() => {
+        this.downvoteCount--
+        this.myState.downvote = undefined
+      })
+    }
+  }
+
+  async toggleUpvote() {
+    const wasntUpvoted = !this.myState.upvote
+    await this._clearVotes()
+    if (wasntUpvoted) {
+      const res = await apilib.upvote(this.rootStore, this.uri, this.cid)
+      runInAction(() => {
+        this.upvoteCount++
+        this.myState.upvote = res.uri
+      })
+    }
+  }
+
+  async toggleDownvote() {
+    const wasntDownvoted = !this.myState.downvote
+    await this._clearVotes()
+    if (wasntDownvoted) {
+      const res = await apilib.downvote(this.rootStore, this.uri, this.cid)
       runInAction(() => {
-        this.likeCount++
-        this.myState.like = res.uri
+        this.downvoteCount++
+        this.myState.downvote = res.uri
       })
     }
   }
diff --git a/src/state/models/profile-ui.ts b/src/state/models/profile-ui.ts
index 0ad893dd1..2ec615a9c 100644
--- a/src/state/models/profile-ui.ts
+++ b/src/state/models/profile-ui.ts
@@ -37,7 +37,7 @@ export class ProfileUiModel {
       },
       {autoBind: true},
     )
-    this.profile = new ProfileViewModel(rootStore, {user: params.user})
+    this.profile = new ProfileViewModel(rootStore, {actor: params.user})
     this.feed = new FeedModel(rootStore, 'author', {
       author: params.user,
       limit: 10,
diff --git a/src/state/models/liked-by-view.ts b/src/state/models/votes-view.ts
index facda9032..d70737021 100644
--- a/src/state/models/liked-by-view.ts
+++ b/src/state/models/votes-view.ts
@@ -1,45 +1,41 @@
 import {makeAutoObservable, runInAction} from 'mobx'
 import {AtUri} from '../../third-party/uri'
-import * as GetLikedBy from '../../third-party/api/src/client/types/app/bsky/feed/getLikedBy'
+import * as GetVotes from '../../third-party/api/src/client/types/app/bsky/feed/getVotes'
 import {RootStoreModel} from './root-store'
 
-type LikedByItem = GetLikedBy.OutputSchema['likedBy'][number]
+type VoteItem = GetVotes.OutputSchema['votes'][number]
 
-export class LikedByViewItemModel implements LikedByItem {
+export class VotesViewItemModel implements VoteItem {
   // ui state
   _reactKey: string = ''
 
   // data
-  did: string = ''
-  handle: string = ''
-  displayName: string = ''
-  createdAt?: string
+  direction: 'up' | 'down' = 'up'
   indexedAt: string = ''
+  createdAt: string = ''
+  actor: GetVotes.Actor = {did: '', handle: ''}
 
-  constructor(reactKey: string, v: LikedByItem) {
+  constructor(reactKey: string, v: VoteItem) {
     makeAutoObservable(this)
     this._reactKey = reactKey
     Object.assign(this, v)
   }
 }
 
-export class LikedByViewModel {
+export class VotesViewModel {
   // state
   isLoading = false
   isRefreshing = false
   hasLoaded = false
   error = ''
   resolvedUri = ''
-  params: GetLikedBy.QueryParams
+  params: GetVotes.QueryParams
 
   // data
   uri: string = ''
-  likedBy: LikedByViewItemModel[] = []
+  votes: VotesViewItemModel[] = []
 
-  constructor(
-    public rootStore: RootStoreModel,
-    params: GetLikedBy.QueryParams,
-  ) {
+  constructor(public rootStore: RootStoreModel, params: GetVotes.QueryParams) {
     makeAutoObservable(
       this,
       {
@@ -113,7 +109,7 @@ export class LikedByViewModel {
   private async _fetch(isRefreshing = false) {
     this._xLoading(isRefreshing)
     try {
-      const res = await this.rootStore.api.app.bsky.feed.getLikedBy(
+      const res = await this.rootStore.api.app.bsky.feed.getVotes(
         Object.assign({}, this.params, {uri: this.resolvedUri}),
       )
       this._replaceAll(res)
@@ -123,15 +119,15 @@ export class LikedByViewModel {
     }
   }
 
-  private _replaceAll(res: GetLikedBy.Response) {
-    this.likedBy.length = 0
+  private _replaceAll(res: GetVotes.Response) {
+    this.votes.length = 0
     let counter = 0
-    for (const item of res.data.likedBy) {
+    for (const item of res.data.votes) {
       this._append(counter++, item)
     }
   }
 
-  private _append(keyId: number, item: LikedByItem) {
-    this.likedBy.push(new LikedByViewItemModel(`item-${keyId}`, item))
+  private _append(keyId: number, item: VoteItem) {
+    this.votes.push(new VotesViewItemModel(`item-${keyId}`, item))
   }
 }