From 88731ee18dbe25c80c7b1c03f55881ef27e87275 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90?= <sxzz@sxzz.moe>
Date: Tue, 10 Jan 2023 15:49:49 +0800
Subject: [PATCH] feat(account): predict relationship from context

---
 components/account/AccountCard.vue              |  3 ++-
 components/account/AccountFollowButton.vue      | 13 +++++++------
 components/account/AccountPaginator.vue         |  2 ++
 composables/users.ts                            |  4 +++-
 pages/[[server]]/@[account]/index/followers.vue |  4 +++-
 pages/[[server]]/@[account]/index/following.vue |  4 +++-
 6 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/components/account/AccountCard.vue b/components/account/AccountCard.vue
index 7fb5bac6..eae4f11e 100644
--- a/components/account/AccountCard.vue
+++ b/components/account/AccountCard.vue
@@ -4,6 +4,7 @@ import type { mastodon } from 'masto'
 const { account } = defineProps<{
   account: mastodon.v1.Account
   hoverCard?: boolean
+  relationshipContext?: 'followedBy' | 'following'
 }>()
 
 cacheAccount(account)
@@ -19,7 +20,7 @@ cacheAccount(account)
       :to="getAccountRoute(account)"
     />
     <div h-full p1 shrink-0>
-      <AccountFollowButton :account="account" />
+      <AccountFollowButton :account="account" :context="relationshipContext" />
     </div>
   </div>
 </template>
diff --git a/components/account/AccountFollowButton.vue b/components/account/AccountFollowButton.vue
index bd073df5..6ee4bff3 100644
--- a/components/account/AccountFollowButton.vue
+++ b/components/account/AccountFollowButton.vue
@@ -1,9 +1,10 @@
 <script setup lang="ts">
 import type { mastodon } from 'masto'
 
-const { account, command, ...props } = defineProps<{
+const { account, command, context, ...props } = defineProps<{
   account: mastodon.v1.Account
   relationship?: mastodon.v1.Relationship
+  context?: 'followedBy' | 'following'
   command?: boolean
 }>()
 
@@ -67,8 +68,8 @@ const buttonStyle = $computed(() => {
     return 'text-base bg-code border-base'
 
   // If following, use a label style with a strong border for Mutuals
-  if (relationship?.following)
-    return `text-base ${relationship.followedBy ? 'border-strong' : 'border-base'}`
+  if (relationship ? relationship.following : context === 'following')
+    return `text-base ${relationship?.followedBy ? 'border-strong' : 'border-base'}`
 
   // If not following, use a button style
   return 'text-inverted bg-primary border-primary'
@@ -94,14 +95,14 @@ const buttonStyle = $computed(() => {
       <span group-hover="hidden">{{ $t('account.muting') }}</span>
       <span hidden group-hover="inline">{{ $t('account.unmute') }}</span>
     </template>
-    <template v-else-if="relationship?.following">
-      <span group-hover="hidden">{{ relationship.followedBy ? $t('account.mutuals') : $t('account.following') }}</span>
+    <template v-else-if="relationship ? relationship.following : context === 'following'">
+      <span group-hover="hidden">{{ relationship?.followedBy ? $t('account.mutuals') : $t('account.following') }}</span>
       <span hidden group-hover="inline">{{ $t('account.unfollow') }}</span>
     </template>
     <template v-else-if="relationship?.requested">
       <span>{{ $t('account.follow_requested') }}</span>
     </template>
-    <template v-else-if="relationship?.followedBy">
+    <template v-else-if="relationship ? relationship.followedBy : context === 'followedBy'">
       <span group-hover="hidden">{{ $t('account.follows_you') }}</span>
       <span hidden group-hover="inline">{{ $t('account.follow_back') }}</span>
     </template>
diff --git a/components/account/AccountPaginator.vue b/components/account/AccountPaginator.vue
index 3832b887..ecb92d7d 100644
--- a/components/account/AccountPaginator.vue
+++ b/components/account/AccountPaginator.vue
@@ -3,6 +3,7 @@ import type { Paginator, mastodon } from 'masto'
 
 const { paginator } = defineProps<{
   paginator: Paginator<mastodon.v1.Account[], mastodon.DefaultPaginationParams>
+  relationshipContext?: 'followedBy' | 'following'
 }>()
 </script>
 
@@ -11,6 +12,7 @@ const { paginator } = defineProps<{
     <template #default="{ item }">
       <AccountCard
         :account="item"
+        :relationship-context="relationshipContext"
         hover-card
         border="b base" py2 px4
       />
diff --git a/composables/users.ts b/composables/users.ts
index a772ee8a..13e8cbd3 100644
--- a/composables/users.ts
+++ b/composables/users.ts
@@ -1,7 +1,7 @@
 import { login as loginMasto } from 'masto'
 import type { WsEvents, mastodon } from 'masto'
 import type { Ref } from 'vue'
-import type { RemovableRef } from '@vueuse/core'
+import type { MaybeComputedRef, RemovableRef } from '@vueuse/core'
 import type { ElkMasto, UserLogin } from '~/types'
 import {
   DEFAULT_POST_CHARS_LIMIT,
@@ -96,6 +96,8 @@ export const currentUserHandle = computed(() => currentUser.value?.account.id
 )
 
 export const useUsers = () => users
+export const useSelfAccount = (user: MaybeComputedRef<mastodon.v1.Account | undefined>) =>
+  computed(() => currentUser.value && resolveUnref(user)?.id === currentUser.value.account.id)
 
 export const characterLimit = computed(() => currentInstance.value?.configuration.statuses.maxCharacters ?? DEFAULT_POST_CHARS_LIMIT)
 
diff --git a/pages/[[server]]/@[account]/index/followers.vue b/pages/[[server]]/@[account]/index/followers.vue
index 4ebf6eaa..8ef6a10a 100644
--- a/pages/[[server]]/@[account]/index/followers.vue
+++ b/pages/[[server]]/@[account]/index/followers.vue
@@ -8,6 +8,8 @@ definePageMeta({ name: 'account-followers' })
 const account = await fetchAccountByHandle(handle)
 const paginator = account ? useMasto().v1.accounts.listFollowers(account.id, {}) : null
 
+const isSelf = useSelfAccount(account)
+
 if (account) {
   useHeadFixed({
     title: () => `${t('account.followers')} | ${getDisplayName(account)} (@${account})`,
@@ -17,6 +19,6 @@ if (account) {
 
 <template>
   <template v-if="paginator">
-    <AccountPaginator :paginator="paginator" />
+    <AccountPaginator :paginator="paginator" :relationship-context="isSelf ? 'followedBy' : undefined" />
   </template>
 </template>
diff --git a/pages/[[server]]/@[account]/index/following.vue b/pages/[[server]]/@[account]/index/following.vue
index 12c77920..d8f6451b 100644
--- a/pages/[[server]]/@[account]/index/following.vue
+++ b/pages/[[server]]/@[account]/index/following.vue
@@ -8,6 +8,8 @@ definePageMeta({ name: 'account-following' })
 const account = await fetchAccountByHandle(handle)
 const paginator = account ? useMasto().v1.accounts.listFollowing(account.id, {}) : null
 
+const isSelf = useSelfAccount(account)
+
 if (account) {
   useHeadFixed({
     title: () => `${t('account.following')} | ${getDisplayName(account)} (@${account.acct})`,
@@ -17,6 +19,6 @@ if (account) {
 
 <template>
   <template v-if="paginator">
-    <AccountPaginator :paginator="paginator" />
+    <AccountPaginator :paginator="paginator" :relationship-context="isSelf ? 'following' : undefined" />
   </template>
 </template>