From ca190251870c239d49c45d245a2a219fe4169625 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Tue, 4 Dec 2018 12:50:29 +0300
Subject: [PATCH] Added support for async following including delayed
 confirmation if we followed user or not

---
 .../user_card_content/user_card_content.js    | 46 +++++++++++++++++++
 .../user_card_content/user_card_content.vue   | 21 +++++++--
 src/i18n/en.json                              |  4 ++
 src/i18n/ru.json                              |  4 ++
 4 files changed, 71 insertions(+), 4 deletions(-)

diff --git a/src/components/user_card_content/user_card_content.js b/src/components/user_card_content/user_card_content.js
index b5dd9b91..235cfb49 100644
--- a/src/components/user_card_content/user_card_content.js
+++ b/src/components/user_card_content/user_card_content.js
@@ -5,6 +5,8 @@ export default {
   props: [ 'user', 'switcher', 'selected', 'hideBio' ],
   data () {
     return {
+      followRequestInProgress: false,
+      followRequestSent: false,
       hideUserStatsLocal: typeof this.$store.state.config.hideUserStats === 'undefined'
         ? this.$store.state.instance.hideUserStats
         : this.$store.state.config.hideUserStats
@@ -70,13 +72,57 @@ export default {
   methods: {
     followUser () {
       const store = this.$store
+      this.followRequestInProgress = true
       store.state.api.backendInteractor.followUser(this.user.id)
         .then((followedUser) => store.commit('addNewUsers', [followedUser]))
+        .then(() => {
+          if (this.user.following) {
+            this.followRequestInProgress = false
+            return
+          }
+          if (!this.user.locked) {
+            let attemptsLeft = 3
+            const fetchUser = () => new Promise((resolve, reject) => {
+              setTimeout(() => {
+                store.state.api.backendInteractor.fetchUser({ id: this.user.id })
+                  .then((user) => store.commit('addNewUsers', [user]))
+                  .then(() => resolve(this.user.following))
+                  .catch((e) => reject(e))
+              }, 500)
+            }).then((confirmed) => {
+              if (!confirmed && attemptsLeft > 0) {
+                attemptsLeft--
+                return fetchUser()
+              } else if (confirmed) {
+                return true
+              } else {
+                return false
+              }
+            })
+
+            return fetchUser()
+              .then((successfulConfirmation) => {
+                if (successfulConfirmation) {
+                  this.followRequestInProgress = false
+                } else {
+                  this.followRequestInProgress = false
+                  this.followRequestSent = true
+                }
+              })
+          } else {
+            this.followRequestInProgress = false
+            this.followRequestSent = true
+          }
+        })
     },
     unfollowUser () {
       const store = this.$store
+      this.followRequestInProgress = true
       store.state.api.backendInteractor.unfollowUser(this.user.id)
         .then((unfollowedUser) => store.commit('addNewUsers', [unfollowedUser]))
+        .then(() => {
+          this.followRequestInProgress = false
+        })
     },
     blockUser () {
       const store = this.$store
diff --git a/src/components/user_card_content/user_card_content.vue b/src/components/user_card_content/user_card_content.vue
index 84669d7f..1dcf348f 100644
--- a/src/components/user_card_content/user_card_content.vue
+++ b/src/components/user_card_content/user_card_content.vue
@@ -44,13 +44,26 @@
           <div class="follow" v-if="loggedIn">
             <span v-if="user.following">
               <!--Following them!-->
-              <button @click="unfollowUser" class="pressed">
-                {{ $t('user_card.following') }}
+              <button @click="unfollowUser" class="pressed" :disabled="followRequestInProgress" :title="$t('user_card.follow_unfollow')">
+                <template v-if="followRequestInProgress">
+                  {{ $t('user_card.follow_progress') }}
+                </template>
+                <template v-else>
+                  {{ $t('user_card.following') }}
+                </template>
               </button>
             </span>
             <span v-if="!user.following">
-              <button @click="followUser">
-                {{ $t('user_card.follow') }}
+              <button @click="followUser" :disabled="followRequestInProgress" :title="followRequestSent ? $t('user_card.follow_again') : ''">
+                <template v-if="followRequestInProgress">
+                  {{ $t('user_card.follow_progress') }}
+                </template>
+                <template v-else-if="followRequestSent">
+                  {{ $t('user_card.follow_sent') }}
+                </template>
+                <template v-else>
+                  {{ $t('user_card.follow') }}
+                </template>
               </button>
             </span>
           </div>
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 893db931..9d12f09e 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -193,6 +193,10 @@
     "blocked": "Blocked!",
     "deny": "Deny",
     "follow": "Follow",
+    "follow_sent": "Request sent!",
+    "follow_progress": "Requesting…",
+    "follow_again": "Send request again?",
+    "follow_unfollow": "Stop following",
     "followees": "Following",
     "followers": "Followers",
     "following": "Following!",
diff --git a/src/i18n/ru.json b/src/i18n/ru.json
index 9c28ccf4..37d88e3c 100644
--- a/src/i18n/ru.json
+++ b/src/i18n/ru.json
@@ -156,6 +156,10 @@
     "block": "Заблокировать",
     "blocked": "Заблокирован",
     "follow": "Читать",
+    "follow_sent": "Запрос отправлен!",
+    "follow_progress": "Запрашиваем…",
+    "follow_again": "Запросить еще заново?",
+    "follow_unfollow": "Перестать читать",
     "followees": "Читаемые",
     "followers": "Читатели",
     "following": "Читаю",