From 15cc5f44e94b094ba61e86875f8d908478a2325d Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 10 Aug 2026 15:48:27 +0300 Subject: [PATCH] wip --- src/api/helpers.js | 2 +- src/components/chat_view/chat_view.js | 5 +-- src/components/lists_edit/lists_edit.js | 2 +- .../remote_user_resolver.js | 20 +++++------ src/components/staff_panel/staff_panel.js | 11 +++--- src/components/status/status.js | 8 ++--- src/components/status_body/status_body.js | 5 +-- .../user_profile/user_profile_admin_view.js | 2 +- src/components/who_to_follow/who_to_follow.js | 6 ++-- .../who_to_follow_panel.js | 9 +++-- src/main.js | 2 +- src/modules/statuses.js | 16 +++++---- .../follow_request_fetcher.service.js | 7 ++-- src/stores/chats.js | 21 ++++++------ src/stores/users.js | 34 ++++++++++++++----- 15 files changed, 85 insertions(+), 65 deletions(-) diff --git a/src/api/helpers.js b/src/api/helpers.js index 90956a4dc..f734debe9 100644 --- a/src/api/helpers.js +++ b/src/api/helpers.js @@ -123,7 +123,7 @@ export const promisedRequest = async ({ const { ok, status } = response if (ok) { - return { response, status, data } + return { response, status, data, timestamp: Date.now() } } else { throw new StatusCodeError(response.status, data, { url, options }, response) } diff --git a/src/components/chat_view/chat_view.js b/src/components/chat_view/chat_view.js index 9ae5c1d09..1998c9453 100644 --- a/src/components/chat_view/chat_view.js +++ b/src/components/chat_view/chat_view.js @@ -370,11 +370,12 @@ const Chat = { async startFetching() { if (!this.isConversation) { try { - const { data } = await getOrCreateChat({ + const result = await getOrCreateChat({ accountId: this.chatUserId, credentials: useOAuthStore().token, }) - this.$store.commit('addNewUsers', [data.account]) + useUsersStore().addNewUsers(result) + const { data } = result data.account = useUsersStore().findUser(data.account.id) this.chat = data } catch (e) { diff --git a/src/components/lists_edit/lists_edit.js b/src/components/lists_edit/lists_edit.js index ec4cd1fa7..c7ead6b66 100644 --- a/src/components/lists_edit/lists_edit.js +++ b/src/components/lists_edit/lists_edit.js @@ -48,7 +48,7 @@ const ListsNew = { .then(() => { this.membersUserIds = this.findListAccounts(this.id) this.membersUserIds.forEach((userId) => { - this.$store.dispatch('fetchUserIfMissing', userId) + useUsersStore().fetchUserIfMissing(userId) }) }) }, diff --git a/src/components/remote_user_resolver/remote_user_resolver.js b/src/components/remote_user_resolver/remote_user_resolver.js index 75304fe52..109b92761 100644 --- a/src/components/remote_user_resolver/remote_user_resolver.js +++ b/src/components/remote_user_resolver/remote_user_resolver.js @@ -1,4 +1,5 @@ import { useOAuthStore } from 'src/stores/oauth.js' +import { useUsersStore } from 'src/stores/users.js' import { fetchUser } from 'src/api/public.js' @@ -16,17 +17,14 @@ const RemoteUserResolver = { id, credentials: useOAuthStore().token, }) - .then(({ data: externalUser }) => { - if (externalUser.error) { - this.error = true - } else { - this.$store.commit('addNewUsers', [externalUser]) - const id = externalUser.id - this.$router.replace({ - name: 'external-user-profile', - params: { id }, - }) - } + .then((result) => { + const { data: externalUser } = result + useUsersStore().addNewUsers(result) + const id = externalUser.id + this.$router.replace({ + name: 'external-user-profile', + params: { id }, + }) }) .catch(() => { this.error = true diff --git a/src/components/staff_panel/staff_panel.js b/src/components/staff_panel/staff_panel.js index b736bb9f9..8e8174394 100644 --- a/src/components/staff_panel/staff_panel.js +++ b/src/components/staff_panel/staff_panel.js @@ -1,15 +1,16 @@ import { groupBy, map } from 'lodash' -import { mapGetters, mapState } from 'vuex' +import { mapState } from 'pinia' import BasicUserCard from 'src/components/basic_user_card/basic_user_card.vue' import { useInstanceStore } from 'src/stores/instance.js' +import { useUsersStore } from 'src/stores/users.js' const StaffPanel = { created() { const nicknames = useInstanceStore().staffAccounts nicknames.forEach((nickname) => - this.$store.dispatch('fetchUserIfMissing', nickname), + useUsersStore().fetchUserIfMissing(nickname), ) }, components: { @@ -27,10 +28,8 @@ const StaffPanel = { { role: 'moderator', users: groupedStaffAccounts.moderator }, ].filter((group) => group.users) }, - ...mapGetters(['findUserByName']), - ...mapState({ - staffAccounts: (state) => useInstanceStore().staffAccounts, - }), + ...mapState(useUsersStore, ['findUserByName']), + ...mapState(useInstanceStore, ['staffAccounts']), }, } diff --git a/src/components/status/status.js b/src/components/status/status.js index 60411eead..5839eadde 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -174,9 +174,7 @@ const Status = { }, replyProfileLink() { if (this.isReply) { - const user = this.$store.getters.findUser( - this.status.in_reply_to_user_id, - ) + const user = useUsersStore().findUser(this.status.in_reply_to_user_id) // FIXME Why user not found sometimes??? return user ? user.statusnet_profile_url : 'NOT_FOUND' } @@ -371,9 +369,7 @@ const Status = { if (this.status.in_reply_to_screen_name) { return this.status.in_reply_to_screen_name } else { - const user = this.$store.getters.findUser( - this.status.in_reply_to_user_id, - ) + const user = useUsersStore().findUser(this.status.in_reply_to_user_id) return user?.screen_name_ui } }, diff --git a/src/components/status_body/status_body.js b/src/components/status_body/status_body.js index dc74426ca..b30395015 100644 --- a/src/components/status_body/status_body.js +++ b/src/components/status_body/status_body.js @@ -3,6 +3,7 @@ import { mapState } from 'pinia' import RichContent from 'src/components/rich_content/rich_content.jsx' import { useMergedConfigStore } from 'src/stores/merged_config.js' +import { useUsersStore } from 'src/stores/users.js' import { library } from '@fortawesome/fontawesome-svg-core' import { @@ -154,7 +155,7 @@ const StatusBody = { mounted() { this.status.attentions?.forEach((attn) => { const { id } = attn - this.$store.dispatch('fetchUserIfMissing', id) + useUsersStore().fetchUserIfMissing(id) }) }, methods: { @@ -171,7 +172,7 @@ const StatusBody = { if (!cleanedString.startsWith('@')) return const handle = cleanedString.slice(1) const host = url.replace(/^https?:\/\//, '').replace(/\/.+?$/, '') - this.$store.dispatch('fetchUserIfMissing', `${handle}@${host}`) + useUsersStore().fetchUserIfMissing(`${handle}@${host}`) }) /* This is a bit of a hack to make current tall status detector work * with rich mentions. Invisible mentions are detected at RichContent level diff --git a/src/components/user_profile/user_profile_admin_view.js b/src/components/user_profile/user_profile_admin_view.js index 342ca1109..534c85db3 100644 --- a/src/components/user_profile/user_profile_admin_view.js +++ b/src/components/user_profile/user_profile_admin_view.js @@ -20,7 +20,7 @@ const UserProfileAdminView = { } }, created() { - this.$store.dispatch('fetchUserIfMissing', this.userId) + useUsersStore().fetchUserIfMissing(this.userId) useInterfaceStore().setForeignProfileBackground(this.user?.background_image) }, updated() { diff --git a/src/components/who_to_follow/who_to_follow.js b/src/components/who_to_follow/who_to_follow.js index 28b63c973..44581f313 100644 --- a/src/components/who_to_follow/who_to_follow.js +++ b/src/components/who_to_follow/who_to_follow.js @@ -1,6 +1,7 @@ import FollowCard from 'src/components/follow_card/follow_card.vue' import { useOAuthStore } from 'src/stores/oauth.js' +import { useUsersStore } from 'src/stores/users.js' import { fetchUser, suggestions } from 'src/api/public.js' @@ -22,9 +23,10 @@ const WhoToFollow = { fetchUser({ id, credentials: useOAuthStore().token, - }).then(({ data: externalUser }) => { + }).then((result) => { + const { data: externalUser } = result if (!externalUser.error) { - this.$store.commit('addNewUsers', [externalUser]) + useUsersStore().addNewUsers(result) this.users.push(externalUser) } }) diff --git a/src/components/who_to_follow_panel/who_to_follow_panel.js b/src/components/who_to_follow_panel/who_to_follow_panel.js index 7e241d6eb..b87004e44 100644 --- a/src/components/who_to_follow_panel/who_to_follow_panel.js +++ b/src/components/who_to_follow_panel/who_to_follow_panel.js @@ -22,11 +22,10 @@ function showWhoToFollow(panel, reply) { fetchUser({ id: name, credentials: useOAuthStore().token, - }).then(({ data: externalUser }) => { - if (!externalUser.error) { - panel.$store.commit('addNewUsers', [externalUser]) - toFollow.id = externalUser.id - } + }).then((result) => { + const { data: externalUser } = result + useUsersStore().addNewUsers(result) + toFollow.id = externalUser.id }) }) } diff --git a/src/main.js b/src/main.js index 44b01aabb..ebe3feb1d 100644 --- a/src/main.js +++ b/src/main.js @@ -41,7 +41,7 @@ const i18n = createI18n({ messages.setLanguage(i18n.global, currentLocale) const persistedStateOptions = { - paths: ['users.lastLoginName', 'oauth', 'config'], + paths: ['oauth', 'config'], } ;(async () => { diff --git a/src/modules/statuses.js b/src/modules/statuses.js index bcef660a0..7a1444ad3 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -876,12 +876,16 @@ const statuses = { following, type, credentials: useOAuthStore().token, - }).then(({ data }) => { - store.commit('addNewUsers', data.accounts) - store.commit( - 'addNewUsers', - data.statuses.map((s) => s.user).filter(Boolean), - ) + }).then((result) => { + const { data, ...rest } = result + useUsersStore().addNewUsers({ + ...rest, + data: data.accounts, + }) + useUsersStore().addNewUsers({ + ...rest, + data: data.statuses.map((s) => s.user).filter(Boolean), + }) store.commit('addNewStatuses', { statuses: data.statuses, }) diff --git a/src/services/follow_request_fetcher/follow_request_fetcher.service.js b/src/services/follow_request_fetcher/follow_request_fetcher.service.js index e49206fcd..492c4e648 100644 --- a/src/services/follow_request_fetcher/follow_request_fetcher.service.js +++ b/src/services/follow_request_fetcher/follow_request_fetcher.service.js @@ -1,12 +1,15 @@ +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( - ({ data: requests }) => { + (result) => { + const { data: requests } = result store.commit('setFollowRequests', requests) - store.commit('addNewUsers', requests) + useUsersStore().addNewUsers(result) }, (rej) => { console.error(rej) diff --git a/src/stores/chats.js b/src/stores/chats.js index 5ade0c126..d9c077eba 100644 --- a/src/stores/chats.js +++ b/src/stores/chats.js @@ -5,6 +5,7 @@ import { maybeShowChatNotification } from '../services/chat_utils/chat_utils.js' import { promiseInterval } from '../services/promise_interval/promise_interval.js' import { useOAuthStore } from 'src/stores/oauth.js' +import { useUsersStore } from 'src/stores/users.js' import { chats } from 'src/api/chats.js' @@ -41,11 +42,11 @@ export const useChatsStore = defineStore('chats', { this.setChatListFetcher(null) }, async fetchChats() { - const { data } = await chats({ - credentials: useOAuthStore().token, - }) - - this.addNewChats(data) + this.addNewChats( + await chats({ + credentials: useOAuthStore().token, + }), + ) }, setChatListFetcher(fetcher) { const prevFetcher = this.chatListFetcher @@ -58,11 +59,11 @@ export const useChatsStore = defineStore('chats', { this.chatList = emptyChatList() this.setChatListFetcher(null) }, - addNewChats(chats) { - window.vuex.commit( - 'addNewUsers', - chats.map((k) => k.account).filter(Boolean), - ) + addNewChats(result) { + useUsersStore().addNewUsers({ + ...result, + data: result.data.map((k) => k.account).filter(Boolean), + }) chats.forEach((updatedChat) => { const chat = getChatById(this, updatedChat.id) diff --git a/src/stores/users.js b/src/stores/users.js index d03348bcb..0b9b233d1 100644 --- a/src/stores/users.js +++ b/src/stores/users.js @@ -68,6 +68,7 @@ export const useUsersStore = defineStore('users', { usersByName: new Map(), usersByURL: new Map(), relationships: new Map(), + timestamps: new WeakMap(), }), getters: { loggedIn: (state) => !!state.currentUser, @@ -137,9 +138,16 @@ export const useUsersStore = defineStore('users', { user.followerIds = [] } }, - addNewUsers(users, timestamp) { + addNewUsers(response) { + const { data, timestamp } = response + const users = Array.isArray(data) ? data : [data] + users.forEach((user) => { const existing = this.users.get(user.id) ?? {} + const oldTimestamp = this.timestamps.get(existing) + + // implicit: if oldTimestamp is undefined this will still be false + if (oldTimestamp > timestamp) return // not overwriting old data with new const { relationship, ...old } = existing const { relationshop, ...neu } = user @@ -148,6 +156,7 @@ export const useUsersStore = defineStore('users', { this.users.set(user.id, newUser) this.usersByName.set(user.screen_name.toLowerCase(), newUser) this.usersByURL.set(user.url.toLowerCase(), newUser) + this.timestamps.set(newUser, timestamp) if (user.id === this.currentUser.id) { this.currentUser = newUser @@ -277,7 +286,8 @@ export const useUsersStore = defineStore('users', { return fetchBlocks({ maxId, credentials: useOAuthStore().token, - }).then(({ data: blocks }) => { + }).then((result) => { + const { data: blocks } = result if (reset) { this.saveBlockIds(blocks.map(({ id }) => id)) } else { @@ -286,7 +296,7 @@ export const useUsersStore = defineStore('users', { if (blocks.length) { this.setBlockIdsMaxId(last(blocks).id) } - this.addNewUsers(blocks) + this.addNewUsers(result) return blocks }) }, @@ -337,7 +347,8 @@ export const useUsersStore = defineStore('users', { return fetchMutes({ maxId, credentials: useOAuthStore().token, - }).then(({ data: mutes }) => { + }).then((result) => { + const { data: mutes } = result if (reset) { this.saveMuteIds(mutes.map(({ id }) => id)) } else { @@ -346,7 +357,7 @@ export const useUsersStore = defineStore('users', { if (mutes.length) { this.setMuteIdsMaxId(last(mutes).id) } - this.addNewUsers(mutes) + this.addNewUsers(result) return mutes }) }, @@ -541,7 +552,7 @@ export const useUsersStore = defineStore('users', { verifyCredentials({ credentials: useOAuthStore().token, }) - .then(({ data: user }) => { + .then(({ data: user, ...rest }) => { // user.credentials = userCredentials user.credentials = accessToken user.blockIds = [] @@ -559,7 +570,7 @@ export const useUsersStore = defineStore('users', { }) }) useUserHighlightStore().initUserHighlight(user) - this.addNewUsers([user]) + this.addNewUsers({ data: user, ...rest }) useEmojiStore().fetchEmoji() @@ -598,7 +609,7 @@ export const useUsersStore = defineStore('users', { if (useInstanceCapabilitiesStore().pleromaChatMessagesAvailable) { // Start fetching chats - dispatch('startFetchingChats') + useChatsStore().startFetchingChats() } } @@ -643,7 +654,7 @@ export const useUsersStore = defineStore('users', { useInterfaceStore().setLayoutHeight(windowHeight()) // Fetch our friends - fetchFriends({ id: user.id }).then(({ data: friends }) => + fetchFriends({ id: user.id }).then((friends) => this.addNewUsers(friends), ) this.loggingIn = false @@ -670,4 +681,9 @@ export const useUsersStore = defineStore('users', { }) }, }, + persist: { + afterLoad({ lastLoginName }) { + return { lastLoginName } + }, + }, })