diff --git a/src/app/services/user.ts b/src/app/services/user.ts index 22a8f57c..1f47c9f9 100644 --- a/src/app/services/user.ts +++ b/src/app/services/user.ts @@ -16,7 +16,7 @@ import { } from "@/types/user"; import BASE_URL, { ContentTypes } from "../config"; import { updateAutoDeleteSetting, updateMute } from "../slices/footprint"; -import { fillUsers, updateContactStatus as updateStatus } from "../slices/users"; +import { addUsers, fillUsers, updateContactStatus as updateStatus } from "../slices/users"; import { RootState } from "../store"; // import toast from "react-hot-toast"; import baseQuery from "./base.query"; @@ -65,17 +65,31 @@ export const userApi = createApi({ }), getContacts: builder.query({ query: () => ({ url: `/user/contacts` }), - async onQueryStarted(data, { dispatch, queryFulfilled }) { + async onQueryStarted(data, { dispatch, queryFulfilled, getState }) { try { - const { data: users } = await queryFulfilled; - const payloads = users.map((c) => { - const uid = c.target_uid; - const status = c.contact_info.status; - return { - uid, - status, - }; - }); + const { data: contacts } = await queryFulfilled; + + // Fill user data for any contact whose user entry is missing from the store + // (e.g. /user endpoint may not return all users to non-admin users) + const missingUsers = contacts + .filter((c) => !(getState() as RootState).users.byId[c.target_uid]) + .map((c) => ({ + ...c.target_info, + avatar: + c.target_info.avatar_updated_at === 0 + ? "" + : `${BASE_URL}/resource/avatar?uid=${c.target_uid}&t=${c.target_info.avatar_updated_at}`, + status: c.contact_info.status, + })); + + if (missingUsers.length > 0) { + dispatch(addUsers(missingUsers)); + } + + const payloads = contacts.map((c) => ({ + uid: c.target_uid, + status: c.contact_info.status, + })); dispatch(updateStatus(payloads)); } catch { console.log("get contact list error"); diff --git a/src/app/slices/users.ts b/src/app/slices/users.ts index 6578c462..1846ec99 100644 --- a/src/app/slices/users.ts +++ b/src/app/slices/users.ts @@ -100,6 +100,17 @@ const usersSlice = createSlice({ } }); }, + // Merge users into store without overwriting existing entries + addUsers(state, action: PayloadAction) { + const users = action.payload || []; + users.forEach((user) => { + const { uid } = user; + if (!state.byId[uid]) { + state.byId[uid] = user; + state.ids.push(uid); + } + }); + }, updateContactStatus( state, action: PayloadAction< @@ -116,6 +127,6 @@ const usersSlice = createSlice({ } }); -export const { updateContactStatus, resetUsers, fillUsers, updateUsersByLogs, updateUsersStatus } = +export const { updateContactStatus, resetUsers, fillUsers, updateUsersByLogs, updateUsersStatus, addUsers } = usersSlice.actions; export default usersSlice.reducer; diff --git a/src/hooks/useFilteredUsers.ts b/src/hooks/useFilteredUsers.ts index 9c140652..5176a9f4 100644 --- a/src/hooks/useFilteredUsers.ts +++ b/src/hooks/useFilteredUsers.ts @@ -16,7 +16,7 @@ export default function useFilteredUsers() { ); const [filteredUsers, setFilteredUsers] = useState([]); const useContactList = enableContact && !isAdmin; - const users = useContactList ? originUsers.filter((u) => u.status == "added") : originUsers; + const users = useContactList ? originUsers.filter((u) => u.status == "added" || u.is_admin) : originUsers; useEffect(() => { if (!input) { setFilteredUsers(sortUsersByRole(users));