import classNames from 'classnames'; import React from 'react'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { FormattedMessage, injectIntl, WrappedComponentProps as IntlProps } from 'react-intl'; import { FormattedDate } from 'react-intl'; import Icon from 'soapbox/components/icon'; import QuotedStatus from 'soapbox/features/status/containers/quoted_status_container'; import MediaGallery from '../../../components/media_gallery'; import StatusContent from '../../../components/status_content'; import StatusReplyMentions from '../../../components/status_reply_mentions'; import { HStack, Text } from '../../../components/ui'; import AccountContainer from '../../../containers/account_container'; import Audio from '../../audio'; import scheduleIdleTask from '../../ui/util/schedule_idle_task'; import Video from '../../video'; import Card from './card'; import StatusInteractionBar from './status-interaction-bar'; import type { List as ImmutableList } from 'immutable'; import type { Attachment as AttachmentEntity, Status as StatusEntity } from 'soapbox/types/entities'; interface IDetailedStatus extends IntlProps { status: StatusEntity, onOpenMedia: (media: ImmutableList, index: number) => void, onOpenVideo: (media: ImmutableList, start: number) => void, onToggleHidden: (status: StatusEntity) => void, measureHeight: boolean, onHeightChange: () => void, domain: string, compact: boolean, showMedia: boolean, onToggleMediaVisibility: () => void, } interface IDetailedStatusState { height: number | null, mediaWrapperWidth: number, } class DetailedStatus extends ImmutablePureComponent { state = { height: null, mediaWrapperWidth: NaN, }; node: HTMLDivElement | null = null; handleOpenVideo = (media: ImmutableList, startTime: number) => { this.props.onOpenVideo(media, startTime); } handleExpandedToggle = () => { this.props.onToggleHidden(this.props.status); } _measureHeight(heightJustChanged = false) { if (this.props.measureHeight && this.node) { scheduleIdleTask(() => this.node && this.setState({ height: Math.ceil(this.node.scrollHeight) + 1 })); if (this.props.onHeightChange && heightJustChanged) { this.props.onHeightChange(); } } } setRef: React.RefCallback = c => { this.node = c; this._measureHeight(); if (c) { this.setState({ mediaWrapperWidth: c.offsetWidth }); } } componentDidUpdate(prevProps: IDetailedStatus, prevState: IDetailedStatusState) { this._measureHeight(prevState.height !== this.state.height); } // handleModalLink = e => { // e.preventDefault(); // // let href; // // if (e.target.nodeName !== 'A') { // href = e.target.parentNode.href; // } else { // href = e.target.href; // } // // window.open(href, 'soapbox-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes'); // } getActualStatus = () => { const { status } = this.props; if (!status) return undefined; return status.reblog && typeof status.reblog === 'object' ? status.reblog : status; } render() { const status = this.getActualStatus(); if (!status) return null; const { account } = status; if (!account || typeof account !== 'object') return null; const outerStyle: React.CSSProperties = { boxSizing: 'border-box' }; const { compact } = this.props; let media = null; let statusTypeIcon = null; if (this.props.measureHeight) { outerStyle.height = `${this.state.height}px`; } const size = status.media_attachments.size; const firstAttachment = status.media_attachments.get(0); if (size > 0 && firstAttachment) { if (size === 1 && firstAttachment.type === 'video') { const video = firstAttachment; if (video.external_video_id && status.card?.html) { const { mediaWrapperWidth } = this.state; const height = mediaWrapperWidth / Number(video.meta.getIn(['original', 'width'])) / Number(video.meta.getIn(['original', 'height'])); media = (
); } else { media = (