import { useQueryClient } from '@tanstack/react-query' import { useCallback, useMemo } from 'react' import { ApiResource, ConversationResource } from '../types' import { JoltConversationEvent, JoltReactionEvent } from '../types/jolt_events' import { completeMessageCreationConversationTracking } from '../utils/performance_tracking' import { useApiClient } from './use_api_client' import { getConversationRequestArgs } from './use_conversation' import { useCurrentPerson } from './use_current_person' import { useJoltChannel, useJoltEvent } from './use_jolt' import { getRequestQueryKey } from './use_suspense_api' interface Props { conversationId: number } export function useConversationJoltEvents({ conversationId }: Props) { const joltChannel = useJoltChannel(`chat.conversations.${conversationId}`) const queryClient = useQueryClient() const currentPerson = useCurrentPerson() const currentPersonId = currentPerson?.id const apiClient = useApiClient() const queryKey = useMemo( () => getRequestQueryKey(getConversationRequestArgs({ conversation_id: conversationId })), [conversationId] ) const handleUpdatedConversation = useCallback( (e: JoltConversationEvent) => { const { last_message_idempotent_key, last_message_author_id, disabled, disabled_reason, disabled_message, } = e.data.data if (last_message_idempotent_key && last_message_author_id === currentPersonId) { completeMessageCreationConversationTracking({ apiClient, idempotentKey: last_message_idempotent_key, }) } queryClient.setQueryData>(queryKey, prev => { if (!prev?.data) return prev return { ...prev, data: { ...prev.data, disabled, disabledReason: disabled_reason, disabledMessage: disabled_message, }, } }) queryClient.invalidateQueries({ queryKey }) }, [queryClient, queryKey, currentPersonId, apiClient] ) const handleConversationRead = useCallback( (e: JoltConversationEvent) => { const { latest_read_message_sort_key } = e.data.data queryClient.setQueryData>(queryKey, prev => { if (!prev?.data || !latest_read_message_sort_key) return prev if ( prev.data.latestReadMessageSortKey && prev.data.latestReadMessageSortKey >= latest_read_message_sort_key ) { return prev } return { ...prev, data: { ...prev.data, latestReadMessageSortKey: latest_read_message_sort_key, unreadReaction: false, }, } }) }, [queryClient, queryKey] ) const handleConversationDestroyed = useCallback(() => { queryClient.setQueryData>(queryKey, prev => { if (!prev?.data) return prev return { ...prev, data: { ...prev.data, deleted: true, }, } }) }, [queryClient, queryKey]) const handleReactionJoltEvent = useCallback( (event: JoltReactionEvent) => { if (event.event !== 'reaction.created') return if (event.data.data.author_id === currentPersonId) return if (event.data.data.message_author_id !== currentPersonId) return queryClient.setQueryData>(queryKey, prev => { if (!prev?.data) return prev return { ...prev, data: { ...prev.data, unreadReaction: true } } }) }, [queryClient, queryKey, currentPersonId] ) useJoltEvent(joltChannel, 'conversation.updated', handleUpdatedConversation) useJoltEvent(joltChannel, 'conversation.read', handleConversationRead) useJoltEvent(joltChannel, 'conversation.destroyed', handleConversationDestroyed) useJoltEvent(joltChannel, 'reaction.*', handleReactionJoltEvent) }