import React, { useCallback, useEffect, useState } from 'react'; import cx from 'classnames'; import { Memori, Message, Tenant, Venue, User, } from '@memori.ai/memori-api-client/dist/types'; import Button from '../ui/Button'; import Dropdown from '../ui/Dropdown'; import MapMarker from '../icons/MapMarker'; import SoundDeactivated from '../icons/SoundDeactivated'; import Sound from '../icons/Sound'; import { useTranslation } from 'react-i18next'; import Setting from '../icons/Setting'; import ShareButton from '../ShareButton/ShareButton'; import FullscreenExit from '../icons/FullscreenExit'; import Fullscreen from '../icons/Fullscreen'; import Refresh from '../icons/Refresh'; import Clear from '../icons/Clear'; import DeepThought from '../icons/DeepThought'; import Group from '../icons/Group'; import UserIcon from '../icons/User'; import MessageIcon from '../icons/Message'; import Logout from '../icons/Logout'; import { getErrori18nKey } from '../../helpers/error'; import toast from 'react-hot-toast'; import memoriApiClient from '@memori.ai/memori-api-client'; import { Props as WidgetProps } from '../MemoriWidget/MemoriWidget'; import ChatConsumptionDropdown from './ChatConsumptionDropdown'; const imgMimeTypes = ['image/jpeg', 'image/png', 'image/jpg', 'image/gif']; export interface Props { className?: string; memori: Memori; tenant?: Tenant; history: Message[]; position?: Venue; setShowPositionDrawer: (show: boolean) => void; setShowSettingsDrawer: (show: boolean) => void; setShowChatHistoryDrawer: (show: boolean) => void; setShowKnownFactsDrawer: (show: boolean) => void; setShowExpertsDrawer: (show: boolean) => void; enableAudio?: boolean; speakerMuted: boolean; setSpeakerMuted: (mute: boolean) => void; hasUserActivatedSpeak?: boolean; showShare?: boolean; showSettings?: boolean; showChatHistory?: boolean; showReload?: boolean; showClear?: boolean; showLogin?: boolean; setShowLoginDrawer: (show: boolean) => void; clearHistory: () => void; loginToken?: string; user?: User; sessionID?: string; baseUrl?: string; fullScreenHandler?: (e: React.MouseEvent) => void; onLogout?: () => void; apiClient: ReturnType; layout?: WidgetProps['layout']; additionalSettings?: WidgetProps['additionalSettings']; showMessageConsumption?: boolean; } const Header: React.FC = ({ className, memori, tenant, history, position, setShowPositionDrawer, setShowSettingsDrawer, setShowChatHistoryDrawer, setShowKnownFactsDrawer, setShowExpertsDrawer, enableAudio = true, speakerMuted, setSpeakerMuted, hasUserActivatedSpeak = false, showShare = true, showSettings = true, showReload = false, showClear = false, showLogin = true, setShowLoginDrawer, clearHistory, loginToken, user, sessionID, showChatHistory = true, fullScreenHandler, baseUrl, onLogout, apiClient, layout, additionalSettings, showMessageConsumption = false, }) => { const { t, i18n } = useTranslation(); const { uploadAsset, pwlUpdateUser } = apiClient.backend; const [fullScreenAvailable, setFullScreenAvailable] = useState(false); const [fullScreen, setFullScreen] = useState(false); useEffect(() => { if (document.fullscreenEnabled) { setFullScreenAvailable(true); } }, []); // Helper function to determine if settings drawer has content const hasSettingsContent = useCallback(( layout?: WidgetProps['layout'], additionalSettings?: WidgetProps['additionalSettings'] ): boolean => { return ( layout === 'TOTEM' || (additionalSettings && Object.keys(additionalSettings).length > 0) || false ); }, [layout, additionalSettings]); const hasSpacedButtons = layout === 'FULLPAGE' || layout === 'CHAT' || layout === 'ZOOMED_FULL_BODY'; const updateAvatar = async (avatar: any) => { if (avatar && loginToken) { const reader = new FileReader(); reader.onload = async e => { try { const { asset: avatarAsset, ...resp } = await uploadAsset( avatar.name ?? 'avatar', e.target?.result as string, loginToken ?? '' ); if (resp.resultCode !== 0) { console.error('[updateAvatar] Upload failed:', resp); toast.error(t(getErrori18nKey(resp.resultCode))); } else if (avatarAsset) { let newUser: Partial = { userID: user?.userID, avatarURL: avatarAsset.assetURL, }; const { user: patchedUser, ...resp } = await pwlUpdateUser( loginToken ?? '', user?.userID ?? '', newUser ); } } catch (e) { let err = e as Error; console.error('[updateAvatar] Error:', err); if (err?.message) toast.error(err.message); } }; reader.readAsDataURL(avatar as Blob); } else { console.error('[updateAvatar] Missing avatar or login token', { avatar, loginToken, }); toast.error(t('login.avatarUploadError')); } }; return (
{memori.needsPosition && position && (
{position.latitude !== 0 && position.longitude !== 0 && ( {position.placeName} )}
)} {showReload && (
) : (