// Copyright 2020-2021 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import React, { useEffect, useState } from 'react'; import { missingCaseError } from '../../util/missingCaseError'; import { About } from './About'; import { Avatar } from '../Avatar'; import { AvatarLightbox } from '../AvatarLightbox'; import type { ConversationType } from '../../state/ducks/conversations'; import { Modal } from '../Modal'; import type { LocalizerType, ThemeType } from '../../types/Util'; import { BadgeDialog } from '../BadgeDialog'; import type { BadgeType } from '../../badges/types'; import { SharedGroupNames } from '../SharedGroupNames'; import { ConfirmationDialog } from '../ConfirmationDialog'; export type PropsDataType = { areWeASubscriber: boolean; areWeAdmin: boolean; badges: ReadonlyArray; contact?: ConversationType; conversationId?: string; readonly i18n: LocalizerType; isAdmin: boolean; isMember: boolean; theme: ThemeType; }; type PropsActionType = { hideContactModal: () => void; openConversationInternal: ( options: Readonly<{ conversationId: string; messageId?: string; switchToAssociatedView?: boolean; }> ) => void; removeMemberFromGroup: (conversationId: string, contactId: string) => void; toggleAdmin: (conversationId: string, contactId: string) => void; toggleSafetyNumberModal: (conversationId: string) => unknown; updateConversationModelSharedGroups: (conversationId: string) => void; }; export type PropsType = PropsDataType & PropsActionType; enum ContactModalView { Default, ShowingAvatar, ShowingBadges, } export const ContactModal = ({ areWeASubscriber, areWeAdmin, badges, contact, conversationId, hideContactModal, i18n, isAdmin, isMember, openConversationInternal, removeMemberFromGroup, theme, toggleAdmin, toggleSafetyNumberModal, updateConversationModelSharedGroups, }: PropsType): JSX.Element => { if (!contact) { throw new Error('Contact modal opened without a matching contact'); } const [view, setView] = useState(ContactModalView.Default); const [confirmToggleAdmin, setConfirmToggleAdmin] = useState(false); useEffect(() => { if (conversationId) { // Kick off the expensive hydration of the current sharedGroupNames updateConversationModelSharedGroups(conversationId); } }, [conversationId, updateConversationModelSharedGroups]); switch (view) { case ContactModalView.Default: { const preferredBadge: undefined | BadgeType = badges[0]; return (
setView(ContactModalView.ShowingAvatar)} onClickBadge={() => setView(ContactModalView.ShowingBadges)} />
{contact.title}
{contact.phoneNumber && (
{contact.phoneNumber}
)} {!contact.isMe && (
)}
{!contact.isMe && ( )} {!contact.isMe && areWeAdmin && isMember && conversationId && ( <> )}
{confirmToggleAdmin && conversationId && ( toggleAdmin(conversationId, contact.id), text: isAdmin ? i18n('ContactModal--rm-admin') : i18n('ContactModal--make-admin'), }, ]} i18n={i18n} onClose={() => setConfirmToggleAdmin(false)} > {isAdmin ? i18n('ContactModal--rm-admin-info', [contact.title]) : i18n('ContactModal--make-admin-info', [contact.title])} )}
); } case ContactModalView.ShowingAvatar: return ( setView(ContactModalView.Default)} /> ); case ContactModalView.ShowingBadges: return ( setView(ContactModalView.Default)} title={contact.title} /> ); default: throw missingCaseError(view); } };