import React from 'react'; import PropTypes from 'prop-types'; import { injectIntl } from 'react-intl'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import ReactSwipeableViews from 'react-swipeable-views'; import { links, getIndex, getLink } from './tabs_bar'; import BundleContainer from '../containers/bundle_container'; import ColumnLoading from './column_loading'; import BundleColumnError from './bundle_column_error'; import { Compose, Notifications, HomeTimeline, CommunityTimeline, PublicTimeline, HashtagTimeline, FavouritedStatuses } from '../../ui/util/async-components'; import detectPassiveEvents from 'detect-passive-events'; import { scrollRight } from '../../../scroll'; const componentMap = { 'COMPOSE': Compose, 'HOME': HomeTimeline, 'NOTIFICATIONS': Notifications, 'PUBLIC': PublicTimeline, 'COMMUNITY': CommunityTimeline, 'HASHTAG': HashtagTimeline, 'FAVOURITES': FavouritedStatuses, }; @component => injectIntl(component, { withRef: true }) export default class ColumnsArea extends ImmutablePureComponent { static contextTypes = { router: PropTypes.object.isRequired, }; static propTypes = { intl: PropTypes.object.isRequired, columns: ImmutablePropTypes.list.isRequired, singleColumn: PropTypes.bool, children: PropTypes.node, }; state = { shouldAnimate: false, } componentWillReceiveProps() { this.setState({ shouldAnimate: false }); } componentDidMount() { if (!this.props.singleColumn) { this.node.addEventListener('wheel', this.handleWheel, detectPassiveEvents ? { passive: true } : false); } this.lastIndex = getIndex(this.context.router.history.location.pathname); this.setState({ shouldAnimate: true }); } componentWillUpdate(nextProps) { if (this.props.singleColumn !== nextProps.singleColumn && nextProps.singleColumn) { this.node.removeEventListener('wheel', this.handleWheel); } } componentDidUpdate(prevProps) { if (this.props.singleColumn !== prevProps.singleColumn && !this.props.singleColumn) { this.node.addEventListener('wheel', this.handleWheel, detectPassiveEvents ? { passive: true } : false); } this.lastIndex = getIndex(this.context.router.history.location.pathname); this.setState({ shouldAnimate: true }); } componentWillUnmount () { if (!this.props.singleColumn) { this.node.removeEventListener('wheel', this.handleWheel); } } handleChildrenContentChange() { if (!this.props.singleColumn) { scrollRight(this.node, this.node.scrollWidth - window.innerWidth); } } handleSwipe = (index) => { this.pendingIndex = index; const nextLinkTranslationId = links[index].props['data-preview-title-id']; const currentLinkSelector = '.tabs-bar__link.active'; const nextLinkSelector = `.tabs-bar__link[data-preview-title-id="${nextLinkTranslationId}"]`; // HACK: Remove the active class from the current link and set it to the next one // React-router does this for us, but too late, feeling laggy. document.querySelector(currentLinkSelector).classList.remove('active'); document.querySelector(nextLinkSelector).classList.add('active'); } handleAnimationEnd = () => { if (typeof this.pendingIndex === 'number') { this.context.router.history.push(getLink(this.pendingIndex)); this.pendingIndex = null; } } handleWheel = () => { if (typeof this._interruptScrollAnimation !== 'function') { return; } this._interruptScrollAnimation(); } setRef = (node) => { this.node = node; } renderView = (link, index) => { const columnIndex = getIndex(this.context.router.history.location.pathname); const title = this.props.intl.formatMessage({ id: link.props['data-preview-title-id'] }); const icon = link.props['data-preview-icon']; const view = (index === columnIndex) ? React.cloneElement(this.props.children) : ; return (
{view}
); } renderLoading = () => { return ; } renderError = (props) => { return ; } render () { const { columns, children, singleColumn } = this.props; const { shouldAnimate } = this.state; const columnIndex = getIndex(this.context.router.history.location.pathname); this.pendingIndex = null; if (singleColumn) { return columnIndex !== -1 ? ( {links.map(this.renderView)} ) :
{children}
; } return (
{columns.map(column => { const params = column.get('params', null) === null ? null : column.get('params').toJS(); return ( {SpecificComponent => } ); })} {React.Children.map(children, child => React.cloneElement(child, { multiColumn: true }))}
); } }