From 07b8115a37a22b2a7d935154e8231c8a90f199d6 Mon Sep 17 00:00:00 2001
From: dave <starpumadev@gmail.com>
Date: Tue, 19 Mar 2019 14:36:27 -0400
Subject: #444 - show `remote follow` button when logged out

---
 src/components/user_card/user_card.vue | 15 ++-------------
 1 file changed, 2 insertions(+), 13 deletions(-)

(limited to 'src/components/user_card/user_card.vue')

diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index 690e1bde..f4114e6e 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -84,14 +84,8 @@
             </button>
           </span>
         </div>
-        <div class="remote-follow" v-if='!loggedIn && user.is_local'>
-          <form method="POST" :action='subscribeUrl'>
-            <input type="hidden" name="nickname" :value="user.screen_name">
-            <input type="hidden" name="profile" value="">
-            <button click="submit" class="remote-button">
-              {{ $t('user_card.remote_follow') }}
-            </button>
-          </form>
+        <div v-if='!loggedIn && user.is_local'>
+          <RemoteFollow :user="user" />
         </div>
         <div class='block' v-if='isOtherUser && loggedIn'>
           <span v-if='user.statusnet_blocking'>
@@ -375,11 +369,6 @@
       min-height: 28px;
     }
 
-    .remote-follow {
-      max-width: 220px;
-      min-height: 28px;
-    }
-
     .follow {
       max-width: 220px;
       min-height: 28px;
-- 
cgit v1.2.3-70-g09d2


From 3255950b0e9a16f2a477d606b91d90bed8a6cef7 Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Sun, 24 Feb 2019 03:02:04 -0500
Subject: Add mute/unmute featrue and mutes management tab

---
 src/components/mute_card/mute_card.js              |  2 +-
 src/components/user_card/user_card.js              | 20 +++++-----
 src/components/user_card/user_card.vue             |  4 +-
 src/components/user_settings/user_settings.vue     |  6 +++
 src/modules/users.js                               | 32 ++++++++++------
 src/services/api/api.service.js                    | 44 ++++++++++++++++++++--
 .../backend_interactor_service.js                  |  6 ++-
 src/utils/url.js                                   |  9 +++++
 8 files changed, 93 insertions(+), 30 deletions(-)
 create mode 100644 src/utils/url.js

(limited to 'src/components/user_card/user_card.vue')

diff --git a/src/components/mute_card/mute_card.js b/src/components/mute_card/mute_card.js
index 65c9cfb5..5ef17b60 100644
--- a/src/components/mute_card/mute_card.js
+++ b/src/components/mute_card/mute_card.js
@@ -12,7 +12,7 @@ const MuteCard = {
       return this.$store.getters.findUser(this.userId)
     },
     muted () {
-      return this.user.muted
+      return this.user.mastodonMuted
     }
   },
   components: {
diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js
index b07da675..61b784fe 100644
--- a/src/components/user_card/user_card.js
+++ b/src/components/user_card/user_card.js
@@ -121,21 +121,19 @@ export default {
       })
     },
     blockUser () {
-      const store = this.$store
-      store.state.api.backendInteractor.blockUser(this.user.id)
-        .then((blockedUser) => {
-          store.commit('addNewUsers', [blockedUser])
-          store.commit('removeStatus', { timeline: 'friends', userId: this.user.id })
-          store.commit('removeStatus', { timeline: 'public', userId: this.user.id })
-          store.commit('removeStatus', { timeline: 'publicAndExternal', userId: this.user.id })
-        })
+      this.$store.dispatch('blockUser', this.user.id)
     },
     unblockUser () {
-      const store = this.$store
-      store.state.api.backendInteractor.unblockUser(this.user.id)
-        .then((unblockedUser) => store.commit('addNewUsers', [unblockedUser]))
+      this.$store.dispatch('unblockUser', this.user.id)
+    },
+    muteUser () {   // Mastodon Mute
+      this.$store.dispatch('muteUser', this.user.id)
+    },
+    unmuteUser () { // Mastodon Unmute
+      this.$store.dispatch('unmuteUser', this.user.id)
     },
     toggleMute () {
+      // TODO: Pleroma mute/unmute, Need to migrate to the Mastodon API
       const store = this.$store
       store.commit('setMuted', {user: this.user, muted: !this.user.muted})
       store.state.api.backendInteractor.setUserMute(this.user)
diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index f4114e6e..3259d1c5 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -74,12 +74,12 @@
         </div>
         <div class='mute' v-if='isOtherUser && loggedIn'>
           <span v-if='user.muted'>
-            <button @click="toggleMute" class="pressed">
+            <button @click="unmuteUser" class="pressed">
               {{ $t('user_card.muted') }}
             </button>
           </span>
           <span v-if='!user.muted'>
-            <button @click="toggleMute">
+            <button @click="muteUser">
               {{ $t('user_card.mute') }}
             </button>
           </span>
diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue
index a1123638..c9e68808 100644
--- a/src/components/user_settings/user_settings.vue
+++ b/src/components/user_settings/user_settings.vue
@@ -192,6 +192,12 @@
             <template slot="empty">{{$t('settings.no_blocks')}}</template>
           </block-list>
         </div>
+
+        <div :label="$t('settings.mutes_tab')">
+          <mute-list :refresh="true">
+            <template slot="empty">{{$t('settings.no_mutes')}}</template>
+          </mute-list>
+        </div>
       </tab-switcher>
     </div>
   </div>
diff --git a/src/modules/users.js b/src/modules/users.js
index 1fe12fc8..9c89f34a 100644
--- a/src/modules/users.js
+++ b/src/modules/users.js
@@ -177,9 +177,14 @@ const users = {
           return blocks
         })
     },
