import { createContext, useContext, useEffect, useMemo } from "react" import type { NextPage } from "../hooks/usePagination" import { usePagination } from "../hooks/usePagination" import { useAuthentication } from "../tools/authentication" import type { MemberWithPublicUser } from "../models/Member" import type { GuildsChannelsPath } from "../components/Application" import type { SocketData } from "../tools/handleSocketData" import { handleSocketData } from "../tools/handleSocketData" import type { User } from "../models/User" import type { CacheKey } from "../tools/cache" import { MEMBERS_CACHE_KEY } from "../tools/cache" export interface Members { members: MemberWithPublicUser[] hasMore: boolean nextPage: NextPage } const defaultMembersContext = {} as any const MembersContext = createContext(defaultMembersContext) export interface MembersProviderProps { path: GuildsChannelsPath } export const MembersProviders: React.FC< React.PropsWithChildren > = (props) => { const { children, path } = props const { authentication } = useAuthentication() const cacheKey = useMemo(() => { return `${path.guildId}-${MEMBERS_CACHE_KEY}` }, [path.guildId]) const { items: members, hasMore, nextPage, resetPagination, setItems, } = usePagination({ api: authentication.api, url: `/guilds/${path.guildId}/members`, cacheKey, }) useEffect(() => { authentication?.socket?.on( "members", (data: SocketData) => { handleSocketData({ data, setItems, cacheKey }) }, ) authentication?.socket?.on("users", (data: SocketData) => { setItems((oldItems) => { const newItems = [...oldItems] switch (data.action) { case "update": { for (const member of newItems) { if (member.user.id === data.item.id) { member.user = data.item break } } break } } return newItems }) }) return () => { authentication?.socket?.off("members") authentication?.socket?.off("users") } }, [authentication.socket, setItems, cacheKey]) useEffect(() => { resetPagination() nextPage() }, [nextPage, resetPagination]) return ( {children} ) } export const useMembers = (): Members => { const members = useContext(MembersContext) if (members === defaultMembersContext) { throw new Error("`useMembers` must be used within `MembersProvider`") } return members }