diff --git a/src/components/extra_notifications/extra_notifications.js b/src/components/extra_notifications/extra_notifications.js index 851656ae5..d20cbb67e 100644 --- a/src/components/extra_notifications/extra_notifications.js +++ b/src/components/extra_notifications/extra_notifications.js @@ -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() { diff --git a/src/components/extra_notifications/extra_notifications.vue b/src/components/extra_notifications/extra_notifications.vue index 388435950..329c5c1c3 100644 --- a/src/components/extra_notifications/extra_notifications.vue +++ b/src/components/extra_notifications/extra_notifications.vue @@ -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) }} { + 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() }, diff --git a/src/components/follow_requests/follow_requests.js b/src/components/follow_requests/follow_requests.js index 513298afc..5936e2303 100644 --- a/src/components/follow_requests/follow_requests.js +++ b/src/components/follow_requests/follow_requests.js @@ -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() }, }, } diff --git a/src/components/mobile_nav/mobile_nav.js b/src/components/mobile_nav/mobile_nav.js index 97645ca73..e7fe404e0 100644 --- a/src/components/mobile_nav/mobile_nav.js +++ b/src/components/mobile_nav/mobile_nav.js @@ -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, ) ) }, diff --git a/src/components/nav_panel/nav_panel.js b/src/components/nav_panel/nav_panel.js index c3e760efb..f5de8bb2c 100644 --- a/src/components/nav_panel/nav_panel.js +++ b/src/components/nav_panel/nav_panel.js @@ -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( diff --git a/src/components/navigation/navigation.js b/src/components/navigation/navigation.js index 39fa2c993..7a2e29646 100644 --- a/src/components/navigation/navigation.js +++ b/src/components/navigation/navigation.js @@ -85,7 +85,7 @@ export const ROOT_ITEMS = { label: 'nav.friend_requests', badgeStyle: 'notification', criteria: ['lockedUser'], - badgeGetter: 'followRequestCount', + badgeGetter: 'followRequestsCount', }, about: { route: 'about', diff --git a/src/components/navigation/navigation_pins.js b/src/components/navigation/navigation_pins.js index 2efa94ee4..f16336ef3 100644 --- a/src/components/navigation/navigation_pins.js +++ b/src/components/navigation/navigation_pins.js @@ -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( diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js index 2272c78af..734671521 100644 --- a/src/components/notifications/notifications.js +++ b/src/components/notifications/notifications.js @@ -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() { diff --git a/src/components/side_drawer/side_drawer.js b/src/components/side_drawer/side_drawer.js index 2d2886d58..40d922228 100644 --- a/src/components/side_drawer/side_drawer.js +++ b/src/components/side_drawer/side_drawer.js @@ -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', diff --git a/src/components/side_drawer/side_drawer.vue b/src/components/side_drawer/side_drawer.vue index c810d93a0..a42287b3c 100644 --- a/src/components/side_drawer/side_drawer.vue +++ b/src/components/side_drawer/side_drawer.vue @@ -141,10 +141,10 @@ icon="user-plus" /> {{ $t("nav.friend_requests") }} - {{ followRequestCount }} + {{ followRequestsCount }} diff --git a/src/modules/api.js b/src/modules/api.js index 290fbfc27..1395752e0 100644 --- a/src/modules/api.js +++ b/src/modules/api.js @@ -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) diff --git a/src/services/follow_request_fetcher/follow_request_fetcher.service.js b/src/services/follow_request_fetcher/follow_request_fetcher.service.js deleted file mode 100644 index 492c4e648..000000000 --- a/src/services/follow_request_fetcher/follow_request_fetcher.service.js +++ /dev/null @@ -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 diff --git a/src/services/notification_utils/notification_utils.js b/src/services/notification_utils/notification_utils.js index 1fdb7bec1..803a56322 100644 --- a/src/services/notification_utils/notification_utils.js +++ b/src/services/notification_utils/notification_utils.js @@ -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) } diff --git a/src/stores/fetchers/follow_requests.js b/src/stores/fetchers/follow_requests.js new file mode 100644 index 000000000..8794ab07e --- /dev/null +++ b/src/stores/fetchers/follow_requests.js @@ -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 diff --git a/src/stores/follow_requests.js b/src/stores/follow_requests.js new file mode 100644 index 000000000..064d57253 --- /dev/null +++ b/src/stores/follow_requests.js @@ -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) + } + }, +}) diff --git a/src/stores/users.js b/src/stores/users.js index 90c87c0f3..71a9ddc94 100644 --- a/src/stores/users.js +++ b/src/stores/users.js @@ -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')