// Copyright 2022 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import Measure from 'react-measure'; import React, { useRef, useState } from 'react'; import classNames from 'classnames'; import type { LocalizerType, RenderTextCallbackType } from '../types/Util'; import type { TextAttachmentType } from '../types/Attachment'; import { AddNewLines } from './conversation/AddNewLines'; import { Emojify } from './conversation/Emojify'; import { TextAttachmentStyleType } from '../types/Attachment'; import { count } from '../util/grapheme'; import { getDomain } from '../types/LinkPreview'; import { getFontNameByTextScript } from '../util/getFontNameByTextScript'; import { getHexFromNumber, getBackgroundColor, } from '../util/getStoryBackground'; const renderNewLines: RenderTextCallbackType = ({ text: textWithNewLines, key, }) => { return ; }; const CHAR_LIMIT_TEXT_LARGE = 50; const CHAR_LIMIT_TEXT_MEDIUM = 200; const COLOR_WHITE_INT = 4294704123; const FONT_SIZE_LARGE = 64; const FONT_SIZE_MEDIUM = 42; const FONT_SIZE_SMALL = 32; enum TextSize { Small, Medium, Large, } export type PropsType = { i18n: LocalizerType; isThumbnail?: boolean; textAttachment: TextAttachmentType; }; function getTextSize(text: string): TextSize { const length = count(text); if (length < CHAR_LIMIT_TEXT_LARGE) { return TextSize.Large; } if (length < CHAR_LIMIT_TEXT_MEDIUM) { return TextSize.Medium; } return TextSize.Small; } function getFont( text: string, textSize: TextSize, textStyle?: TextAttachmentStyleType | null, i18n?: LocalizerType ): string { const textStyleIndex = Number(textStyle) || 0; const fontName = getFontNameByTextScript(text, textStyleIndex, i18n); let fontSize = FONT_SIZE_SMALL; switch (textSize) { case TextSize.Large: fontSize = FONT_SIZE_LARGE; break; case TextSize.Medium: fontSize = FONT_SIZE_MEDIUM; break; default: fontSize = FONT_SIZE_SMALL; } const fontWeight = textStyle === TextAttachmentStyleType.BOLD ? 'bold ' : ''; return `${fontWeight}${fontSize}pt ${fontName}`; } export const TextAttachment = ({ i18n, isThumbnail, textAttachment, }: PropsType): JSX.Element | null => { const linkPreview = useRef(null); const [linkPreviewOffsetTop, setLinkPreviewOffsetTop] = useState< number | undefined >(); return ( {({ contentRect, measureRef }) => ( // eslint-disable-next-line jsx-a11y/no-static-element-interactions
{ if (linkPreviewOffsetTop) { setLinkPreviewOffsetTop(undefined); } }} onKeyUp={ev => { if (ev.key === 'Escape' && linkPreviewOffsetTop) { setLinkPreviewOffsetTop(undefined); } }} ref={measureRef} >
{textAttachment.text && (
)} {textAttachment.preview && ( <> {linkPreviewOffsetTop && !isThumbnail && textAttachment.preview.url && (
{i18n('TextAttachment__preview__link')}
{textAttachment.preview.url}
)}
setLinkPreviewOffsetTop(linkPreview?.current?.offsetTop) } onMouseOver={() => setLinkPreviewOffsetTop(linkPreview?.current?.offsetTop) } >
{textAttachment.preview.title && (
{textAttachment.preview.title}
)}
{getDomain(String(textAttachment.preview.url))}
)}
)} ); };