better fetchUserIfMissing

This commit is contained in:
Henry Jameson 2026-08-10 16:22:33 +03:00
commit 92ef3b1cd1
5 changed files with 96 additions and 37 deletions

View file

@ -47,8 +47,8 @@ const ListsNew = {
.fetchListAccounts({ listId: this.id }) .fetchListAccounts({ listId: this.id })
.then(() => { .then(() => {
this.membersUserIds = this.findListAccounts(this.id) this.membersUserIds = this.findListAccounts(this.id)
this.membersUserIds.forEach((userId) => { this.membersUserIds.forEach((id) => {
useUsersStore().fetchUserIfMissing(userId) useUsersStore().fetchUserIfMissing({ id })
}) })
}) })
}, },

View file

@ -9,8 +9,8 @@ import { useUsersStore } from 'src/stores/users.js'
const StaffPanel = { const StaffPanel = {
created() { created() {
const nicknames = useInstanceStore().staffAccounts const nicknames = useInstanceStore().staffAccounts
nicknames.forEach((nickname) => nicknames.forEach((name) =>
useUsersStore().fetchUserIfMissing(nickname), useUsersStore().fetchUserIfMissing({ name }),
) )
}, },
components: { components: {

View file

@ -155,7 +155,7 @@ const StatusBody = {
mounted() { mounted() {
this.status.attentions?.forEach((attn) => { this.status.attentions?.forEach((attn) => {
const { id } = attn const { id } = attn
useUsersStore().fetchUserIfMissing(id) useUsersStore().fetchUserIfMissing({ id })
}) })
}, },
methods: { methods: {
@ -172,7 +172,7 @@ const StatusBody = {
if (!cleanedString.startsWith('@')) return if (!cleanedString.startsWith('@')) return
const handle = cleanedString.slice(1) const handle = cleanedString.slice(1)
const host = url.replace(/^https?:\/\//, '').replace(/\/.+?$/, '') 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 /* This is a bit of a hack to make current tall status detector work
* with rich mentions. Invisible mentions are detected at RichContent level * with rich mentions. Invisible mentions are detected at RichContent level

View file

@ -20,7 +20,7 @@ const UserProfileAdminView = {
} }
}, },
created() { created() {
useUsersStore().fetchUserIfMissing(this.userId) useUsersStore().fetchUserIfMissing({ id: this.userId })
useInterfaceStore().setForeignProfileBackground(this.user?.background_image) useInterfaceStore().setForeignProfileBackground(this.user?.background_image)
}, },
updated() { updated() {

View file

@ -69,6 +69,8 @@ export const useUsersStore = defineStore('users', {
usersByURL: new Map(), usersByURL: new Map(),
relationships: new Map(), relationships: new Map(),
timestamps: new WeakMap(), timestamps: new WeakMap(),
fetchesIds: new Map(),
fetchesNames: new Map(),
}), }),
getters: { getters: {
loggedIn: (state) => !!state.currentUser, loggedIn: (state) => !!state.currentUser,
@ -102,7 +104,7 @@ export const useUsersStore = defineStore('users', {
user.rights = newRights user.rights = newRights
}, },
async updateUserAdminData({ user }) { async updateUserAdminData({ user }) {
const localUser = await this.fetchUserIfMissing(user.id) const localUser = await this.fetchUserIfMissing({ id: user.id })
localUser.adminData = user localUser.adminData = user
localUser.deactivated = !user.is_active localUser.deactivated = !user.is_active
@ -227,39 +229,98 @@ export const useUsersStore = defineStore('users', {
} }
notification.from_profile = this.users.get(notification.from_profile.id) notification.from_profile = this.users.get(notification.from_profile.id)
}, },
async fetchUserIfMissing(id) { async fetchUserIfMissing({ id, name }) {
const user = this.findUser(id) 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) { 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 { } else {
return user return user
} }
}, },
fetchUser(id) { async fetchUser(id) {
return fetchUser({ try {
id, const result = await fetchUser({
credentials: useOAuthStore().token, 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
}
}) })
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) { async fetchUserByName(name) {
return fetchUserByName({ try {
name, const result = fetchUserByName({
credentials: useOAuthStore().token, name,
}).then(({ data: user }) => { credentials: useOAuthStore().token,
this.addNewUsers([user]) })
return user
}) 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) { fetchUserRelationship(id) {
if (this.currentUser) { if (this.currentUser) {
@ -682,8 +743,6 @@ export const useUsersStore = defineStore('users', {
}, },
}, },
persist: { persist: {
afterLoad({ lastLoginName }) { paths: ['lastLoginName'],
return { lastLoginName }
},
}, },
}) })