From d976811cf173397c26b17117ada8ca6712b93ea4 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 4 Apr 2022 15:55:28 -0500 Subject: [PATCH] Convert DetailedStatus to tsx, pretty much --- ...detailed_status.js => detailed-status.tsx} | 180 ++++++++++-------- .../containers/detailed_status_container.js | 2 +- app/soapbox/features/status/index.tsx | 3 +- 3 files changed, 103 insertions(+), 82 deletions(-) rename app/soapbox/features/status/components/{detailed_status.js => detailed-status.tsx} (52%) diff --git a/app/soapbox/features/status/components/detailed_status.js b/app/soapbox/features/status/components/detailed-status.tsx similarity index 52% rename from app/soapbox/features/status/components/detailed_status.js rename to app/soapbox/features/status/components/detailed-status.tsx index 61c338ceb..8ff1b6ff8 100644 --- a/app/soapbox/features/status/components/detailed_status.js +++ b/app/soapbox/features/status/components/detailed-status.tsx @@ -1,11 +1,9 @@ import classNames from 'classnames'; -import PropTypes from 'prop-types'; import React from 'react'; -import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import { FormattedMessage, injectIntl } from 'react-intl'; +import { FormattedMessage, injectIntl, WrappedComponentProps as IntlProps } from 'react-intl'; import { FormattedDate } from 'react-intl'; -import { Link, NavLink } from 'react-router-dom'; +import { Link } from 'react-router-dom'; import Icon from 'soapbox/components/icon'; import QuotedStatus from 'soapbox/features/status/containers/quoted_status_container'; @@ -23,27 +21,37 @@ import Video from '../../video'; import Card from './card'; import StatusInteractionBar from './status_interaction_bar'; -export default @injectIntl -class DetailedStatus extends ImmutablePureComponent { +import type { List as ImmutableList } from 'immutable'; +import type { Attachment as AttachmentEntity, Status as StatusEntity } from 'soapbox/types/entities'; - static propTypes = { - status: ImmutablePropTypes.record, - onOpenMedia: PropTypes.func.isRequired, - onOpenVideo: PropTypes.func.isRequired, - onToggleHidden: PropTypes.func.isRequired, - measureHeight: PropTypes.bool, - onHeightChange: PropTypes.func, - domain: PropTypes.string, - compact: PropTypes.bool, - showMedia: PropTypes.bool, - onToggleMediaVisibility: PropTypes.func, - }; +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, }; - handleOpenVideo = (media, startTime) => { + node: HTMLDivElement | null = null; + + handleOpenVideo = (media: ImmutableList, startTime: number) => { this.props.onOpenVideo(media, startTime); } @@ -51,7 +59,7 @@ class DetailedStatus extends ImmutablePureComponent { this.props.onToggleHidden(this.props.status); } - _measureHeight(heightJustChanged) { + _measureHeight(heightJustChanged = false) { if (this.props.measureHeight && this.node) { scheduleIdleTask(() => this.node && this.setState({ height: Math.ceil(this.node.scrollHeight) + 1 })); @@ -61,7 +69,7 @@ class DetailedStatus extends ImmutablePureComponent { } } - setRef = c => { + setRef: React.RefCallback = c => { this.node = c; this._measureHeight(); @@ -70,35 +78,41 @@ class DetailedStatus extends ImmutablePureComponent { } } - componentDidUpdate(prevProps, prevState) { + componentDidUpdate(prevProps: IDetailedStatus, prevState: IDetailedStatusState) { this._measureHeight(prevState.height !== this.state.height); } - handleModalLink = e => { - e.preventDefault(); + // 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'); + // } - 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.props.status && this.props.status.get('reblog')) ? this.props.status.get('reblog') : this.props.status; - const outerStyle = { boxSizing: 'border-box' }; - const { compact } = this.props; - const favicon = status.getIn(['account', 'pleroma', 'favicon']); - const domain = getDomain(status.get('account')); - const size = status.get('media_attachments').size; + 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; + const favicon = account.getIn(['pleroma', 'favicon']); + const domain = getDomain(account); - if (!status) { - return null; - } let media = null; let statusTypeIcon = null; @@ -107,12 +121,15 @@ class DetailedStatus extends ImmutablePureComponent { outerStyle.height = `${this.state.height}px`; } - if (size > 0) { - if (size === 1 && status.getIn(['media_attachments', 0, 'type']) === 'video') { - const video = status.getIn(['media_attachments', 0]); + 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 / (video.getIn(['meta', 'original', 'width']) / video.getIn(['meta', 'original', 'height'])); + const height = mediaWrapperWidth / Number(video.meta.getIn(['original', 'width'])) / Number(video.meta.getIn(['original', 'height'])); media = (
); } - } else if (size === 1 && status.getIn(['media_attachments', 0, 'type']) === 'audio' && status.get('media_attachments').size === 1) { - const attachment = status.getIn(['media_attachments', 0]); + } else if (size === 1 && firstAttachment.type === 'audio') { + const attachment = firstAttachment; media = (