// Copyright 2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import React, { useState, useCallback } from 'react'; import classNames from 'classnames'; import { Button, ButtonVariant } from './Button'; import { QrCode } from './QrCode'; import type { ConversationType } from '../state/ducks/conversations'; import { Intl } from './Intl'; import { Emojify } from './conversation/Emojify'; import type { LocalizerType } from '../types/Util'; import type { SafetyNumberType } from '../types/safetyNumber'; import { SAFETY_NUMBER_MIGRATION_URL } from '../types/support'; import { SafetyNumberIdentifierType, SafetyNumberMode, } from '../types/safetyNumber'; import { arrow } from '../util/keyboard'; export type PropsType = { contact: ConversationType; generateSafetyNumber: (contact: ConversationType) => void; i18n: LocalizerType; onClose: () => void; safetyNumberMode: SafetyNumberMode; safetyNumbers?: ReadonlyArray; toggleVerified: (contact: ConversationType) => void; showOnboarding?: () => void; verificationDisabled: boolean; }; export function SafetyNumberViewer({ contact, generateSafetyNumber, i18n, onClose, safetyNumberMode, safetyNumbers, toggleVerified, showOnboarding, verificationDisabled, }: PropsType): JSX.Element | null { const hasSafetyNumbers = safetyNumbers != null; React.useEffect(() => { if (!contact) { return; } generateSafetyNumber(contact); }, [contact, generateSafetyNumber]); // Keyboard navigation const [selectedIndex, setSelectedIndex] = useState(0); const selectPrevNumber = useCallback(() => { setSelectedIndex(x => Math.max(x - 1, 0)); }, []); const selectNextNumber = useCallback(() => { if (!safetyNumbers || safetyNumbers.length === 0) { setSelectedIndex(0); return; } setSelectedIndex(x => Math.min(x + 1, safetyNumbers.length - 1)); }, [safetyNumbers]); React.useEffect(() => { const handleKeyDown = (ev: KeyboardEvent) => { if (ev.key === arrow('start')) { selectPrevNumber(); } if (ev.key === arrow('end')) { selectNextNumber(); } }; document.addEventListener('keydown', handleKeyDown); return () => { document.removeEventListener('keydown', handleKeyDown); }; }, [selectPrevNumber, selectNextNumber]); if (!contact || !hasSafetyNumbers) { return null; } if (!safetyNumbers.length) { return (
{i18n('icu:cannotGenerateSafetyNumber')}
); } const boldName = ( ); const { isVerified } = contact; const verifyButtonText = isVerified ? i18n('icu:SafetyNumberViewer__clearVerification') : i18n('icu:SafetyNumberViewer__markAsVerified'); const isMigrationVisible = safetyNumberMode !== SafetyNumberMode.JustE164; const visibleSafetyNumber = safetyNumbers.at(selectedIndex); if (!visibleSafetyNumber) { return null; } const cardClassName = classNames('module-SafetyNumberViewer__card', { 'module-SafetyNumberViewer__card--aci': visibleSafetyNumber.identifierType === SafetyNumberIdentifierType.ACIIdentifier, 'module-SafetyNumberViewer__card--e164': visibleSafetyNumber.identifierType === SafetyNumberIdentifierType.E164Identifier, }); const numberBlocks = visibleSafetyNumber.numberBlocks.join(' '); const safetyNumberCard = (
{numberBlocks}
{selectedIndex > 0 && (
); const carousel = (
{safetyNumbers.map(({ identifierType }, index) => { return (
); return (
{isMigrationVisible && (

{ if (showOnboarding) { e.preventDefault(); showOnboarding(); } }} >

)} {safetyNumberCard} {safetyNumbers.length > 1 && carousel}
{isMigrationVisible ? ( ) : ( )}
); }