-    blockUser (store, id) {
-      return store.rootState.api.backendInteractor.blockUser(id)
-        .then((user) => store.commit('addNewUsers', [user]))
+    blockUser (store, userId) {
+      return store.rootState.api.backendInteractor.blockUser(userId)
+        .then((blockedUser) => {
+          store.commit('addNewUsers', [blockedUser])
+          store.commit('removeStatus', { timeline: 'friends', userId })
+          store.commit('removeStatus', { timeline: 'public', userId })
+          store.commit('removeStatus', { timeline: 'publicAndExternal', userId })
+        })
     },
     unblockUser (store, id) {
       return store.rootState.api.backendInteractor.unblockUser(id)
@@ -188,18 +193,26 @@ const users = {
     fetchMutes (store) {
       return store.rootState.api.backendInteractor.fetchMutes()
         .then((mutedUsers) => {
-          each(mutedUsers, (user) => { user.muted = true })
+          each(mutedUsers, (user) => { user.mastodonMuted = true })
           store.commit('addNewUsers', mutedUsers)
           store.commit('saveMutes', map(mutedUsers, 'id'))
         })
     },
     muteUser (store, id) {
-      return store.state.api.backendInteractor.setUserMute({ id, muted: true })
-        .then((user) => store.commit('addNewUsers', [user]))
+      return store.rootState.api.backendInteractor.muteUser(id)
+        .then(() => {
+          const user = store.rootState.users.usersObject[id]
+          set(user, 'mastodonMuted', true)
+          store.commit('addNewUsers', [user])
+        })
     },
     unmuteUser (store, id) {
-      return store.state.api.backendInteractor.setUserMute({ id, muted: false })
-        .then((user) => store.commit('addNewUsers', [user]))
+      return store.rootState.api.backendInteractor.unmuteUser(id)
+        .then(() => {
+          const user = store.rootState.users.usersObject[id]
+          set(user, 'mastodonMuted', false)
+          store.commit('addNewUsers', [user])
+        })
     },
     addFriends ({ rootState, commit }, fetchBy) {
       return new Promise((resolve, reject) => {
@@ -350,9 +363,6 @@ const users = {
               // Start getting fresh posts.
               store.dispatch('startFetching', { timeline: 'friends' })
 
-              // Get user mutes
-              store.dispatch('fetchMutes')
-
               // Fetch our friends
               store.rootState.api.backendInteractor.fetchFriends({ id: user.id })
                 .then((friends) => commit('addNewUsers', friends))
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 176f1c18..92abf94b 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -1,3 +1,5 @@
+import { generateUrl } from '../../utils/url'
+
 /* eslint-env browser */
 const LOGIN_URL = '/api/account/verify_credentials.json'
 const FRIENDS_TIMELINE_URL = '/api/statuses/friends_timeline.json'
@@ -19,6 +21,9 @@ const DM_TIMELINE_URL = '/api/statuses/dm_timeline.json'
 const FOLLOWERS_URL = '/api/statuses/followers.json'
 const FRIENDS_URL = '/api/statuses/friends.json'
 const BLOCKS_URL = '/api/statuses/blocks.json'
+const MUTES_URL = '/api/v1/mutes.json'
+const MUTING_URL = '/api/v1/accounts/:id/mute'
+const UNMUTING_URL = '/api/v1/accounts/:id/unmute'
 const FOLLOWING_URL = '/api/friendships/create.json'
 const UNFOLLOWING_URL = '/api/friendships/destroy.json'
 const QVITTER_USER_PREF_URL = '/api/qvitter/set_profile_pref.json'
@@ -538,14 +543,43 @@ const changePassword = ({credentials, password, newPassword, newPasswordConfirma
 }
 
 const fetchMutes = ({credentials}) => {
-  const url = '/api/qvitter/mutes.json'
+  return fetch(MUTES_URL, {
+    headers: authHeaders(credentials)
+  }).then((data) => {
+    if (data.ok) {
+      return data.json()
+    }
+    throw new Error('Error fetching mutes', data)
+  })
+}
 
+const muteUser = ({id, credentials}) => {
+  const url = generateUrl(MUTING_URL, { id })
   return fetch(url, {
-    headers: authHeaders(credentials)
-  }).then((data) => data.json())
+    headers: authHeaders(credentials),
+    method: 'POST'
+  }).then((data) => {
+    if (data.ok) {
+      return data.json()
+    }
+    throw new Error('Error muting', data)
+  })
+}
+
+const unmuteUser = ({id, credentials}) => {
+  const url = generateUrl(UNMUTING_URL, { id })
+  return fetch(url, {
+    headers: authHeaders(credentials),
+    method: 'POST'
+  }).then((data) => {
+    if (data.ok) {
+      return data.json()
+    }
+    throw new Error('Error unmuting', data)
+  })
 }
 
-const fetchBlocks = ({page, credentials}) => {
+const fetchBlocks = ({credentials}) => {
   return fetch(BLOCKS_URL, {
     headers: authHeaders(credentials)
   }).then((data) => {
@@ -620,6 +654,8 @@ const apiService = {
   fetchAllFollowing,
   setUserMute,
   fetchMutes,
+  muteUser,
+  unmuteUser,
   fetchBlocks,
   fetchOAuthTokens,
   revokeOAuthToken,
diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js
index cbd0b733..674fb4a4 100644
--- a/src/services/backend_interactor_service/backend_interactor_service.js
+++ b/src/services/backend_interactor_service/backend_interactor_service.js
@@ -67,7 +67,9 @@ const backendInteractorService = (credentials) => {
   }
 
   const fetchMutes = () => apiService.fetchMutes({credentials})
-  const fetchBlocks = (params) => apiService.fetchBlocks({credentials, ...params})
+  const muteUser = (id) => apiService.muteUser({credentials, id})
+  const unmuteUser = (id) => apiService.unmuteUser({credentials, id})
+  const fetchBlocks = () => apiService.fetchBlocks({credentials})
   const fetchFollowRequests = () => apiService.fetchFollowRequests({credentials})
   const fetchOAuthTokens = () => apiService.fetchOAuthTokens({credentials})
   const revokeOAuthToken = (id) => apiService.revokeOAuthToken({id, credentials})
@@ -102,6 +104,8 @@ const backendInteractorService = (credentials) => {
     startFetching,
     setUserMute,
     fetchMutes,
+    muteUser,
+    unmuteUser,
     fetchBlocks,
     fetchOAuthTokens,
     revokeOAuthToken,
diff --git a/src/utils/url.js b/src/utils/url.js
new file mode 100644
index 00000000..79ea7394
--- /dev/null
+++ b/src/utils/url.js
@@ -0,0 +1,9 @@
+// Generate url based on template
+// Example: /api/v1/accounts/:id/mute -> /api/v1/accounts/123/mute
+export const generateUrl = (template, params = {}) => {
+  let url = template
+  Object.entries(params).forEach(([key, value]) => {
+    url = url.replace(':' + key, value)
+  })
+  return url
+}
-- 
cgit v1.2.3-70-g09d2

