179 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			179 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
import React from 'react';
 | 
						|
import { connect } from 'react-redux';
 | 
						|
import { defineMessages, injectIntl } from 'react-intl';
 | 
						|
import PropTypes from 'prop-types';
 | 
						|
import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
						|
import Column from 'flavours/glitch/components/column';
 | 
						|
import ColumnHeader from 'flavours/glitch/components/column_header';
 | 
						|
import { addColumn, removeColumn, moveColumn, changeColumnParams } from 'flavours/glitch/actions/columns';
 | 
						|
import { fetchDirectory, expandDirectory } from 'flavours/glitch/actions/directory';
 | 
						|
import { List as ImmutableList } from 'immutable';
 | 
						|
import AccountCard from './components/account_card';
 | 
						|
import RadioButton from 'flavours/glitch/components/radio_button';
 | 
						|
import LoadMore from 'flavours/glitch/components/load_more';
 | 
						|
import ScrollContainer from 'flavours/glitch/containers/scroll_container';
 | 
						|
import LoadingIndicator from 'flavours/glitch/components/loading_indicator';
 | 
						|
import { Helmet } from 'react-helmet';
 | 
						|
 | 
						|
const messages = defineMessages({
 | 
						|
  title: { id: 'column.directory', defaultMessage: 'Browse profiles' },
 | 
						|
  recentlyActive: { id: 'directory.recently_active', defaultMessage: 'Recently active' },
 | 
						|
  newArrivals: { id: 'directory.new_arrivals', defaultMessage: 'New arrivals' },
 | 
						|
  local: { id: 'directory.local', defaultMessage: 'From {domain} only' },
 | 
						|
  federated: { id: 'directory.federated', defaultMessage: 'From known fediverse' },
 | 
						|
});
 | 
						|
 | 
						|
const mapStateToProps = state => ({
 | 
						|
  accountIds: state.getIn(['user_lists', 'directory', 'items'], ImmutableList()),
 | 
						|
  isLoading: state.getIn(['user_lists', 'directory', 'isLoading'], true),
 | 
						|
  domain: state.getIn(['meta', 'domain']),
 | 
						|
});
 | 
						|
 | 
						|
export default @connect(mapStateToProps)
 | 
						|
@injectIntl
 | 
						|
