From 9a9d66dca18fa270a28905fcb0a89ad8a649f925 Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Tue, 7 May 2019 15:54:49 -0400
Subject: [PATCH 1/8] reduce needless calculation

---
 src/components/status/status.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index 43c3030e..02715253 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -139,7 +139,7 @@
           </div>
 
           <transition name="fade">
-            <div class="favs-repeated-users" v-if="combinedFavsAndRepeatsUsers.length > 0 && isFocused">
+            <div class="favs-repeated-users" v-if="isFocused && combinedFavsAndRepeatsUsers.length > 0">
               <div class="stats">
                 <div class="stat-count" v-if="statusFromGlobalRepository.rebloggedBy && statusFromGlobalRepository.rebloggedBy.length > 0">
                   <a class="stat-title">{{ $t('status.repeats') }}</a>

From 78a4ab98af96320cfaf12ad2e35e818a3886e648 Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Tue, 7 May 2019 16:20:24 -0400
Subject: [PATCH 2/8] do not regenerate status object

---
 src/modules/statuses.js | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index 1a223d09..48912adc 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -461,11 +461,9 @@ export const mutations = {
     state.timelines[timeline].flushMarker = id
   },
   addFavsAndRepeats (state, { id, favoritedByUsers, rebloggedByUsers }) {
-    state.allStatusesObject[id] = {
-      ...state.allStatusesObject[id],
-      favoritedBy: favoritedByUsers,
-      rebloggedBy: rebloggedByUsers
-    }
+    const newStatus = state.allStatusesObject[id]
+    newStatus.favoritedBy = favoritedByUsers
+    newStatus.rebloggedBy = rebloggedByUsers
   }
 }
 

From f75e40e462ea8deeb57dfb773f836b42b34fdcb1 Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Tue, 7 May 2019 16:43:54 -0400
Subject: [PATCH 3/8] sync up favoritedBy with favorite/unfavorite action

---
 src/modules/statuses.js | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index 48912adc..3559e5dd 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -1,4 +1,4 @@
-import { remove, slice, each, find, maxBy, minBy, merge, first, last, isArray, omitBy } from 'lodash'
+import { remove, slice, each, findIndex, find, maxBy, minBy, merge, first, last, isArray, omitBy } from 'lodash'
 import { set } from 'vue'
 import apiService from '../services/api/api.service.js'
 // import parse from '../services/status_parser/status_parser.js'
@@ -404,10 +404,16 @@ export const mutations = {
     const newStatus = state.allStatusesObject[status.id]
     newStatus.favorited = value
   },
