import { useConfig } from 'domains/config/hooks' import { useI18n } from 'domains/i18n/hooks' import { useAppDispatch, RootState } from 'domains/store' import { InfoEvent, ServiceDataEvent, ParticipantEvent, MessageEvent, } from 'domains/store/store.types' import { useVisibility } from 'domains/visibility/hooks' import { useCallback, useMemo } from 'preact/hooks' import { useSelector } from 'react-redux' import { useElementFocusingById } from 'ui/hooks/focus-helper-hooks' import useSeamlyCommands from 'ui/hooks/use-seamly-commands' import { actionTypes, sourceTypes, TRANSLATION_PROPOSAL, } from 'ui/utils/seamly-utils' import { selectIsTranslated } from './selectors' import { disableTranslation, disableTranslationProposalPrompt } from './slice' import { Language } from './translations.types' export function useTranslations() { const { sendContext } = useSeamlyCommands() const dispatch = useAppDispatch() const config = useConfig() const enableTranslations = useCallback( (userLocale: Language['locale'], source: string) => { sendContext({ userLocale, source, }) }, [sendContext], ) const disableTranslations = useCallback(() => { sendContext({ userLocale: config.context?.contentLocale, }) dispatch(disableTranslation()) }, [config.context?.contentLocale, dispatch, sendContext]) const { languages, isActive, isAvailable, currentLocale } = useSelector( ({ translations }: RootState) => translations, ) return { languages, isActive, isAvailable, currentLocale, enableTranslations, disableTranslations, } } export const useTranslatedEventData = < T extends MessageEvent | InfoEvent | ServiceDataEvent, >( eventData?: T, ): { body: T['payload']['body'] | T['payload']['translatedBody'] hasTranslation: boolean isTranslated: boolean locale: string } => { const isTranslated = useSelector(selectIsTranslated(eventData)) if (!eventData?.payload) { return { body: undefined, hasTranslation: false, isTranslated: false, locale: '', } } const translatedBody = eventData.payload?.translatedBody && 'data' in eventData.payload.translatedBody ? eventData.payload?.translatedBody.data : eventData.payload.translatedBody const { translation, body } = { body: eventData.payload?.body, translation: eventData.payload?.translation, } const hasTranslation = !!translatedBody return { // @ts-ignore body: isTranslated && hasTranslation ? translatedBody : body, hasTranslation, isTranslated: isTranslated && hasTranslation, locale: translation?.locale, } } export const useTranslatedParticipantData = ( channelEvent: ParticipantEvent, ) => { const { translatedBody, translation, body } = { body: channelEvent.payload?.participant?.introduction, translatedBody: channelEvent.payload?.participant?.translatedIntroduction, translation: channelEvent.payload?.participant?.translation, } const hasTranslation = !!translatedBody const isTranslated = useSelector(selectIsTranslated(channelEvent)) return { body: isTranslated && hasTranslation ? translatedBody : body, hasTranslation, isTranslated: isTranslated && hasTranslation, userLocale: translation?.locale, } } export function useTranslationsContainer() { const id = useSelector( ({ translations }: RootState) => translations.containerId, ) const focusContainer = useElementFocusingById(id) return { id, focusContainer } } export function useLocaleNativeName(userLocale?: string) { const { languages } = useTranslations() return useMemo( () => languages?.find((lang) => lang.locale === userLocale)?.nativeName, [userLocale, languages], ) } export const useTranslationProposal = () => { const { isActive, languages } = useTranslations() const dispatch = useAppDispatch() const { sendAction } = useSeamlyCommands() const { translationProposal } = useSelector( (state: RootState) => state.translations, ) const { enableTranslations } = useTranslations() const { isOpen } = useVisibility() const { userLocale } = useI18n() const proposedLocale = translationProposal?.proposedLocale const proposedLocaleNativeName = useLocaleNativeName(proposedLocale) const showProposal = useMemo( () => translationProposal !== null && !isActive && isOpen && userLocale !== proposedLocale && languages.some((language) => language.locale === proposedLocale), [ translationProposal, isActive, isOpen, userLocale, proposedLocale, languages, ], ) const dismissTranslationProposal = () => { sendAction({ type: actionTypes.dismiss, body: { type: TRANSLATION_PROPOSAL }, }) dispatch(disableTranslationProposalPrompt()) } const activateTranslationProposal = () => { if (translationProposal?.proposedLocale) enableTranslations( translationProposal.proposedLocale, sourceTypes.translationProposal, ) } return { activateTranslationProposal, dismissTranslationProposal, proposedLocale, proposedLocaleNativeName, showProposal, translationProposal, } }