2022-01-01 20:42:25 +01:00
|
|
|
import { createContext, useContext, useEffect } from 'react'
|
|
|
|
|
2022-03-16 12:18:09 +01:00
|
|
|
import { NextPage, usePagination } from '../hooks/usePagination'
|
|
|
|
import { useAuthentication } from '../tools/authentication'
|
|
|
|
import { MessageWithMember } from '../models/Message'
|
|
|
|
import { GuildsChannelsPath } from '../components/Application'
|
|
|
|
import { handleSocketData, SocketData } from '../tools/handleSocketData'
|
2022-08-24 17:22:55 +02:00
|
|
|
import { CacheKey, MESSAGES_CACHE_KEY } from '../tools/cache'
|
2022-01-01 20:42:25 +01:00
|
|
|
|
|
|
|
export interface Messages {
|
|
|
|
messages: MessageWithMember[]
|
|
|
|
hasMore: boolean
|
|
|
|
nextPage: NextPage
|
|
|
|
}
|
|
|
|
|
|
|
|
const defaultMessagesContext = {} as any
|
|
|
|
const MessagesContext = createContext<Messages>(defaultMessagesContext)
|
|
|
|
|
|
|
|
export interface MessagesProviderProps {
|
|
|
|
path: GuildsChannelsPath
|
|
|
|
}
|
|
|
|
|
2022-05-12 20:35:46 +02:00
|
|
|
export const MessagesProvider: React.FC<
|
|
|
|
React.PropsWithChildren<MessagesProviderProps>
|
|
|
|
> = (props) => {
|
2022-01-01 20:42:25 +01:00
|
|
|
const { path, children } = props
|
2022-06-29 06:23:23 +02:00
|
|
|
const { authentication, user } = useAuthentication()
|
2022-01-01 20:42:25 +01:00
|
|
|
|
2022-08-24 17:22:55 +02:00
|
|
|
const cacheKey: CacheKey = `${path.channelId}-${MESSAGES_CACHE_KEY}`
|
|
|
|
|
2022-01-01 20:42:25 +01:00
|
|
|
const {
|
|
|
|
items: messages,
|
|
|
|
hasMore,
|
|
|
|
nextPage,
|
2022-01-13 18:21:45 +01:00
|
|
|
resetPagination,
|
|
|
|
setItems
|
2022-01-01 20:42:25 +01:00
|
|
|
} = usePagination<MessageWithMember>({
|
|
|
|
api: authentication.api,
|
|
|
|
url: `/channels/${path.channelId}/messages`,
|
2022-08-24 17:22:55 +02:00
|
|
|
inverse: true,
|
|
|
|
cacheKey
|
2022-01-01 20:42:25 +01:00
|
|
|
})
|
|
|
|
|
2022-01-13 18:21:45 +01:00
|
|
|
useEffect(() => {
|
2022-08-24 17:22:55 +02:00
|
|
|
authentication?.socket?.on(
|
2022-01-13 18:21:45 +01:00
|
|
|
'messages',
|
|
|
|
(data: SocketData<MessageWithMember>) => {
|
|
|
|
if (data.item.channelId === path.channelId) {
|
|
|
|
const messagesDiv = window.document.getElementById(
|
|
|
|
'messages'
|
|
|
|
) as HTMLDivElement
|
|
|
|
const isAtBottom =
|
|
|
|
messagesDiv.scrollHeight - messagesDiv.scrollTop <=
|
|
|
|
messagesDiv.clientHeight
|
2022-08-24 17:22:55 +02:00
|
|
|
handleSocketData({ data, setItems, cacheKey })
|
2022-06-29 06:23:23 +02:00
|
|
|
if (
|
|
|
|
data.action === 'create' &&
|
|
|
|
(isAtBottom || data.item.member.userId === user.id)
|
|
|
|
) {
|
2022-01-13 18:21:45 +01:00
|
|
|
messagesDiv.scrollTo(0, messagesDiv.scrollHeight)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
return () => {
|
2022-08-24 17:22:55 +02:00
|
|
|
authentication?.socket?.off('messages')
|
2022-01-13 18:21:45 +01:00
|
|
|
}
|
2022-08-24 17:22:55 +02:00
|
|
|
}, [authentication.socket, setItems, path, user.id, cacheKey])
|
2022-01-13 18:21:45 +01:00
|
|
|
|
2022-01-01 20:42:25 +01:00
|
|
|
useEffect(() => {
|
|
|
|
resetPagination()
|
|
|
|
nextPage(undefined, () => {
|
|
|
|
const messagesDiv = window.document.getElementById(
|
|
|
|
'messages'
|
|
|
|
) as HTMLDivElement
|
|
|
|
messagesDiv.scrollTo(0, messagesDiv.scrollHeight)
|
|
|
|
})
|
|
|
|
}, [nextPage, resetPagination])
|
|
|
|
|
|
|
|
return (
|
|
|
|
<MessagesContext.Provider value={{ messages, hasMore, nextPage }}>
|
|
|
|
{children}
|
|
|
|
</MessagesContext.Provider>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
export const useMessages = (): Messages => {
|
|
|
|
const messages = useContext(MessagesContext)
|
|
|
|
if (messages === defaultMessagesContext) {
|
|
|
|
throw new Error('useMessages must be used within a MessagesProvider')
|
|
|
|
}
|
|
|
|
return messages
|
|
|
|
}
|