summaryrefslogtreecommitdiff
path: root/packages/frontend/src
diff options
context:
space:
mode:
authorかっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>2024-11-15 17:30:54 +0900
committerGitHub <noreply@github.com>2024-11-15 17:30:54 +0900
commitc0d168260482caa974e3fc9e084b121fc32e8ec4 (patch)
treeaddcc1432d1ba3097667ca3ba86d33cd87793615 /packages/frontend/src
parentupdate deps (#14950) (diff)
downloadmisskey-c0d168260482caa974e3fc9e084b121fc32e8ec4.tar.gz
misskey-c0d168260482caa974e3fc9e084b121fc32e8ec4.tar.bz2
misskey-c0d168260482caa974e3fc9e084b121fc32e8ec4.zip
feat: 送信したフォローリクエストを確認できるように (#14856)
* FEAT: Allow users to view pending follow requests they sent This commit implements the `following/requests/sent` interface firstly implemented on Firefish, and provides a UI interface to view the pending follow requests users sent. * ux: should not show follow requests tab when have no pending sent follow req * fix default followreq tab * fix default followreq tab * restore missing hasPendingReceivedFollowRequest in navbar * refactor * use tabler icons * tweak design * Revert "ux: should not show follow requests tab when have no pending sent follow req" This reverts commit e580b92c37f27c2849c6d27e22ca4c47086081bb. * Update Changelog * Update Changelog * change tab titles --------- Co-authored-by: Lhc_fl <lhcfl@outlook.com> Co-authored-by: Hazelnoot <acomputerdog@gmail.com>
Diffstat (limited to 'packages/frontend/src')
-rw-r--r--packages/frontend/src/components/MkFollowButton.vue10
-rw-r--r--packages/frontend/src/navbar.ts1
-rw-r--r--packages/frontend/src/pages/follow-requests.vue105
3 files changed, 78 insertions, 38 deletions
diff --git a/packages/frontend/src/components/MkFollowButton.vue b/packages/frontend/src/components/MkFollowButton.vue
index cc07175907..c1dc67f776 100644
--- a/packages/frontend/src/components/MkFollowButton.vue
+++ b/packages/frontend/src/components/MkFollowButton.vue
@@ -91,7 +91,10 @@ async function onClick() {
text: i18n.tsx.unfollowConfirm({ name: props.user.name || props.user.username }),
});
- if (canceled) return;
+ if (canceled) {
+ wait.value = false;
+ return;
+ }
await misskeyApi('following/delete', {
userId: props.user.id,
@@ -125,7 +128,10 @@ async function onClick() {
});
hasPendingFollowRequestFromYou.value = true;
- if ($i == null) return;
+ if ($i == null) {
+ wait.value = false;
+ return;
+ }
claimAchievement('following1');
diff --git a/packages/frontend/src/navbar.ts b/packages/frontend/src/navbar.ts
index ac730f8021..096d404a57 100644
--- a/packages/frontend/src/navbar.ts
+++ b/packages/frontend/src/navbar.ts
@@ -40,7 +40,6 @@ export const navbarItemDef = reactive({
followRequests: {
title: i18n.ts.followRequests,
icon: 'ti ti-user-plus',
- show: computed(() => $i != null && $i.isLocked),
indicated: computed(() => $i != null && $i.hasPendingReceivedFollowRequest),
to: '/my/follow-requests',
},
diff --git a/packages/frontend/src/pages/follow-requests.vue b/packages/frontend/src/pages/follow-requests.vue
index a840d0d0b3..8688863c2c 100644
--- a/packages/frontend/src/pages/follow-requests.vue
+++ b/packages/frontend/src/pages/follow-requests.vue
@@ -5,69 +5,104 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<MkStickyContainer>
- <template #header><MkPageHeader/></template>
+ <template #header><MkPageHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/></template>
<MkSpacer :contentMax="800">
- <MkPagination ref="paginationComponent" :pagination="pagination">
- <template #empty>
- <div class="_fullinfo">
- <img :src="infoImageUrl" class="_ghost"/>
- <div>{{ i18n.ts.noFollowRequests }}</div>
- </div>
- </template>
- <template #default="{items}">
- <div class="mk-follow-requests">
- <div v-for="req in items" :key="req.id" class="user _panel">
- <MkAvatar class="avatar" :user="req.follower" indicator link preview/>
- <div class="body">
- <div class="name">
- <MkA v-user-preview="req.follower.id" class="name" :to="userPage(req.follower)"><MkUserName :user="req.follower"/></MkA>
- <p class="acct">@{{ acct(req.follower) }}</p>
- </div>
- <div class="commands">
- <MkButton class="command" rounded primary @click="accept(req.follower)"><i class="ti ti-check"/> {{ i18n.ts.accept }}</MkButton>
- <MkButton class="command" rounded danger @click="reject(req.follower)"><i class="ti ti-x"/> {{ i18n.ts.reject }}</MkButton>
+ <MkHorizontalSwipe v-model:tab="tab" :tabs="headerTabs">
+ <div :key="tab" class="_gaps">
+ <MkPagination ref="paginationComponent" :pagination="pagination">
+ <template #empty>
+ <div class="_fullinfo">
+ <img :src="infoImageUrl" class="_ghost"/>
+ <div>{{ i18n.ts.noFollowRequests }}</div>
+ </div>
+ </template>
+ <template #default="{items}">
+ <div class="mk-follow-requests">
+ <div v-for="req in items" :key="req.id" class="user _panel">
+ <MkAvatar class="avatar" :user="displayUser(req)" indicator link preview/>
+ <div class="body">
+ <div class="name">
+ <MkA v-user-preview="displayUser(req).id" class="name" :to="userPage(displayUser(req))"><MkUserName :user="displayUser(req)"/></MkA>
+ <p class="acct">@{{ acct(displayUser(req)) }}</p>
+ </div>
+ <div v-if="tab === 'list'" class="commands">
+ <MkButton class="command" rounded primary @click="accept(displayUser(req))"><i class="ti ti-check"/> {{ i18n.ts.accept }}</MkButton>
+ <MkButton class="command" rounded danger @click="reject(displayUser(req))"><i class="ti ti-x"/> {{ i18n.ts.reject }}</MkButton>
+ </div>
+ <div v-else class="commands">
+ <MkButton class="command" rounded danger @click="cancel(displayUser(req))"><i class="ti ti-x"/> {{ i18n.ts.cancel }}</MkButton>
+ </div>
+ </div>
</div>
</div>
- </div>
- </div>
- </template>
- </MkPagination>
+ </template>
+ </MkPagination>
+ </div>
+ </MkHorizontalSwipe>
</MkSpacer>
</MkStickyContainer>
</template>
<script lang="ts" setup>
-import { shallowRef, computed } from 'vue';
-import MkPagination from '@/components/MkPagination.vue';
+import * as Misskey from 'misskey-js';
+import { shallowRef, computed, ref } from 'vue';
+import MkPagination, { type Paging } from '@/components/MkPagination.vue';
import MkButton from '@/components/MkButton.vue';
import { userPage, acct } from '@/filters/user.js';
-import { misskeyApi } from '@/scripts/misskey-api.js';
+import * as os from '@/os.js';
import { i18n } from '@/i18n.js';
import { definePageMetadata } from '@/scripts/page-metadata.js';
import { infoImageUrl } from '@/instance.js';
+import { $i } from '@/account.js';
+import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue';
const paginationComponent = shallowRef<InstanceType<typeof MkPagination>>();
-const pagination = {
- endpoint: 'following/requests/list' as const,
+const pagination = computed<Paging>(() => tab.value === 'list' ? {
+ endpoint: 'following/requests/list',
+ limit: 10,
+} : {
+ endpoint: 'following/requests/sent',
limit: 10,
-};
+});
+
+function accept(user: Misskey.entities.UserLite) {
+ os.apiWithDialog('following/requests/accept', { userId: user.id }).then(() => {
+ paginationComponent.value?.reload();
+ });
+}
-function accept(user) {
- misskeyApi('following/requests/accept', { userId: user.id }).then(() => {
+function reject(user: Misskey.entities.UserLite) {
+ os.apiWithDialog('following/requests/reject', { userId: user.id }).then(() => {
paginationComponent.value?.reload();
});
}
-function reject(user) {
- misskeyApi('following/requests/reject', { userId: user.id }).then(() => {
+function cancel(user: Misskey.entities.UserLite) {
+ os.apiWithDialog('following/requests/cancel', { userId: user.id }).then(() => {
paginationComponent.value?.reload();
});
}
+function displayUser(req) {
+ return tab.value === 'list' ? req.follower : req.followee;
+}
+
const headerActions = computed(() => []);
-const headerTabs = computed(() => []);
+const headerTabs = computed(() => [
+ {
+ key: 'list',
+ title: i18n.ts._followRequest.recieved,
+ icon: 'ti ti-mail',
+ }, {
+ key: 'sent',
+ title: i18n.ts._followRequest.sent,
+ icon: 'ti ti-send',
+ },
+]);
+
+const tab = ref($i?.isLocked ? 'list' : 'sent');
definePageMetadata(() => ({
title: i18n.ts.followRequests,