-  setFavoritedConfirm (state, { status }) {
+  setFavoritedConfirm (state, { status, user }) {
     const newStatus = state.allStatusesObject[status.id]
     newStatus.favorited = status.favorited
     newStatus.fave_num = status.fave_num
+    const index = findIndex(newStatus.favoritedBy, { id: user.id })
+    if (index !== -1 && !newStatus.favorited) {
+      newStatus.favoritedBy.splice(index, 1)
+    } else if (index === -1 && newStatus.favorited) {
+      newStatus.favoritedBy.push(user)
+    }
   },
   setRetweeted (state, { status, value }) {
     const newStatus = state.allStatusesObject[status.id]
@@ -500,7 +506,7 @@ const statuses = {
       commit('setFavorited', { status, value: true })
       apiService.favorite({ id: status.id, credentials: rootState.users.currentUser.credentials })
         .then(status => {
-          commit('setFavoritedConfirm', { status })
+          commit('setFavoritedConfirm', { status, user: rootState.users.currentUser })
         })
     },
     unfavorite ({ rootState, commit }, status) {
@@ -508,7 +514,7 @@ const statuses = {
       commit('setFavorited', { status, value: false })
       apiService.unfavorite({ id: status.id, credentials: rootState.users.currentUser.credentials })
         .then(status => {
-          commit('setFavoritedConfirm', { status })
+          commit('setFavoritedConfirm', { status, user: rootState.users.currentUser })
         })
     },
     retweet ({ rootState, commit }, status) {

From ff3a7e8b5ba4a46c740eea8e59b8746088e09a05 Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Tue, 7 May 2019 23:17:52 -0400
Subject: [PATCH 4/8] update status interaction upon retweet action response

---
 src/modules/statuses.js | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index 3559e5dd..9556c6d4 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -428,6 +428,17 @@ export const mutations = {
 
     newStatus.repeated = value
   },
+  setRetweetedConfirm (state, { status, user }) {
+    const newStatus = state.allStatusesObject[status.id]
+    newStatus.repeated = status.repeated
+    newStatus.repeat_num = status.repeat_num
+    const index = findIndex(newStatus.rebloggedBy, { id: user.id })
+    if (index !== -1 && !newStatus.repeated) {
+      newStatus.rebloggedBy.splice(index, 1)
+    } else if (index === -1 && newStatus.repeated) {
+      newStatus.rebloggedBy.push(user)
+    }
+  },
   setDeleted (state, { status }) {
     const newStatus = state.allStatusesObject[status.id]
     newStatus.deleted = true
@@ -521,10 +532,16 @@ const statuses = {
       // Optimistic retweeting...
       commit('setRetweeted', { status, value: true })
       apiService.retweet({ id: status.id, credentials: rootState.users.currentUser.credentials })
+        .then(status => {
+          commit('setRetweetedConfirm', { status: status.retweeted_status, user: rootState.users.currentUser })
+        })
     },
     unretweet ({ rootState, commit }, status) {
       commit('setRetweeted', { status, value: false })
       apiService.unretweet({ id: status.id, credentials: rootState.users.currentUser.credentials })
+        .then(status => {
+          commit('setRetweetedConfirm', { status, user: rootState.users.currentUser })
+        })
     },
     queueFlush ({ rootState, commit }, { timeline, id }) {
       commit('queueFlush', { timeline, id })

From 28c2a700e1f06ac8f718d1b6c8b571720f4777b4 Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Tue, 7 May 2019 23:19:46 -0400
Subject: [PATCH 5/8] update favorite number earlier

---
 src/modules/statuses.js | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index 9556c6d4..f384c6d3 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -402,6 +402,15 @@ export const mutations = {
   },
   setFavorited (state, { status, value }) {
     const newStatus = state.allStatusesObject[status.id]
+
+    if (newStatus.favorited !== value) {
+      if (value) {
+        newStatus.fave_num++
+      } else {
+        newStatus.fave_num--
+      }
+    }
+
     newStatus.favorited = value
   },
   setFavoritedConfirm (state, { status, user }) {

From a54cf47ba504712369574270ff15af23d3d634f9 Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Tue, 7 May 2019 23:21:19 -0400
Subject: [PATCH 6/8] clean up

---
 src/modules/statuses.js | 29 +++++++----------------------
 1 file changed, 7 insertions(+), 22 deletions(-)

diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index f384c6d3..527789f8 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -488,8 +488,8 @@ export const mutations = {
   },
   addFavsAndRepeats (state, { id, favoritedByUsers, rebloggedByUsers }) {
     const newStatus = state.allStatusesObject[id]
-    newStatus.favoritedBy = favoritedByUsers
-    newStatus.rebloggedBy = rebloggedByUsers
+    newStatus.favoritedBy = favoritedByUsers.filter(_ => _)
+    newStatus.rebloggedBy = rebloggedByUsers.filter(_ => _)
   }
 }
 
@@ -525,32 +525,24 @@ const statuses = {
       // Optimistic favoriting...
       commit('setFavorited', { status, value: true })
       apiService.favorite({ id: status.id, credentials: rootState.users.currentUser.credentials })
-        .then(status => {
-          commit('setFavoritedConfirm', { status, user: rootState.users.currentUser })
-        })
+        .then(status => commit('setFavoritedConfirm', { status, user: rootState.users.currentUser }))
     },
     unfavorite ({ rootState, commit }, status) {
       // Optimistic favoriting...
       commit('setFavorited', { status, value: false })
       apiService.unfavorite({ id: status.id, credentials: rootState.users.currentUser.credentials })
-        .then(status => {
-          commit('setFavoritedConfirm', { status, user: rootState.users.currentUser })
-        })
+        .then(status => commit('setFavoritedConfirm', { status, user: rootState.users.currentUser }))
     },
     retweet ({ rootState, commit }, status) {
       // Optimistic retweeting...
       commit('setRetweeted', { status, value: true })
       apiService.retweet({ id: status.id, credentials: rootState.users.currentUser.credentials })
-        .then(status => {
-          commit('setRetweetedConfirm', { status: status.retweeted_status, user: rootState.users.currentUser })
-        })
+        .then(status => commit('setRetweetedConfirm', { status: status.retweeted_status, user: rootState.users.currentUser }))
     },
     unretweet ({ rootState, commit }, status) {
       commit('setRetweeted', { status, value: false })
       apiService.unretweet({ id: status.id, credentials: rootState.users.currentUser.credentials })
-        .then(status => {
-          commit('setRetweetedConfirm', { status, user: rootState.users.currentUser })
-        })
+        .then(status => commit('setRetweetedConfirm', { status, user: rootState.users.currentUser }))
     },
     queueFlush ({ rootState, commit }, { timeline, id }) {
       commit('queueFlush', { timeline, id })
@@ -567,14 +559,7 @@ const statuses = {
         rootState.api.backendInteractor.fetchFavoritedByUsers(id),
         rootState.api.backendInteractor.fetchRebloggedByUsers(id)
       ]).then(([favoritedByUsers, rebloggedByUsers]) =>
-        commit(
-          'addFavsAndRepeats',
-          {
-            id,
-            favoritedByUsers: favoritedByUsers.filter(_ => _),
-            rebloggedByUsers: rebloggedByUsers.filter(_ => _)
-          }
-        )
+        commit('addFavsAndRepeats', { id, favoritedByUsers, rebloggedByUsers })
       )
     }
   },

From 26131266a926c8511d92e3d10aa618af5e94c6e3 Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Tue, 7 May 2019 23:27:22 -0400
Subject: [PATCH 7/8] refactor api service functions using new helper

---
 src/services/api/api.service.js | 48 +++------------------------------
 1 file changed, 4 insertions(+), 44 deletions(-)

diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index da44fc54..b7a602b8 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -506,62 +506,22 @@ const verifyCredentials = (user) => {
 }
 
 const favorite = ({ id, credentials }) => {
-  return fetch(MASTODON_FAVORITE_URL(id), {
-    headers: authHeaders(credentials),
-    method: 'POST'
-  })
-    .then(response => {
-      if (response.ok) {
-        return response.json()
-      } else {
-        throw new Error('Error favoriting post')
-      }
-    })
+  return promisedRequest({ url: MASTODON_FAVORITE_URL(id), method: 'POST', credentials })
     .then((data) => parseStatus(data))
 }
 
 const unfavorite = ({ id, credentials }) => {
-  return fetch(MASTODON_UNFAVORITE_URL(id), {
-    headers: authHeaders(credentials),
-    method: 'POST'
-  })
-    .then(response => {
-      if (response.ok) {
-        return response.json()
-      } else {
-        throw new Error('Error removing favorite')
-      }
-    })
+  return promisedRequest({ url: MASTODON_UNFAVORITE_URL(id), method: 'POST', credentials })
     .then((data) => parseStatus(data))
 }
 
 const retweet = ({ id, credentials }) => {
-  return fetch(MASTODON_RETWEET_URL(id), {
-    headers: authHeaders(credentials),
-    method: 'POST'
-  })
-    .then(response => {
-      if (response.ok) {
-        return response.json()
-      } else {
-        throw new Error('Error repeating post')
-      }
-    })
+  return promisedRequest({ url: MASTODON_RETWEET_URL(id), method: 'POST', credentials })
     .then((data) => parseStatus(data))
 }
 
 const unretweet = ({ id, credentials }) => {
-  return fetch(MASTODON_UNRETWEET_URL(id), {
-    headers: authHeaders(credentials),
-    method: 'POST'
-  })
-    .then(response => {
-      if (response.ok) {
-        return response.json()
-      } else {
-        throw new Error('Error removing repeat')
-      }
-    })
+  return promisedRequest({ url: MASTODON_UNRETWEET_URL(id), method: 'POST', credentials })
     .then((data) => parseStatus(data))
 }
 

From 7d60ab322ed996b067242c3f047f90814f9c8f7c Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Tue, 7 May 2019 23:36:35 -0400
Subject: [PATCH 8/8] use backendInteractor

---
 src/modules/statuses.js                               | 11 ++++++-----
 .../backend_interactor_service.js                     | 11 ++++++++++-
 2 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/src/modules/statuses.js b/src/modules/statuses.js
index 527789f8..4c92d4e1 100644
--- a/src/modules/statuses.js
+++ b/src/modules/statuses.js
@@ -524,24 +524,25 @@ const statuses = {
     favorite ({ rootState, commit }, status) {
       // Optimistic favoriting...
       commit('setFavorited', { status, value: true })
-      apiService.favorite({ id: status.id, credentials: rootState.users.currentUser.credentials })
+      rootState.api.backendInteractor.favorite(status.id)
         .then(status => commit('setFavoritedConfirm', { status, user: rootState.users.currentUser }))
     },
     unfavorite ({ rootState, commit }, status) {
-      // Optimistic favoriting...
+      // Optimistic unfavoriting...
       commit('setFavorited', { status, value: false })
-      apiService.unfavorite({ id: status.id, credentials: rootState.users.currentUser.credentials })
+      rootState.api.backendInteractor.unfavorite(status.id)
         .then(status => commit('setFavoritedConfirm', { status, user: rootState.users.currentUser }))
     },
     retweet ({ rootState, commit }, status) {
       // Optimistic retweeting...
       commit('setRetweeted', { status, value: true })
-      apiService.retweet({ id: status.id, credentials: rootState.users.currentUser.credentials })
+      rootState.api.backendInteractor.retweet(status.id)
         .then(status => commit('setRetweetedConfirm', { status: status.retweeted_status, user: rootState.users.currentUser }))
     },
     unretweet ({ rootState, commit }, status) {
+      // Optimistic unretweeting...
       commit('setRetweeted', { status, value: false })
-      apiService.unretweet({ id: status.id, credentials: rootState.users.currentUser.credentials })
+      rootState.api.backendInteractor.unretweet(status.id)
         .then(status => commit('setRetweetedConfirm', { status, user: rootState.users.currentUser }))
     },
     queueFlush ({ rootState, commit }, { timeline, id }) {
diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js
index 58bb1248..c2b93de4 100644
--- a/src/services/backend_interactor_service/backend_interactor_service.js
+++ b/src/services/backend_interactor_service/backend_interactor_service.js
@@ -117,6 +117,11 @@ const backendInteractorService = (credentials) => {
   const fetchRebloggedByUsers = (id) => apiService.fetchRebloggedByUsers({id})
   const reportUser = (params) => apiService.reportUser({credentials, ...params})
 
+  const favorite = (id) => apiService.favorite({id, credentials})
+  const unfavorite = (id) => apiService.unfavorite({id, credentials})
+  const retweet = (id) => apiService.retweet({id, credentials})
+  const unretweet = (id) => apiService.unretweet({id, credentials})
+
   const backendInteractorServiceInstance = {
     fetchStatus,
     fetchConversation,
@@ -161,7 +166,11 @@ const backendInteractorService = (credentials) => {
     denyUser,
     fetchFavoritedByUsers,
     fetchRebloggedByUsers,
-    reportUser
+    reportUser,
+    favorite,
+    unfavorite,
+    retweet,
+    unretweet
   }
 
   return backendInteractorServiceInstance