From 035c9741375f154efe989c5a441a0fa725c7aad3 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 9 May 2022 22:22:01 -0500 Subject: [PATCH] RemoteTimeline: convert to TSX --- app/soapbox/features/remote_timeline/index.js | 116 ------------------ .../features/remote_timeline/index.tsx | 94 ++++++++++++++ 2 files changed, 94 insertions(+), 116 deletions(-) delete mode 100644 app/soapbox/features/remote_timeline/index.js create mode 100644 app/soapbox/features/remote_timeline/index.tsx diff --git a/app/soapbox/features/remote_timeline/index.js b/app/soapbox/features/remote_timeline/index.js deleted file mode 100644 index a207498c6..000000000 --- a/app/soapbox/features/remote_timeline/index.js +++ /dev/null @@ -1,116 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; -import { connect } from 'react-redux'; -import { withRouter } from 'react-router-dom'; - -import { getSettings } from 'soapbox/actions/settings'; -import IconButton from 'soapbox/components/icon_button'; -import Column from 'soapbox/features/ui/components/column'; - -import { connectRemoteStream } from '../../actions/streaming'; -import { expandRemoteTimeline } from '../../actions/timelines'; -import StatusListContainer from '../ui/containers/status_list_container'; - -import PinnedHostsPicker from './components/pinned_hosts_picker'; - -const messages = defineMessages({ - title: { id: 'column.remote', defaultMessage: 'Federated timeline' }, -}); - -const mapStateToProps = (state, props) => { - const instance = props.params.instance; - const settings = getSettings(state); - const onlyMedia = settings.getIn(['remote', 'other', 'onlyMedia']); - - const timelineId = 'remote'; - - return { - timelineId, - onlyMedia, - hasUnread: state.getIn(['timelines', `${timelineId}${onlyMedia ? ':media' : ''}:${instance}`, 'unread']) > 0, - instance, - pinned: settings.getIn(['remote_timeline', 'pinnedHosts']).includes(instance), - }; -}; - -export default @connect(mapStateToProps) -@injectIntl -@withRouter -class RemoteTimeline extends React.PureComponent { - - static propTypes = { - dispatch: PropTypes.func.isRequired, - intl: PropTypes.object.isRequired, - hasUnread: PropTypes.bool, - onlyMedia: PropTypes.bool, - timelineId: PropTypes.string, - instance: PropTypes.string.isRequired, - pinned: PropTypes.bool, - history: PropTypes.object, - }; - - componentDidMount() { - const { dispatch, onlyMedia, instance } = this.props; - dispatch(expandRemoteTimeline(instance, { onlyMedia })); - this.disconnect = dispatch(connectRemoteStream(instance, { onlyMedia })); - } - - componentDidUpdate(prevProps) { - if (prevProps.onlyMedia !== this.props.onlyMedia) { - const { dispatch, onlyMedia, instance } = this.props; - this.disconnect(); - - dispatch(expandRemoteTimeline(instance, { onlyMedia })); - this.disconnect = dispatch(connectRemoteStream(instance, { onlyMedia })); - } - } - - componentWillUnmount() { - if (this.disconnect) { - this.disconnect(); - this.disconnect = null; - } - } - - handleCloseClick = e => { - this.props.history.push('/timeline/fediverse'); - } - - handleLoadMore = maxId => { - const { dispatch, onlyMedia, instance } = this.props; - dispatch(expandRemoteTimeline(instance, { maxId, onlyMedia })); - } - - render() { - const { intl, onlyMedia, timelineId, instance, pinned } = this.props; - - return ( - - - {!pinned &&
- - -
} - - } - divideType='space' - /> -
- ); - } - -} diff --git a/app/soapbox/features/remote_timeline/index.tsx b/app/soapbox/features/remote_timeline/index.tsx new file mode 100644 index 000000000..d3560f4a6 --- /dev/null +++ b/app/soapbox/features/remote_timeline/index.tsx @@ -0,0 +1,94 @@ +import React, { useEffect, useRef } from 'react'; +import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; +import { useHistory } from 'react-router-dom'; + +import IconButton from 'soapbox/components/icon_button'; +import Column from 'soapbox/features/ui/components/column'; +import { useAppDispatch, useSettings } from 'soapbox/hooks'; + +import { connectRemoteStream } from '../../actions/streaming'; +import { expandRemoteTimeline } from '../../actions/timelines'; +import StatusListContainer from '../ui/containers/status_list_container'; + +import PinnedHostsPicker from './components/pinned_hosts_picker'; + +const messages = defineMessages({ + title: { id: 'column.remote', defaultMessage: 'Federated timeline' }, +}); + +interface IRemoteTimeline { + params?: { + instance?: string, + } +} + +/** View statuses from a remote instance. */ +const RemoteTimeline: React.FC = ({ params }) => { + const intl = useIntl(); + const history = useHistory(); + const dispatch = useAppDispatch(); + + const instance = params?.instance; + const settings = useSettings(); + + const stream = useRef(null); + + const timelineId = 'remote'; + const onlyMedia = !!settings.getIn(['remote', 'other', 'onlyMedia']); + + const pinned: boolean = (settings.getIn(['remote_timeline', 'pinnedHosts']) as any).includes(instance); + + const disconnect = () => { + if (stream.current) { + stream.current(); + } + }; + + useEffect(() => { + disconnect(); + dispatch(expandRemoteTimeline(instance, { onlyMedia, maxId: undefined })); + stream.current = dispatch(connectRemoteStream(instance, { onlyMedia })); + + return () => { + disconnect(); + stream.current = null; + }; + }, [onlyMedia]); + + const handleCloseClick: React.MouseEventHandler = () => { + history.push('/timeline/fediverse'); + }; + + const handleLoadMore = (maxId: string) => { + dispatch(expandRemoteTimeline(instance, { maxId, onlyMedia })); + }; + + return ( + + {instance && } + {!pinned &&
+ + +
} + + } + divideType='space' + /> +
+ ); +}; + +export default RemoteTimeline;