migrate follow requests to separate pinia store

This commit is contained in:
Henry Jameson 2026-08-31 19:05:26 +03:00
commit 8a743c648c
17 changed files with 121 additions and 99 deletions

View file

@ -1,8 +1,8 @@
import { mapState } from 'pinia'
import { mapGetters } from 'vuex'
import { useAnnouncementsStore } from 'src/stores/announcements.js'
import { useChatsStore } from 'src/stores/chats.js'
import { useFollowRequestsStore } from 'src/stores/follow_requests.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
@ -37,7 +37,7 @@ const ExtraNotifications = {
return (
this.mergedConfig.showExtraNotifications &&
this.mergedConfig.showFollowRequestsInExtraNotifications &&
this.followRequestCount
this.followRequestsCount
)
},
hasAnythingToShow() {
@ -55,12 +55,12 @@ const ExtraNotifications = {
currentUser() {
return useUsersStore().currentUser
},
...mapGetters(['followRequestCount']),
...mapState(useAnnouncementsStore, {
unreadAnnouncementCount: 'unreadAnnouncementCount',
}),
...mapState(useMergedConfigStore, ['mergedConfig']),
...mapState(useChatsStore, ['unreadChatsCount']),
...mapState(useFollowRequestsStore, ['followRequestsCount']),
},
methods: {
openNotificationSettings() {

View file

@ -48,7 +48,7 @@
class="fa-scale-110 icon"
icon="user-plus"
/>
{{ $t('notifications.unread_follow_requests', { num: followRequestCount }, followRequestCount) }}
{{ $t('notifications.unread_follow_requests', { num: followRequestsCount }, followRequestsCount) }}
</router-link>
</div>
<i18n-t

View file

@ -2,6 +2,7 @@ import { defineAsyncComponent } from 'vue'
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'
@ -54,12 +55,11 @@ const FollowRequestCard = {
approveUser({
id: this.user.id,
credentials: useOAuthStore().token,
}).then(() => {
const notifId = this.findFollowRequestNotificationId()
useFollowRequestsStore().remove(this.user.id)
notifId && useNotificationsStore().markSingleNotificationAsSeen(notifId)
})
// TODO fix
this.$store.dispatch('removeFollowRequest', this.user)
const notifId = this.findFollowRequestNotificationId()
useNotificationsStore().markSingleNotificationAsSeen(notifId)
this.hideApproveConfirmDialog()
},
denyUser() {
@ -70,15 +70,13 @@ const FollowRequestCard = {
}
},
doDeny() {
const notifId = this.findFollowRequestNotificationId()
denyUser({
id: this.user.id,
credentials: useOAuthStore().token,
}).then(() => {
useNotificationsStore().dismissNotificationLocal(notifId)
// TODO fix
this.$store.dispatch('removeFollowRequest', this.user)
const notifId = this.findFollowRequestNotificationId()
useFollowRequestsStore().remove(this.user.id)
notifId && useNotificationsStore().markSingleNotificationAsSeen(notifId)
})
this.hideDenyConfirmDialog()
},

View file

@ -1,3 +1,5 @@
import { useFollowRequestsStore } from 'src/stores/follow_requests.js'
import FollowRequestCard from 'src/components/follow_request_card/follow_request_card.vue'
const FollowRequests = {
@ -6,7 +8,7 @@ const FollowRequests = {
},
computed: {
requests() {
return this.$store.state.api.followRequests
return useFollowRequestsStore().requests.values()
},
},
}

View file

@ -10,6 +10,7 @@ import {
import { useAnnouncementsStore } from 'src/stores/announcements.js'
import { useChatsStore } from 'src/stores/chats.js'
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'
@ -67,10 +68,10 @@ const MobileNav = {
return (
this.unseenNotifications.length +
countExtraNotifications(
this.$store,
useMergedConfigStore().mergedConfig,
useChatsStore().unreadChatsCount,
useAnnouncementsStore().unreadAnnouncementCount,
useFollowRequestsStore().followRequestsCount,
)
)
},

View file

@ -1,5 +1,4 @@
import { mapState } from 'pinia'
import { mapState as mapVuexState } from 'vuex'
import BookmarkFoldersMenuContent from 'src/components/bookmark_folders_menu/bookmark_folders_menu_content.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue'
@ -11,6 +10,7 @@ import NavigationPins from 'src/components/navigation/navigation_pins.vue'
import { useAnnouncementsStore } from 'src/stores/announcements'
import { useChatsStore } from 'src/stores/chats.js'
import { useFollowRequestsStore } from 'src/stores/follow_requests.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
@ -130,9 +130,7 @@ const NavPanel = {
new Set(store.prefsStorage.collections.pinnedNavItems),
}),
...mapState(useUsersStore, ['currentUser']),
...mapVuexState({
followRequestCount: (state) => state.api.followRequests.length,
}),
...mapState(useFollowRequestsStore, ['followRequestsCount']),
...mapState(useChatsStore, ['unreadChatsCount']),
timelinesItems() {
return filterNavigation(

View file

@ -85,7 +85,7 @@ export const ROOT_ITEMS = {
label: 'nav.friend_requests',
badgeStyle: 'notification',
criteria: ['lockedUser'],
badgeGetter: 'followRequestCount',
badgeGetter: 'followRequestsCount',
},
about: {
route: 'about',

View file

@ -1,5 +1,4 @@
import { mapState } from 'pinia'
import { mapState as mapVuexState } from 'vuex'
import {
filterNavigation,
@ -14,6 +13,7 @@ import {
import { useAnnouncementsStore } from 'src/stores/announcements'
import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders'
import { useFollowRequestsStore } from 'src/stores/follow_requests.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useListsStore } from 'src/stores/lists'
@ -78,9 +78,7 @@ const NavPanel = {
'localBubble',
]),
...mapState(useUsersStore, ['currentUser']),
...mapVuexState({
followRequestCount: (state) => state.api.followRequests.length,
}),
...mapState(useFollowRequestsStore, ['followRequestsCount']),
pinnedList() {
if (!this.currentUser) {
return filterNavigation(

View file

@ -14,6 +14,7 @@ import NotificationFilters from './notification_filters.vue'
import { useAnnouncementsStore } from 'src/stores/announcements.js'
import { useChatsStore } from 'src/stores/chats.js'
import { useFollowRequestsStore } from 'src/stores/follow_requests.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useNotificationsStore } from 'src/stores/notifications.js'
@ -107,10 +108,10 @@ const Notifications = {
},
extraNotificationsCount() {
return countExtraNotifications(
this.$store,
useMergedConfigStore().mergedConfig,
useChatsStore().unreadChatsCount,
useAnnouncementsStore().unreadAnnouncementCount,
useFollowRequestsStore().followRequestsCount,
)
},
unseenCountTitle() {

View file

@ -8,6 +8,7 @@ import { unseenNotifications } from '../../services/notification_utils/notificat
import { useAnnouncementsStore } from 'src/stores/announcements'
import { useChatsStore } from 'src/stores/chats.js'
import { useFollowRequestsStore } from 'src/stores/follow_requests.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface'
@ -85,9 +86,6 @@ const SideDrawer = {
unseenNotificationsCount() {
return this.unseenNotifications.length
},
followRequestCount() {
return this.$store.state.api.followRequests.length
},
timelinesRoute() {
let name
if (useInterfaceStore().lastTimeline) {
@ -100,6 +98,7 @@ const SideDrawer = {
return { name }
}
},
...mapState(useFollowRequestsStore, ['followRequestsCount']),
...mapState(useAnnouncementsStore, [
'supportsAnnouncements',
'unreadAnnouncementCount',

View file

@ -141,10 +141,10 @@
icon="user-plus"
/> {{ $t("nav.friend_requests") }}
<span
v-if="followRequestCount > 0"
v-if="followRequestsCount > 0"
class="badge -notification"
>
{{ followRequestCount }}
{{ followRequestsCount }}
</span>
</router-link>
</li>

View file

@ -1,19 +1,12 @@
import { Socket } from 'phoenix'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { useShoutStore } from 'src/stores/shout.js'
import followRequestFetcher from 'src/services/follow_request_fetcher/follow_request_fetcher.service'
const api = {
state: {
fetchers: {},
socket: null,
followRequests: [],
},
getters: {
followRequestCount: (state) => state.followRequests.length,
},
mutations: {
addFetcher(state, { fetcherName, fetcher }) {
@ -29,27 +22,8 @@ const api = {
setSocket(state, socket) {
state.socket = socket
},
setFollowRequests(state, value) {
state.followRequests = value
},
},
actions: {
// Follow requests
startFetchingFollowRequests(store) {
if (store.state.fetchers.followRequests) return
const fetcher = followRequestFetcher.startFetching({
store,
credentials: useOAuthStore().token,
})
store.commit('addFetcher', { fetcherName: 'followRequests', fetcher })
},
stopFetchingFollowRequests(store) {
const fetcher = store.state.fetchers.followRequests
if (!fetcher) return
store.commit('removeFetcher', { fetcherName: 'followRequests', fetcher })
},
// Pleroma websocket
setWsToken(store, token) {
store.commit('setWsToken', token)

View file

@ -1,33 +0,0 @@
import { useUsersStore } from 'src/stores/users.js'
import { fetchFollowRequests } from 'src/api/user.js'
import { promiseInterval } from 'src/services/promise_interval/promise_interval.js'
const fetchAndUpdate = ({ store, credentials }) => {
return fetchFollowRequests({ credentials })
.then(
(result) => {
const { data: requests } = result
store.commit('setFollowRequests', requests)
useUsersStore().addNewUsers(result)
},
(rej) => {
console.error(rej)
},
)
.catch((e) => {
console.error(e)
})
}
const startFetching = ({ credentials, store }) => {
const boundFetchAndUpdate = () => fetchAndUpdate({ credentials, store })
boundFetchAndUpdate()
return promiseInterval(boundFetchAndUpdate, 10000)
}
const followRequestFetcher = {
startFetching,
}
export default followRequestFetcher

View file

@ -98,13 +98,11 @@ export const unseenNotifications = (
}
export const countExtraNotifications = (
store,
mergedConfig,
unreadChatsCount,
unreadAnnouncementCount,
unreadAnnouncementsCount,
followRequestsCount,
) => {
const rootGetters = store.rootGetters || store.getters
if (!mergedConfig.showExtraNotifications) {
return 0
}
@ -112,10 +110,10 @@ export const countExtraNotifications = (
return [
mergedConfig.showChatsInExtraNotifications ? unreadChatsCount : 0,
mergedConfig.showAnnouncementsInExtraNotifications
? unreadAnnouncementCount
? unreadAnnouncementsCount
: 0,
mergedConfig.showFollowRequestsInExtraNotifications
? rootGetters.followRequestCount
? followRequestsCount
: 0,
].reduce((a, c) => a + c, 0)
}

View file

@ -0,0 +1,44 @@
import { ref } from 'vue'
import { useFollowRequestsStore } from 'src/stores/follow_requests.js'
import { useUsersStore } from 'src/stores/users.js'
import { fetchFollowRequests } from 'src/api/user.js'
import { promiseInterval } from 'src/services/promise_interval/promise_interval.js'
const followRequestFetcher = ({ credentials }) => {
const interval = ref(null)
const fetchAndUpdate = () => {
return fetchFollowRequests({ credentials })
.then((result) => {
const { data: requests } = result
useFollowRequestsStore().setFollowRequests(requests)
useUsersStore().addNewUsers(result)
})
.catch((e) => {
console.error(e)
})
}
const startFetching = () => {
if (interval.value) throw new Error('Interval already exists!')
fetchAndUpdate()
interval.value = promiseInterval(fetchAndUpdate, 10000)
}
const stopFetching = () => {
interval.value.stop()
interval.value = null
}
return {
fetchAndUpdate,
startFetching,
stopFetching,
}
}
export default followRequestFetcher

View file

@ -0,0 +1,37 @@
import { defineStore } from 'pinia'
import followRequestFetcher from 'src/stores/fetchers/follow_requests.js'
import { useOAuthStore } from 'src/stores/oauth.js'
export const useFollowRequestsStore = defineStore('followRequests', {
state: () => ({
fetcher: null,
requests: new Map(),
}),
getters: {
followRequestsCount(state) {
return state.requests.size
},
},
actions: {
startFetching() {
if (this.fetcher) throw 'Fetcher already exists!'
this.fetcher = followRequestFetcher({
credentials: useOAuthStore().token,
})
this.fetcher.startFetching()
},
stopFetching() {
if (!this.fetcher) throw "Fetcher doesn't exists!"
this.fetcher.stopFetching(), (this.fetcher = null)
},
setFollowRequests(requests) {
this.requests = new Map(requests.map((user) => [user.id, user]))
},
remove(id) {
this.requests.delete(id)
}
},
})

View file

@ -6,6 +6,7 @@ import { useAnnouncementsStore } from 'src/stores/announcements.js'
import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders.js'
import { useChatsStore } from 'src/stores/chats.js'
import { useEmojiStore } from 'src/stores/emoji.js'
import { useFollowRequestsStore } from 'src/stores/follow_requests.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface.js'
@ -678,9 +679,10 @@ export const useUsersStore = defineStore('users', {
useListsStore().startFetching()
useBookmarkFoldersStore().startFetching()
if (user.locked) {
dispatch('startFetchingFollowRequests')
}
// if (user.locked) {
dispatch('startFetchingFollowRequests')
useFollowRequestsStore().startFetching()
// }
if (useMergedConfigStore().mergedConfig.useStreamingApi) {
useStreamingStore().initSocket(true)
@ -724,6 +726,9 @@ export const useUsersStore = defineStore('users', {
useListsStore().stopFetching()
useBookmarkFoldersStore().stopFetching()
useChatsStore().stopFetching()
// if (this.currentUser.locked) {
useFollowRequestsStore().stopFetching()
// }
store?.dispatch('stopFetchingFollowRequests')