diff --git a/src/components/lists_edit/lists_edit.js b/src/components/lists_edit/lists_edit.js index c7ead6b66..cea9236a5 100644 --- a/src/components/lists_edit/lists_edit.js +++ b/src/components/lists_edit/lists_edit.js @@ -47,8 +47,8 @@ const ListsNew = { .fetchListAccounts({ listId: this.id }) .then(() => { this.membersUserIds = this.findListAccounts(this.id) - this.membersUserIds.forEach((userId) => { - useUsersStore().fetchUserIfMissing(userId) + this.membersUserIds.forEach((id) => { + useUsersStore().fetchUserIfMissing({ id }) }) }) }, diff --git a/src/components/staff_panel/staff_panel.js b/src/components/staff_panel/staff_panel.js index 8e8174394..ea2a0194f 100644 --- a/src/components/staff_panel/staff_panel.js +++ b/src/components/staff_panel/staff_panel.js @@ -9,8 +9,8 @@ import { useUsersStore } from 'src/stores/users.js' const StaffPanel = { created() { const nicknames = useInstanceStore().staffAccounts - nicknames.forEach((nickname) => - useUsersStore().fetchUserIfMissing(nickname), + nicknames.forEach((name) => + useUsersStore().fetchUserIfMissing({ name }), ) }, components: { diff --git a/src/components/status_body/status_body.js b/src/components/status_body/status_body.js index b30395015..d361f3a9a 100644 --- a/src/components/status_body/status_body.js +++ b/src/components/status_body/status_body.js @@ -155,7 +155,7 @@ const StatusBody = { mounted() { this.status.attentions?.forEach((attn) => { const { id } = attn - useUsersStore().fetchUserIfMissing(id) + useUsersStore().fetchUserIfMissing({ id }) }) }, methods: { @@ -172,7 +172,7 @@ const StatusBody = { if (!cleanedString.startsWith('@')) return const handle = cleanedString.slice(1) const host = url.replace(/^https?:\/\//, '').replace(/\/.+?$/, '') - useUsersStore().fetchUserIfMissing(`${handle}@${host}`) + useUsersStore().fetchUserIfMissing({ name: `${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 534c85db3..da0a05372 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() { - useUsersStore().fetchUserIfMissing(this.userId) + useUsersStore().fetchUserIfMissing({ id: this.userId }) useInterfaceStore().setForeignProfileBackground(this.user?.background_image) }, updated() { diff --git a/src/stores/users.js b/src/stores/users.js index 0b9b233d1..c1f85d5f8 100644 --- a/src/stores/users.js +++ b/src/stores/users.js @@ -69,6 +69,8 @@ export const useUsersStore = defineStore('users', { usersByURL: new Map(), relationships: new Map(), timestamps: new WeakMap(), + fetchesIds: new Map(), + fetchesNames: new Map(), }), getters: { loggedIn: (state) => !!state.currentUser, @@ -102,7 +104,7 @@ export const useUsersStore = defineStore('users', { user.rights = newRights }, async updateUserAdminData({ user }) { - const localUser = await this.fetchUserIfMissing(user.id) + const localUser = await this.fetchUserIfMissing({ id: user.id }) localUser.adminData = user localUser.deactivated = !user.is_active @@ -227,39 +229,98 @@ export const useUsersStore = defineStore('users', { } notification.from_profile = this.users.get(notification.from_profile.id) }, - async fetchUserIfMissing(id) { - const user = this.findUser(id) + async fetchUserIfMissing({ id, name }) { + let findFunc + let fetchFunc + let map + let otherMap + let identifier + + if (id) { + findFunc = this.findUser + fetchFunc = this.fetchUser + map = this.fetchesIds + identifier = id + } else if (name) { + findFunc = this.findUserByName + fetchFunc = this.fetchUserByName + map = this.fetchesNames + identifier = name + } else { + throw new TypeError('No identifier provided') + } + + const user = findFunc(identifier) + if (!user) { - return this.fetchUser(id) + let promise + + if (map.has(identifier)) { + promise = map.get(identifier) + } else { + promise = fetchFunc(identifier) + } + + map.set(identifier, promise) + + const result = await promise + + if (result?.data) { + const { id, screen_name } = result.data + + this.fetchesIds.set(id, promise) + this.fetchesNames.set(screen_name, promise) + this.addNewUsers(result) + return this.users.get(id) + } else { + return null + } } else { return user } }, - fetchUser(id) { - return fetchUser({ - id, - credentials: useOAuthStore().token, - }) - .then(({ data: user }) => { - this.addNewUsers([user]) - return user - }) - .catch((error) => { - if (error.statusCode === 404) { - console.warn(`User ${id} not found`) - } else { - throw error - } + async fetchUser(id) { + try { + const result = await fetchUser({ + id, + credentials: useOAuthStore().token, }) + + this.addNewUsers(result) + return this.users.get(result.data.id) + } catch(error) { + if ( + error.name === 'StatusCodeError' && + error.statusCode === 404 + ) { + console.warn(`User ${id} not found`) + return null + } else { + throw error + } + } }, - fetchUserByName(name) { - return fetchUserByName({ - name, - credentials: useOAuthStore().token, - }).then(({ data: user }) => { - this.addNewUsers([user]) - return user - }) + async fetchUserByName(name) { + try { + const result = fetchUserByName({ + name, + credentials: useOAuthStore().token, + }) + + this.addNewUsers(result) + + return this.users.get(result.data.id) + } catch(error) { + if ( + error.name === 'StatusCodeError' && + error.statusCode === 404 + ) { + console.warn(`User ${id} not found`) + return null + } else { + throw error + } + } }, fetchUserRelationship(id) { if (this.currentUser) { @@ -682,8 +743,6 @@ export const useUsersStore = defineStore('users', { }, }, persist: { - afterLoad({ lastLoginName }) { - return { lastLoginName } - }, + paths: ['lastLoginName'], }, })