// Copyright 2020-2021 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import React, { ReactPortal, useEffect, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; import { About } from './About'; import { Avatar } from '../Avatar'; import { AvatarLightbox } from '../AvatarLightbox'; import { ConversationType } from '../../state/ducks/conversations'; import { LocalizerType } from '../../types/Util'; import { SharedGroupNames } from '../SharedGroupNames'; export type PropsType = { areWeAdmin: boolean; contact?: ConversationType; readonly i18n: LocalizerType; isAdmin: boolean; isMember: boolean; onClose: () => void; openConversation: (conversationId: string) => void; removeMember: (conversationId: string) => void; showSafetyNumber: (conversationId: string) => void; toggleAdmin: (conversationId: string) => void; updateSharedGroups: () => void; }; export const ContactModal = ({ areWeAdmin, contact, i18n, isAdmin, isMember, onClose, openConversation, removeMember, showSafetyNumber, toggleAdmin, updateSharedGroups, }: PropsType): ReactPortal | null => { if (!contact) { throw new Error('Contact modal opened without a matching contact'); } const [root, setRoot] = useState(null); const overlayRef = useRef(null); const closeButtonRef = useRef(null); const [showingAvatar, setShowingAvatar] = useState(false); useEffect(() => { const div = document.createElement('div'); document.body.appendChild(div); setRoot(div); return () => { document.body.removeChild(div); setRoot(null); }; }, []); useEffect(() => { // Kick off the expensive hydration of the current sharedGroupNames updateSharedGroups(); }, [updateSharedGroups]); useEffect(() => { if (root !== null && closeButtonRef.current) { closeButtonRef.current.focus(); } }, [root]); useEffect(() => { const handler = (event: KeyboardEvent) => { if (event.key === 'Escape') { event.preventDefault(); event.stopPropagation(); onClose(); } }; document.addEventListener('keyup', handler); return () => { document.removeEventListener('keyup', handler); }; }, [onClose]); const onClickOverlay = (e: React.MouseEvent) => { if (e.target === overlayRef.current) { e.preventDefault(); e.stopPropagation(); onClose(); } }; let content: JSX.Element; if (showingAvatar) { content = ( setShowingAvatar(false)} /> ); } else { content = (
{!contact.isMe && ( )} {!contact.isMe && areWeAdmin && isMember && ( <> )}
); } return root ? createPortal(
{ overlayRef.current = ref; }} role="presentation" className="module-contact-modal__overlay" onClick={onClickOverlay} > {content}
, root ) : null; };