From 10e3cb588ae1938d86a4a4b3bfbc78fa61979d02 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Thu, 3 Sep 2026 21:21:08 +0300 Subject: [PATCH] follow requests refactor --- src/App.js | 6 + src/App.vue | 1 + src/api/user.js | 5 +- .../follow_request_card.js | 84 +---- .../follow_request_card.vue | 26 +- .../follow_request_confirm.vue | 38 ++ src/components/notification/notification.js | 65 +--- src/components/notification/notification.vue | 26 +- src/stores/fetchers/follow_requests.js | 2 - src/stores/follow_requests.js | 78 +++- test/unit/specs/stores/drafts.spec.js | 48 ++- .../unit/specs/stores/follow_requests.spec.js | 338 ++++++++++++++++++ 12 files changed, 507 insertions(+), 210 deletions(-) create mode 100644 src/components/follow_request_confirm/follow_request_confirm.vue create mode 100644 test/unit/specs/stores/follow_requests.spec.js diff --git a/src/App.js b/src/App.js index 66ae09a9d..ae38204b6 100644 --- a/src/App.js +++ b/src/App.js @@ -49,6 +49,12 @@ export default { MobilePostStatusButton, MobileNav, DesktopNav, + FollowRequestConfirm: defineAsyncComponent( + () => + import( + 'src/components/follow_request_confirm/follow_request_confirm.vue' + ), + ), SettingsModal: defineAsyncComponent( () => import('src/components/settings_modal/settings_modal.vue'), ), diff --git a/src/App.vue b/src/App.vue index bd19c5c10..cad329a78 100644 --- a/src/App.vue +++ b/src/App.vue @@ -75,6 +75,7 @@ + diff --git a/src/api/user.js b/src/api/user.js index 8849847d6..2f356ebbc 100644 --- a/src/api/user.js +++ b/src/api/user.js @@ -43,9 +43,10 @@ export const MASTODON_FOLLOW_URL = (id) => `/api/v1/accounts/${id}/follow` export const MASTODON_UNFOLLOW_URL = (id) => `/api/v1/accounts/${id}/unfollow` const MASTODON_FOLLOW_REQUESTS_URL = '/api/v1/follow_requests' -const MASTODON_APPROVE_USER_URL = (id) => +export const MASTODON_APPROVE_USER_URL = (id) => `/api/v1/follow_requests/${id}/authorize` -const MASTODON_DENY_USER_URL = (id) => `/api/v1/follow_requests/${id}/reject` +export const MASTODON_DENY_USER_URL = (id) => + `/api/v1/follow_requests/${id}/reject` const MASTODON_USER_RELATIONSHIPS_URL = ({ id, withSuspended }) => `/api/v1/accounts/relationships/${paramsString({ id, withSuspended })}` export const MASTODON_USER_IN_LISTS = (id) => `/api/v1/accounts/${id}/lists` diff --git a/src/components/follow_request_card/follow_request_card.js b/src/components/follow_request_card/follow_request_card.js index a8492b887..d790e68a5 100644 --- a/src/components/follow_request_card/follow_request_card.js +++ b/src/components/follow_request_card/follow_request_card.js @@ -1,96 +1,16 @@ -import { defineAsyncComponent } from 'vue' +import { mapActions } from 'pinia' import BasicUserCard from '../basic_user_card/basic_user_card.vue' import { useFollowRequestsStore } from 'src/stores/follow_requests.js' -import { useMergedConfigStore } from 'src/stores/merged_config.js' -import { useNotificationsStore } from 'src/stores/notifications.js' -import { useOAuthStore } from 'src/stores/oauth.js' - -import { approveUser, denyUser } from 'src/api/user.js' const FollowRequestCard = { props: ['user'], components: { BasicUserCard, - ConfirmModal: defineAsyncComponent( - () => import('src/components/confirm_modal/confirm_modal.vue'), - ), - }, - data() { - return { - showingApproveConfirmDialog: false, - showingDenyConfirmDialog: false, - } }, methods: { - findFollowRequestNotificationId() { - const notif = useNotificationsStore().data.find( - (notif) => - notif.from_profile.id === this.user.id && - notif.type === 'follow_request', - ) - return notif?.id - }, - showApproveConfirmDialog() { - this.showingApproveConfirmDialog = true - }, - hideApproveConfirmDialog() { - this.showingApproveConfirmDialog = false - }, - showDenyConfirmDialog() { - this.showingDenyConfirmDialog = true - }, - hideDenyConfirmDialog() { - this.showingDenyConfirmDialog = false - }, - approveUser() { - if (this.shouldConfirmApprove) { - this.showApproveConfirmDialog() - } else { - this.doApprove() - } - }, - doApprove() { - approveUser({ - id: this.user.id, - credentials: useOAuthStore().token, - }).then(() => { - const notifId = this.findFollowRequestNotificationId() - useFollowRequestsStore().remove(this.user.id) - notifId && useNotificationsStore().markSingleNotificationAsSeen(notifId) - }) - this.hideApproveConfirmDialog() - }, - denyUser() { - if (this.shouldConfirmDeny) { - this.showDenyConfirmDialog() - } else { - this.doDeny() - } - }, - doDeny() { - denyUser({ - id: this.user.id, - credentials: useOAuthStore().token, - }).then(() => { - const notifId = this.findFollowRequestNotificationId() - useFollowRequestsStore().remove(this.user.id) - notifId && useNotificationsStore().markSingleNotificationAsSeen(notifId) - }) - this.hideDenyConfirmDialog() - }, - }, - computed: { - mergedConfig() { - return useMergedConfigStore().mergedConfig - }, - shouldConfirmApprove() { - return this.mergedConfig.modalOnApproveFollow - }, - shouldConfirmDeny() { - return this.mergedConfig.modalOnDenyFollow - }, + ...mapActions(useFollowRequestsStore, ['approve', 'deny']), }, } diff --git a/src/components/follow_request_card/follow_request_card.vue b/src/components/follow_request_card/follow_request_card.vue index 64b185094..4d771b454 100644 --- a/src/components/follow_request_card/follow_request_card.vue +++ b/src/components/follow_request_card/follow_request_card.vue @@ -3,39 +3,17 @@ - - - {{ $t('user_card.approve_confirm', { user: user.screen_name_ui }) }} - - - {{ $t('user_card.deny_confirm', { user: user.screen_name_ui }) }} - - diff --git a/src/components/follow_request_confirm/follow_request_confirm.vue b/src/components/follow_request_confirm/follow_request_confirm.vue new file mode 100644 index 000000000..2a873f3f5 --- /dev/null +++ b/src/components/follow_request_confirm/follow_request_confirm.vue @@ -0,0 +1,38 @@ + + + diff --git a/src/components/notification/notification.js b/src/components/notification/notification.js index 65acfed5c..cff7f655f 100644 --- a/src/components/notification/notification.js +++ b/src/components/notification/notification.js @@ -1,5 +1,4 @@ -import { mapState } from 'pinia' -import { defineAsyncComponent } from 'vue' +import { mapActions, mapState } from 'pinia' import Report from 'src/components/report/report.vue' import StatusContent from 'src/components/status_content/status_content.vue' @@ -16,13 +15,10 @@ import { import { useFollowRequestsStore } from 'src/stores/follow_requests.js' import { useInstanceStore } from 'src/stores/instance.js' import { useMergedConfigStore } from 'src/stores/merged_config.js' -import { useNotificationsStore } from 'src/stores/notifications.js' -import { useOAuthStore } from 'src/stores/oauth.js' import { useStatusesStore } from 'src/stores/statuses.js' import { useUserHighlightStore } from 'src/stores/user_highlight.js' import { useUsersStore } from 'src/stores/users.js' -import { approveUser, denyUser } from 'src/api/user.js' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' import { library } from '@fortawesome/fontawesome-svg-core' @@ -58,8 +54,6 @@ const Notification = { selecting: false, statusExpanded: false, unmuted: false, - showingApproveConfirmDialog: false, - showingDenyConfirmDialog: false, } }, props: ['notification'], @@ -73,9 +67,6 @@ const Notification = { UserPopover, UserLink, - ConfirmModal: defineAsyncComponent( - () => import('src/components/confirm_modal/confirm_modal.vue'), - ), }, mounted() { document.addEventListener('selectionchange', this.onContentSelect) @@ -125,53 +116,7 @@ const Notification = { toggleMute() { this.unmuted = !this.unmuted }, - showApproveConfirmDialog() { - this.showingApproveConfirmDialog = true - }, - hideApproveConfirmDialog() { - this.showingApproveConfirmDialog = false - }, - showDenyConfirmDialog() { - this.showingDenyConfirmDialog = true - }, - hideDenyConfirmDialog() { - this.showingDenyConfirmDialog = false - }, - approveUser() { - if (this.shouldConfirmApprove) { - this.showApproveConfirmDialog() - } else { - this.doApprove() - } - }, - doApprove() { - approveUser({ - id: this.user.id, - credentials: useOAuthStore().token, - }) - useFollowRequestsStore().remove(this.user.id) - useNotificationsStore().markSingleNotificationAsSeen(this.notification.id) - this.hideApproveConfirmDialog() - }, - denyUser() { - if (this.shouldConfirmDeny) { - this.showDenyConfirmDialog() - } else { - this.doDeny() - } - }, - doDeny() { - denyUser({ - id: this.user.id, - credentials: useOAuthStore().token, - }).then(() => { - useNotificationsStore().markSingleNotificationAsSeen( - this.notification.id, - ) - useFollowRequestsStore().remove(this.user.id) - }) - this.hideDenyConfirmDialog() - }, + ...mapActions(useFollowRequestsStore, ['approve', 'deny']), }, computed: { status() { @@ -222,12 +167,6 @@ const Notification = { scaleMfm() { return this.mergedConfig.scaleMfm }, - shouldConfirmApprove() { - return this.mergedConfig.modalOnApproveFollow - }, - shouldConfirmDeny() { - return this.mergedConfig.modalOnDenyFollow - }, ...mapState(useUsersStore, ['currentUser']), }, } diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue index 601e574db..156c9ac11 100644 --- a/src/components/notification/notification.vue +++ b/src/components/notification/notification.vue @@ -226,7 +226,7 @@