// Copyright 2018 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import React, { useEffect, useState } from 'react'; import { usePopper } from 'react-popper'; import { createPortal } from 'react-dom'; import { showSettings } from '../shims/Whisper'; import { Avatar, AvatarSize } from './Avatar'; import { AvatarPopup } from './AvatarPopup'; import type { LocalizerType, ThemeType } from '../types/Util'; import type { AvatarColorType } from '../types/Colors'; import type { BadgeType } from '../badges/types'; import { handleOutsideClick } from '../util/handleOutsideClick'; export type PropsType = { areStoriesEnabled: boolean; avatarPath?: string; badge?: BadgeType; color?: AvatarColorType; hasPendingUpdate: boolean; i18n: LocalizerType; isMe?: boolean; isVerified?: boolean; name?: string; phoneNumber?: string; profileName?: string; theme: ThemeType; title: string; hasFailedStorySends?: boolean; unreadStoriesCount: number; showArchivedConversations: () => void; startComposing: () => void; startUpdate: () => unknown; toggleProfileEditor: () => void; toggleStoriesView: () => unknown; }; export function MainHeader({ areStoriesEnabled, avatarPath, badge, color, hasFailedStorySends, hasPendingUpdate, i18n, name, phoneNumber, profileName, showArchivedConversations, startComposing, startUpdate, theme, title, toggleProfileEditor, toggleStoriesView, unreadStoriesCount, }: PropsType): JSX.Element { const [targetElement, setTargetElement] = useState(null); const [popperElement, setPopperElement] = useState(null); const [portalElement, setPortalElement] = useState(null); const [showAvatarPopup, setShowAvatarPopup] = useState(false); const popper = usePopper(targetElement, popperElement, { placement: 'bottom-start', strategy: 'fixed', modifiers: [ { name: 'offset', options: { offset: [null, 4], }, }, ], }); useEffect(() => { const div = document.createElement('div'); document.body.appendChild(div); setPortalElement(div); return () => { div.remove(); setPortalElement(null); }; }, []); useEffect(() => { return handleOutsideClick( () => { if (!showAvatarPopup) { return false; } setShowAvatarPopup(false); return true; }, { containerElements: [portalElement, targetElement], name: 'MainHeader.showAvatarPopup', } ); }, [portalElement, targetElement, showAvatarPopup]); useEffect(() => { function handleGlobalKeyDown(event: KeyboardEvent) { if (showAvatarPopup && event.key === 'Escape') { setShowAvatarPopup(false); } } document.addEventListener('keydown', handleGlobalKeyDown, true); return () => { document.removeEventListener('keydown', handleGlobalKeyDown, true); }; }, [showAvatarPopup]); return (
` needs it to determine blurring. sharedGroupNames={[]} size={AvatarSize.TWENTY_EIGHT} onClick={() => { setShowAvatarPopup(true); }} /> {hasPendingUpdate && (
)}
{showAvatarPopup && portalElement != null && createPortal(
{ toggleProfileEditor(); setShowAvatarPopup(false); }} onViewPreferences={() => { showSettings(); setShowAvatarPopup(false); }} onViewArchive={() => { showArchivedConversations(); setShowAvatarPopup(false); }} style={{}} />
, portalElement )}
{areStoriesEnabled && ( )}
); }