/* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment */ import type { CSSProperties } from 'react'; import { useState, useRef, useCallback } from 'react'; import { FormattedDate, FormattedMessage } from 'react-intl'; import classNames from 'classnames'; import { Link } from 'react-router-dom'; import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?react'; import { AnimatedNumber } from 'mastodon/components/animated_number'; import { ContentWarning } from 'mastodon/components/content_warning'; import EditedTimestamp from 'mastodon/components/edited_timestamp'; import type { StatusLike } from 'mastodon/components/hashtag_bar'; import { getHashtagBarForStatus } from 'mastodon/components/hashtag_bar'; import { Icon } from 'mastodon/components/icon'; import { IconLogo } from 'mastodon/components/logo'; import PictureInPicturePlaceholder from 'mastodon/components/picture_in_picture_placeholder'; import { VisibilityIcon } from 'mastodon/components/visibility_icon'; import { Avatar } from '../../../components/avatar'; import { DisplayName } from '../../../components/display_name'; import MediaGallery from '../../../components/media_gallery'; import StatusContent from '../../../components/status_content'; import Audio from '../../audio'; import scheduleIdleTask from '../../ui/util/schedule_idle_task'; import Video from '../../video'; import Card from './card'; interface VideoModalOptions { startTime: number; autoPlay?: boolean; defaultVolume: number; componentIndex: number; } export const DetailedStatus: React.FC<{ status: any; onOpenMedia?: (status: any, index: number, lang: string) => void; onOpenVideo?: (status: any, lang: string, options: VideoModalOptions) => void; onTranslate?: (status: any) => void; measureHeight?: boolean; onHeightChange?: () => void; domain: string; showMedia?: boolean; withLogo?: boolean; pictureInPicture: any; onToggleHidden?: (status: any) => void; onToggleMediaVisibility?: () => void; }> = ({ status, onOpenMedia, onOpenVideo, onTranslate, measureHeight, onHeightChange, domain, showMedia, withLogo, pictureInPicture, onToggleMediaVisibility, onToggleHidden, }) => { const properStatus = status?.get('reblog') ?? status; const [height, setHeight] = useState(0); const nodeRef = useRef(); const handleOpenVideo = useCallback( (options: VideoModalOptions) => { const lang = (status.getIn(['translation', 'language']) || status.get('language')) as string; if (onOpenVideo) onOpenVideo(status.getIn(['media_attachments', 0]), lang, options); }, [onOpenVideo, status], ); const handleExpandedToggle = useCallback(() => { if (onToggleHidden) onToggleHidden(status); }, [onToggleHidden, status]); const _measureHeight = useCallback( (heightJustChanged?: boolean) => { if (measureHeight && nodeRef.current) { scheduleIdleTask(() => { if (nodeRef.current) setHeight(Math.ceil(nodeRef.current.scrollHeight) + 1); }); if (onHeightChange && heightJustChanged) { onHeightChange(); } } }, [onHeightChange, measureHeight, setHeight], ); const handleRef = useCallback( (c: HTMLDivElement) => { nodeRef.current = c; _measureHeight(); }, [_measureHeight], ); const handleTranslate = useCallback(() => { if (onTranslate) onTranslate(status); }, [onTranslate, status]); if (!properStatus) { return null; } let media; let applicationLink; let reblogLink; let attachmentAspectRatio; if (properStatus.get('media_attachments').getIn([0, 'type']) === 'video') { attachmentAspectRatio = `${properStatus.get('media_attachments').getIn([0, 'meta', 'original', 'width'])} / ${properStatus.get('media_attachments').getIn([0, 'meta', 'original', 'height'])}`; } else if ( properStatus.get('media_attachments').getIn([0, 'type']) === 'audio' ) { attachmentAspectRatio = '16 / 9'; } else { attachmentAspectRatio = properStatus.get('media_attachments').size === 1 && properStatus .get('media_attachments') .getIn([0, 'meta', 'small', 'aspect']) ? properStatus .get('media_attachments') .getIn([0, 'meta', 'small', 'aspect']) : '3 / 2'; } const outerStyle = { boxSizing: 'border-box' } as CSSProperties; if (measureHeight) { outerStyle.height = height; } const language = status.getIn(['translation', 'language']) || status.get('language'); if (pictureInPicture.get('inUse')) { media = ; } else if (status.get('media_attachments').size > 0) { if (status.getIn(['media_attachments', 0, 'type']) === 'audio') { const attachment = status.getIn(['media_attachments', 0]); const description = attachment.getIn(['translation', 'description']) || attachment.get('description'); media = (