From 44a7d87cb1f5df953b6c14c16c59e2e4ead1bcb9 Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Mon, 20 Feb 2023 03:20:59 +0100 Subject: Rename JSX files with proper `.jsx` extension (#23733) --- .../mastodon/features/account_timeline/index.jsx | 208 +++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 app/javascript/mastodon/features/account_timeline/index.jsx (limited to 'app/javascript/mastodon/features/account_timeline/index.jsx') diff --git a/app/javascript/mastodon/features/account_timeline/index.jsx b/app/javascript/mastodon/features/account_timeline/index.jsx new file mode 100644 index 000000000..337977fde --- /dev/null +++ b/app/javascript/mastodon/features/account_timeline/index.jsx @@ -0,0 +1,208 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import PropTypes from 'prop-types'; +import { lookupAccount, fetchAccount } from '../../actions/accounts'; +import { expandAccountFeaturedTimeline, expandAccountTimeline } from '../../actions/timelines'; +import StatusList from '../../components/status_list'; +import LoadingIndicator from '../../components/loading_indicator'; +import Column from '../ui/components/column'; +import HeaderContainer from './containers/header_container'; +import ColumnBackButton from '../../components/column_back_button'; +import { List as ImmutableList } from 'immutable'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { FormattedMessage } from 'react-intl'; +import MissingIndicator from 'mastodon/components/missing_indicator'; +import TimelineHint from 'mastodon/components/timeline_hint'; +import { me } from 'mastodon/initial_state'; +import { connectTimeline, disconnectTimeline } from 'mastodon/actions/timelines'; +import LimitedAccountHint from './components/limited_account_hint'; +import { getAccountHidden } from 'mastodon/selectors'; +import { fetchFeaturedTags } from '../../actions/featured_tags'; +import { normalizeForLookup } from 'mastodon/reducers/accounts_map'; + +const emptyList = ImmutableList(); + +const mapStateToProps = (state, { params: { acct, id, tagged }, withReplies = false }) => { + const accountId = id || state.getIn(['accounts_map', normalizeForLookup(acct)]); + + if (accountId === null) { + return { + isLoading: false, + isAccount: false, + statusIds: emptyList, + }; + } else if (!accountId) { + return { + isLoading: true, + statusIds: emptyList, + }; + } + + const path = withReplies ? `${accountId}:with_replies` : `${accountId}${tagged ? `:${tagged}` : ''}`; + + return { + accountId, + remote: !!(state.getIn(['accounts', accountId, 'acct']) !== state.getIn(['accounts', accountId, 'username'])), + remoteUrl: state.getIn(['accounts', accountId, 'url']), + isAccount: !!state.getIn(['accounts', accountId]), + statusIds: state.getIn(['timelines', `account:${path}`, 'items'], emptyList), + featuredStatusIds: withReplies ? ImmutableList() : state.getIn(['timelines', `account:${accountId}:pinned${tagged ? `:${tagged}` : ''}`, 'items'], emptyList), + isLoading: state.getIn(['timelines', `account:${path}`, 'isLoading']), + hasMore: state.getIn(['timelines', `account:${path}`, 'hasMore']), + suspended: state.getIn(['accounts', accountId, 'suspended'], false), + hidden: getAccountHidden(state, accountId), + blockedBy: state.getIn(['relationships', accountId, 'blocked_by'], false), + }; +}; + +const RemoteHint = ({ url }) => ( + } /> +); + +RemoteHint.propTypes = { + url: PropTypes.string.isRequired, +}; + +export default @connect(mapStateToProps) +class AccountTimeline extends ImmutablePureComponent { + + static propTypes = { + params: PropTypes.shape({ + acct: PropTypes.string, + id: PropTypes.string, + tagged: PropTypes.string, + }).isRequired, + accountId: PropTypes.string, + dispatch: PropTypes.func.isRequired, + statusIds: ImmutablePropTypes.list, + featuredStatusIds: ImmutablePropTypes.list, + isLoading: PropTypes.bool, + hasMore: PropTypes.bool, + withReplies: PropTypes.bool, + blockedBy: PropTypes.bool, + isAccount: PropTypes.bool, + suspended: PropTypes.bool, + hidden: PropTypes.bool, + remote: PropTypes.bool, + remoteUrl: PropTypes.string, + multiColumn: PropTypes.bool, + }; + + _load () { + const { accountId, withReplies, params: { tagged }, dispatch } = this.props; + + dispatch(fetchAccount(accountId)); + + if (!withReplies) { + dispatch(expandAccountFeaturedTimeline(accountId, { tagged })); + } + + dispatch(fetchFeaturedTags(accountId)); + dispatch(expandAccountTimeline(accountId, { withReplies, tagged })); + + if (accountId === me) { + dispatch(connectTimeline(`account:${me}`)); + } + } + + componentDidMount () { + const { params: { acct }, accountId, dispatch } = this.props; + + if (accountId) { + this._load(); + } else { + dispatch(lookupAccount(acct)); + } + } + + componentDidUpdate (prevProps) { + const { params: { acct, tagged }, accountId, withReplies, dispatch } = this.props; + + if (prevProps.accountId !== accountId && accountId) { + this._load(); + } else if (prevProps.params.acct !== acct) { + dispatch(lookupAccount(acct)); + } else if (prevProps.params.tagged !== tagged) { + if (!withReplies) { + dispatch(expandAccountFeaturedTimeline(accountId, { tagged })); + } + dispatch(expandAccountTimeline(accountId, { withReplies, tagged })); + } + + if (prevProps.accountId === me && accountId !== me) { + dispatch(disconnectTimeline(`account:${me}`)); + } + } + + componentWillUnmount () { + const { dispatch, accountId } = this.props; + + if (accountId === me) { + dispatch(disconnectTimeline(`account:${me}`)); + } + } + + handleLoadMore = maxId => { + this.props.dispatch(expandAccountTimeline(this.props.accountId, { maxId, withReplies: this.props.withReplies, tagged: this.props.params.tagged })); + }; + + render () { + const { accountId, statusIds, featuredStatusIds, isLoading, hasMore, blockedBy, suspended, isAccount, hidden, multiColumn, remote, remoteUrl } = this.props; + + if (isLoading && statusIds.isEmpty()) { + return ( + + + + ); + } else if (!isLoading && !isAccount) { + return ( + + + + + ); + } + + let emptyMessage; + + const forceEmptyState = suspended || blockedBy || hidden; + + if (suspended) { + emptyMessage = ; + } else if (hidden) { + emptyMessage = ; + } else if (blockedBy) { + emptyMessage = ; + } else if (remote && statusIds.isEmpty()) { + emptyMessage = ; + } else { + emptyMessage = ; + } + + const remoteMessage = remote ? : null; + + return ( + + + + } + alwaysPrepend + append={remoteMessage} + scrollKey='account_timeline' + statusIds={forceEmptyState ? emptyList : statusIds} + featuredStatusIds={featuredStatusIds} + isLoading={isLoading} + hasMore={!forceEmptyState && hasMore} + onLoadMore={this.handleLoadMore} + emptyMessage={emptyMessage} + bindToDocument={!multiColumn} + timelineId='account' + /> + + ); + } + +} -- cgit