class Directory extends React.PureComponent {
 | 
						|
 | 
						|
  static contextTypes = {
 | 
						|
    router: PropTypes.object,
 | 
						|
  };
 | 
						|
 | 
						|
  static propTypes = {
 | 
						|
    isLoading: PropTypes.bool,
 | 
						|
    accountIds: ImmutablePropTypes.list.isRequired,
 | 
						|
    dispatch: PropTypes.func.isRequired,
 | 
						|
    columnId: PropTypes.string,
 | 
						|
    intl: PropTypes.object.isRequired,
 | 
						|
    multiColumn: PropTypes.bool,
 | 
						|
    domain: PropTypes.string.isRequired,
 | 
						|
    params: PropTypes.shape({
 | 
						|
      order: PropTypes.string,
 | 
						|
      local: PropTypes.bool,
 | 
						|
    }),
 | 
						|
  };
 | 
						|
 | 
						|
  state = {
 | 
						|
    order: null,
 | 
						|
    local: null,
 | 
						|
  };
 | 
						|
 | 
						|
  handlePin = () => {
 | 
						|
    const { columnId, dispatch } = this.props;
 | 
						|
 | 
						|
    if (columnId) {
 | 
						|
      dispatch(removeColumn(columnId));
 | 
						|
    } else {
 | 
						|
      dispatch(addColumn('DIRECTORY', this.getParams(this.props, this.state)));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  getParams = (props, state) => ({
 | 
						|
    order: state.order === null ? (props.params.order || 'active') : state.order,
 | 
						|
    local: state.local === null ? (props.params.local || false) : state.local,
 | 
						|
  });
 | 
						|
 | 
						|
  handleMove = dir => {
 | 
						|
    const { columnId, dispatch } = this.props;
 | 
						|
    dispatch(moveColumn(columnId, dir));
 | 
						|
  }
 | 
						|
 | 
						|
  handleHeaderClick = () => {
 | 
						|
    this.column.scrollTop();
 | 
						|
  }
 | 
						|
 | 
						|
  componentDidMount () {
 | 
						|
    const { dispatch } = this.props;
 | 
						|
    dispatch(fetchDirectory(this.getParams(this.props, this.state)));
 | 
						|
  }
 | 
						|
 | 
						|
  componentDidUpdate (prevProps, prevState) {
 | 
						|
    const { dispatch } = this.props;
 | 
						|
    const paramsOld = this.getParams(prevProps, prevState);
 | 
						|
    const paramsNew = this.getParams(this.props, this.state);
 | 
						|
 | 
						|
    if (paramsOld.order !== paramsNew.order || paramsOld.local !== paramsNew.local) {
 | 
						|
      dispatch(fetchDirectory(paramsNew));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  setRef = c => {
 | 
						|
    this.column = c;
 | 
						|
  }
 | 
						|
 | 
						|
  handleChangeOrder = e => {
 | 
						|
    const { dispatch, columnId } = this.props;
 | 
						|
 | 
						|
    if (columnId) {
 | 
						|
      dispatch(changeColumnParams(columnId, ['order'], e.target.value));
 | 
						|
    } else {
 | 
						|
      this.setState({ order: e.target.value });
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  handleChangeLocal = e => {
 | 
						|
    const { dispatch, columnId } = this.props;
 | 
						|
 | 
						|
    if (columnId) {
 | 
						|
      dispatch(changeColumnParams(columnId, ['local'], e.target.value === '1'));
 | 
						|
    } else {
 | 
						|
      this.setState({ local: e.target.value === '1' });
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  handleLoadMore = () => {
 | 
						|
    const { dispatch } = this.props;
 | 
						|
    dispatch(expandDirectory(this.getParams(this.props, this.state)));
 | 
						|
  }
 | 
						|
 | 
						|
  render () {
 | 
						|
    const { isLoading, accountIds, intl, columnId, multiColumn, domain } = this.props;
 | 
						|
    const { order, local }  = this.getParams(this.props, this.state);
 | 
						|
    const pinned = !!columnId;
 | 
						|
 | 
						|
    const scrollableArea = (
 | 
						|
      <div className='scrollable'>
 | 
						|
        <div className='filter-form'>
 | 
						|
          <div className='filter-form__column' role='group'>
 | 
						|
            <RadioButton name='order' value='active' label={intl.formatMessage(messages.recentlyActive)} checked={order === 'active'} onChange={this.handleChangeOrder} />
 | 
						|
            <RadioButton name='order' value='new' label={intl.formatMessage(messages.newArrivals)} checked={order === 'new'} onChange={this.handleChangeOrder} />
 | 
						|
          </div>
 | 
						|
 | 
						|
          <div className='filter-form__column' role='group'>
 | 
						|
            <RadioButton name='local' value='1' label={intl.formatMessage(messages.local, { domain })} checked={local} onChange={this.handleChangeLocal} />
 | 
						|
            <RadioButton name='local' value='0' label={intl.formatMessage(messages.federated)} checked={!local} onChange={this.handleChangeLocal} />
 | 
						|
          </div>
 | 
						|
        </div>
 | 
						|
 | 
						|
        <div className='directory__list'>
 | 
						|
          {isLoading ? <LoadingIndicator /> : accountIds.map(accountId => (
 | 
						|
            <AccountCard id={accountId} key={accountId} />
 | 
						|
          ))}
 | 
						|
        </div>
 | 
						|
 | 
						|
        <LoadMore onClick={this.handleLoadMore} visible={!isLoading} />
 | 
						|
      </div>
 | 
						|
    );
 | 
						|
 | 
						|
    return (
 | 
						|
      <Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
 | 
						|
        <ColumnHeader
 | 
						|
          icon='address-book-o'
 | 
						|
          title={intl.formatMessage(messages.title)}
 | 
						|
          onPin={this.handlePin}
 | 
						|
          onMove={this.handleMove}
 | 
						|
          onClick={this.handleHeaderClick}
 | 
						|
          pinned={pinned}
 | 
						|
          multiColumn={multiColumn}
 | 
						|
        />
 | 
						|
 | 
						|
        {multiColumn && !pinned ? <ScrollContainer scrollKey='directory'>{scrollableArea}</ScrollContainer> : scrollableArea}
 | 
						|
 | 
						|
        <Helmet>
 | 
						|
          <title>{intl.formatMessage(messages.title)}</title>
 | 
						|
          <meta name='robots' content='noindex' />
 | 
						|
        </Helmet>
 | 
						|
      </Column>
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
}
 |