diff --git a/app/soapbox/features/status/components/detailed-status.tsx b/app/soapbox/features/status/components/detailed-status.tsx index ebdb0be46..79c40346a 100644 --- a/app/soapbox/features/status/components/detailed-status.tsx +++ b/app/soapbox/features/status/components/detailed-status.tsx @@ -1,7 +1,6 @@ import classNames from 'classnames'; -import React from 'react'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { FormattedDate, FormattedMessage, injectIntl, WrappedComponentProps as IntlProps } from 'react-intl'; +import React, { useEffect, useRef, useState } from 'react'; +import { FormattedDate, FormattedMessage, useIntl } from 'react-intl'; import Icon from 'soapbox/components/icon'; import StatusMedia from 'soapbox/components/status-media'; @@ -17,13 +16,14 @@ 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 { +interface IDetailedStatus { status: StatusEntity, onOpenMedia: (media: ImmutableList, index: number) => void, onOpenVideo: (media: ImmutableList, start: number) => void, onToggleHidden: (status: StatusEntity) => void, measureHeight: boolean, - onHeightChange: () => void, + /** @deprecated Unused. */ + onHeightChange?: () => void, domain: string, compact: boolean, showMedia: boolean, @@ -31,171 +31,139 @@ interface IDetailedStatus extends IntlProps { onToggleMediaVisibility: () => void, } -interface IDetailedStatusState { - height: number | null, -} +const DetailedStatus: React.FC = ({ + status, + onToggleHidden, + onOpenCompareHistoryModal, + onToggleMediaVisibility, + measureHeight, + showMedia, + compact, +}) => { + const intl = useIntl(); -class DetailedStatus extends ImmutablePureComponent { + const node = useRef(null); + const [height, setHeight] = useState(); - state = { - height: null, + const handleExpandedToggle = () => { + onToggleHidden(status); }; - node: HTMLDivElement | null = null; + const handleOpenCompareHistoryModal = () => { + onOpenCompareHistoryModal(status); + }; - handleExpandedToggle = () => { - this.props.onToggleHidden(this.props.status); - } - - handleOpenCompareHistoryModal = () => { - this.props.onOpenCompareHistoryModal(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(); - } + useEffect(() => { + if (measureHeight && node.current) { + scheduleIdleTask(() => { + if (node.current) { + setHeight(Math.ceil(node.current.scrollHeight) + 1); + } + }); } - } + }, [node.current, height]); - setRef: React.RefCallback = c => { - this.node = c; - this._measureHeight(); - } - - 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; + const getActualStatus = () => { if (!status) return undefined; return status.reblog && typeof status.reblog === 'object' ? status.reblog : status; + }; + + const actualStatus = getActualStatus(); + if (!actualStatus) return null; + const { account } = actualStatus; + if (!account || typeof account !== 'object') return null; + + const outerStyle: React.CSSProperties = { boxSizing: 'border-box' }; + + let statusTypeIcon = null; + + if (measureHeight) { + outerStyle.height = `${height}px`; } - render() { - const status = this.getActualStatus(); - if (!status) return null; - const { account } = status; - if (!account || typeof account !== 'object') return null; + let quote; - const outerStyle: React.CSSProperties = { boxSizing: 'border-box' }; - const { compact } = this.props; - - let statusTypeIcon = null; - - if (this.props.measureHeight) { - outerStyle.height = `${this.state.height}px`; - } - - let quote; - - if (status.quote) { - if (status.pleroma.get('quote_visible', true) === false) { - quote = ( -
-

-
- ); - } else { - quote = ; - } - } - - if (status.visibility === 'direct') { - statusTypeIcon = ; - } else if (status.visibility === 'private') { - statusTypeIcon = ; - } - - return ( -
-
-
- -
- - {/* status.group && ( -
- Posted in {status.getIn(['group', 'title'])} -
- )*/} - - - - - - - - {quote} - - - - -
- {statusTypeIcon} - - - - - - - - - {status.edited_at && ( - <> - {' · '} -
- - - -
- - )} -
-
-
+ if (actualStatus.quote) { + if (actualStatus.pleroma.get('quote_visible', true) === false) { + quote = ( +
+

-
- ); + ); + } else { + quote = ; + } } -} + if (actualStatus.visibility === 'direct') { + statusTypeIcon = ; + } else if (actualStatus.visibility === 'private') { + statusTypeIcon = ; + } -export default injectIntl(DetailedStatus); + return ( +
+
+
+ +
+ + + + + + + + {quote} + + + + +
+ {statusTypeIcon} + + + + + + + + + {actualStatus.edited_at && ( + <> + {' · '} +
+ + + +
+ + )} +
+
+
+
+
+ ); +}; + +export default DetailedStatus;