import { createSelector } from '@reduxjs/toolkit' import { selectUserHasResponded } from 'domains/app/selectors' import { useConfig } from 'domains/config/hooks' import * as ConfigSelectors from 'domains/config/selectors' import type { RootState } from 'domains/store' import type { ChannelEvent, ServiceDataEvent } from 'domains/store/store.types' import { useSelector } from 'react-redux' import { microsecondsToMilliseconds } from 'ui/utils/general-utils' export const selectState = ({ state }: RootState) => state export const useSeamlyStateContext = () => useSelector(selectState) export const selectEventsWithSuggestion = createSelector( selectState, ConfigSelectors.selectConfig, selectUserHasResponded, ({ events, serviceData }, config, hasUserResponded) => { if ( hasUserResponded || config.layoutMode === 'inline' || !serviceData?.suggestion || !serviceData?.suggestion?.body?.length ) { return events } const suggestionsEvent: ServiceDataEvent = { type: 'service_data', payload: serviceData.suggestion, } return [...events, suggestionsEvent] }, ) export const selectEvents = createSelector( selectEventsWithSuggestion, ConfigSelectors.selectConfig, (events, config) => { const { enabled, threshold } = config?.messages?.timeIndicator ?? {} if (!enabled) { return events } return events.map(({ type, payload }, idx, arr) => { if (idx === 0) { return { type, payload: { ...payload, timeIndicator: payload?.occurredAt, }, } } const previousEvent = arr[idx - 1] if ( !payload?.occurredAt || !previousEvent.payload?.occurredAt || !threshold ) { return { type, payload: { ...payload, timeIndicator: undefined, }, } } const timeIndicator = microsecondsToMilliseconds( payload.occurredAt - previousEvent.payload.occurredAt, ) >= threshold ? payload.occurredAt : undefined return { type, payload: { ...payload, timeIndicator, }, } }) as ChannelEvent[] }, ) export const useEvents = () => useSelector(selectEvents) export const selectEventIds = createSelector(selectEvents, (events) => { return events.map((event) => event.payload.id) }) export const useEventsIds = () => useSelector(selectEventIds) export const useSeamlyIsLoading = () => useSeamlyStateContext().isLoading export const useSeamlyHeaderData = () => useSeamlyStateContext().headerTitles export const useSeamlyUnreadCount = () => useSeamlyStateContext().unreadEvents export const useLoadedImageEventIds = () => useSeamlyStateContext().loadedImageEventIds export const useSkiplinkElement = () => useSeamlyStateContext().skiplinkElementId export const useSkiplinkTarget = () => useSeamlyStateContext().skiplinkTargetId export const useSeamlyParticipant = (participantId) => useSeamlyStateContext().participantInfo.participants[participantId] export const useSeamlyServiceInfo = () => useSeamlyStateContext().serviceInfo const selectLastMessageEventId = createSelector(selectEvents, (events) => { const filteredEvents = events.filter((event) => event.type === 'message') return filteredEvents[filteredEvents.length - 1]?.payload.id }) export const useLastMessageEventId = () => useSelector(selectLastMessageEventId) export const useSeamlyIsHistoryLoaded = () => useSeamlyStateContext().historyLoaded export const useSeamlyCurrentAgent = () => { const { participants, currentAgent } = useSeamlyStateContext().participantInfo return currentAgent ? participants[currentAgent] : null } export const useSeamlyServiceData = (key: string) => { return useSeamlyStateContext().serviceData[key] } export const useEntryTextLimit = () => { const { entryMeta: { active: entryType, options, optionsOverride }, } = useSeamlyStateContext() let limit: number | null = null if (entryType && typeof optionsOverride[entryType]?.limit === 'number') { limit = optionsOverride[entryType].limit } else if (entryType && typeof options[entryType]?.limit === 'number') { limit = options[entryType].limit } return { hasLimit: limit !== null, limit: limit !== null ? limit : null, } } export const useSeamlyLayoutMode = () => { const { layoutMode } = useConfig() return { isInline: layoutMode === 'inline', isWindow: layoutMode === 'window', isApp: layoutMode === 'app', isResolving: !layoutMode, } }