Infinite scroll for followers/following lists
This commit is contained in:
		
							parent
							
								
									49b7896953
								
							
						
					
					
						commit
						dbfe1e4be6
					
				
					 9 changed files with 219 additions and 68 deletions
				
			
		| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
import api       from '../api'
 | 
			
		||||
import api, { getLinks } from '../api'
 | 
			
		||||
import Immutable from 'immutable';
 | 
			
		||||
 | 
			
		||||
export const ACCOUNT_SET_SELF = 'ACCOUNT_SET_SELF';
 | 
			
		||||
| 
						 | 
				
			
			@ -35,10 +35,18 @@ export const FOLLOWERS_FETCH_REQUEST = 'FOLLOWERS_FETCH_REQUEST';
 | 
			
		|||
export const FOLLOWERS_FETCH_SUCCESS = 'FOLLOWERS_FETCH_SUCCESS';
 | 
			
		||||
export const FOLLOWERS_FETCH_FAIL    = 'FOLLOWERS_FETCH_FAIL';
 | 
			
		||||
 | 
			
		||||
export const FOLLOWERS_EXPAND_REQUEST = 'FOLLOWERS_EXPAND_REQUEST';
 | 
			
		||||
export const FOLLOWERS_EXPAND_SUCCESS = 'FOLLOWERS_EXPAND_SUCCESS';
 | 
			
		||||
export const FOLLOWERS_EXPAND_FAIL    = 'FOLLOWERS_EXPAND_FAIL';
 | 
			
		||||
 | 
			
		||||
export const FOLLOWING_FETCH_REQUEST = 'FOLLOWING_FETCH_REQUEST';
 | 
			
		||||
export const FOLLOWING_FETCH_SUCCESS = 'FOLLOWING_FETCH_SUCCESS';
 | 
			
		||||
export const FOLLOWING_FETCH_FAIL    = 'FOLLOWING_FETCH_FAIL';
 | 
			
		||||
 | 
			
		||||
export const FOLLOWING_EXPAND_REQUEST = 'FOLLOWING_EXPAND_REQUEST';
 | 
			
		||||
export const FOLLOWING_EXPAND_SUCCESS = 'FOLLOWING_EXPAND_SUCCESS';
 | 
			
		||||
export const FOLLOWING_EXPAND_FAIL    = 'FOLLOWING_EXPAND_FAIL';
 | 
			
		||||
 | 
			
		||||
export const RELATIONSHIPS_FETCH_REQUEST = 'RELATIONSHIPS_FETCH_REQUEST';
 | 
			
		||||
export const RELATIONSHIPS_FETCH_SUCCESS = 'RELATIONSHIPS_FETCH_SUCCESS';
 | 
			
		||||
export const RELATIONSHIPS_FETCH_FAIL    = 'RELATIONSHIPS_FETCH_FAIL';
 | 
			
		||||
| 
						 | 
				
			
			@ -46,7 +54,7 @@ export const RELATIONSHIPS_FETCH_FAIL    = 'RELATIONSHIPS_FETCH_FAIL';
 | 
			
		|||
export function setAccountSelf(account) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_SET_SELF,
 | 
			
		||||
    account: account
 | 
			
		||||
    account
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -101,22 +109,22 @@ export function expandAccountTimeline(id) {
 | 
			
		|||
export function fetchAccountRequest(id) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_FETCH_REQUEST,
 | 
			
		||||
    id: id
 | 
			
		||||
    id
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function fetchAccountSuccess(account) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_FETCH_SUCCESS,
 | 
			
		||||
    account: account
 | 
			
		||||
    account
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function fetchAccountFail(id, error) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_FETCH_FAIL,
 | 
			
		||||
    id: id,
 | 
			
		||||
    error: error
 | 
			
		||||
    id,
 | 
			
		||||
    error
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -147,89 +155,89 @@ export function unfollowAccount(id) {
 | 
			
		|||
export function followAccountRequest(id) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_FOLLOW_REQUEST,
 | 
			
		||||
    id: id
 | 
			
		||||
    id
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function followAccountSuccess(relationship) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_FOLLOW_SUCCESS,
 | 
			
		||||
    relationship: relationship
 | 
			
		||||
    relationship
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function followAccountFail(error) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_FOLLOW_FAIL,
 | 
			
		||||
    error: error
 | 
			
		||||
    error
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function unfollowAccountRequest(id) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_UNFOLLOW_REQUEST,
 | 
			
		||||
    id: id
 | 
			
		||||
    id
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function unfollowAccountSuccess(relationship) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_UNFOLLOW_SUCCESS,
 | 
			
		||||
    relationship: relationship
 | 
			
		||||
    relationship
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function unfollowAccountFail(error) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_UNFOLLOW_FAIL,
 | 
			
		||||
    error: error
 | 
			
		||||
    error
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function fetchAccountTimelineRequest(id) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_TIMELINE_FETCH_REQUEST,
 | 
			
		||||
    id: id
 | 
			
		||||
    id
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function fetchAccountTimelineSuccess(id, statuses, replace) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_TIMELINE_FETCH_SUCCESS,
 | 
			
		||||
    id: id,
 | 
			
		||||
    statuses: statuses,
 | 
			
		||||
    replace: replace
 | 
			
		||||
    id,
 | 
			
		||||
    statuses,
 | 
			
		||||
    replace
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function fetchAccountTimelineFail(id, error) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_TIMELINE_FETCH_FAIL,
 | 
			
		||||
    id: id,
 | 
			
		||||
    error: error
 | 
			
		||||
    id,
 | 
			
		||||
    error
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function expandAccountTimelineRequest(id) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_TIMELINE_EXPAND_REQUEST,
 | 
			
		||||
    id: id
 | 
			
		||||
    id
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function expandAccountTimelineSuccess(id, statuses) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_TIMELINE_EXPAND_SUCCESS,
 | 
			
		||||
    id: id,
 | 
			
		||||
    statuses: statuses
 | 
			
		||||
    id,
 | 
			
		||||
    statuses
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function expandAccountTimelineFail(id, error) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_TIMELINE_EXPAND_FAIL,
 | 
			
		||||
    id: id,
 | 
			
		||||
    error: error
 | 
			
		||||
    id,
 | 
			
		||||
    error
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -260,42 +268,42 @@ export function unblockAccount(id) {
 | 
			
		|||
export function blockAccountRequest(id) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_BLOCK_REQUEST,
 | 
			
		||||
    id: id
 | 
			
		||||
    id
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function blockAccountSuccess(relationship) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_BLOCK_SUCCESS,
 | 
			
		||||
    relationship: relationship
 | 
			
		||||
    relationship
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function blockAccountFail(error) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_BLOCK_FAIL,
 | 
			
		||||
    error: error
 | 
			
		||||
    error
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function unblockAccountRequest(id) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_UNBLOCK_REQUEST,
 | 
			
		||||
    id: id
 | 
			
		||||
    id
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function unblockAccountSuccess(relationship) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_UNBLOCK_SUCCESS,
 | 
			
		||||
    relationship: relationship
 | 
			
		||||
    relationship
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function unblockAccountFail(error) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: ACCOUNT_UNBLOCK_FAIL,
 | 
			
		||||
    error: error
 | 
			
		||||
    error
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -304,7 +312,9 @@ export function fetchFollowers(id) {
 | 
			
		|||
    dispatch(fetchFollowersRequest(id));
 | 
			
		||||
 | 
			
		||||
    api(getState).get(`/api/v1/accounts/${id}/followers`).then(response => {
 | 
			
		||||
      dispatch(fetchFollowersSuccess(id, response.data));
 | 
			
		||||
      const prev = getLinks(response).refs.find(link => link.rel === 'prev').uri;
 | 
			
		||||
 | 
			
		||||
      dispatch(fetchFollowersSuccess(id, response.data, prev));
 | 
			
		||||
      dispatch(fetchRelationships(response.data.map(item => item.id)));
 | 
			
		||||
    }).catch(error => {
 | 
			
		||||
      dispatch(fetchFollowersFail(id, error));
 | 
			
		||||
| 
						 | 
				
			
			@ -315,23 +325,65 @@ export function fetchFollowers(id) {
 | 
			
		|||
export function fetchFollowersRequest(id) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOWERS_FETCH_REQUEST,
 | 
			
		||||
    id: id
 | 
			
		||||
    id
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function fetchFollowersSuccess(id, accounts) {
 | 
			
		||||
export function fetchFollowersSuccess(id, accounts, prev) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOWERS_FETCH_SUCCESS,
 | 
			
		||||
    id: id,
 | 
			
		||||
    accounts: accounts
 | 
			
		||||
    id,
 | 
			
		||||
    accounts,
 | 
			
		||||
    prev
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function fetchFollowersFail(id, error) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOWERS_FETCH_FAIL,
 | 
			
		||||
    id: id,
 | 
			
		||||
    error: error
 | 
			
		||||
    id,
 | 
			
		||||
    error
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function expandFollowers(id) {
 | 
			
		||||
  return (dispatch, getState) => {
 | 
			
		||||
    const url = getState().getIn(['user_lists', 'followers', id, 'prev']);
 | 
			
		||||
 | 
			
		||||
    dispatch(expandFollowersRequest(id));
 | 
			
		||||
 | 
			
		||||
    api(getState).get(url).then(response => {
 | 
			
		||||
      const prev = getLinks(response).refs.find(link => link.rel === 'prev').uri;
 | 
			
		||||
 | 
			
		||||
      dispatch(expandFollowersSuccess(id, response.data, prev));
 | 
			
		||||
      dispatch(fetchRelationships(response.data.map(item => item.id)));
 | 
			
		||||
    }).catch(error => {
 | 
			
		||||
      dispatch(expandFollowersFail(id, error));
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function expandFollowersRequest(id) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOWERS_EXPAND_REQUEST,
 | 
			
		||||
    id
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function expandFollowersSuccess(id, accounts, prev) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOWERS_EXPAND_SUCCESS,
 | 
			
		||||
    id,
 | 
			
		||||
    accounts,
 | 
			
		||||
    prev
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function expandFollowersFail(id, error) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOWERS_EXPAND_FAIL,
 | 
			
		||||
    id,
 | 
			
		||||
    error
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -351,23 +403,64 @@ export function fetchFollowing(id) {
 | 
			
		|||
export function fetchFollowingRequest(id) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOWING_FETCH_REQUEST,
 | 
			
		||||
    id: id
 | 
			
		||||
    id
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function fetchFollowingSuccess(id, accounts) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOWING_FETCH_SUCCESS,
 | 
			
		||||
    id: id,
 | 
			
		||||
    accounts: accounts
 | 
			
		||||
    id,
 | 
			
		||||
    accounts
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function fetchFollowingFail(id, error) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOWING_FETCH_FAIL,
 | 
			
		||||
    id: id,
 | 
			
		||||
    error: error
 | 
			
		||||
    id,
 | 
			
		||||
    error
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function expandFollowing(id) {
 | 
			
		||||
  return (dispatch, getState) => {
 | 
			
		||||
    const url = getState().getIn(['user_lists', 'following', id, 'prev']);
 | 
			
		||||
 | 
			
		||||
    dispatch(expandFollowingRequest(id));
 | 
			
		||||
 | 
			
		||||
    api(getState).get(url).then(response => {
 | 
			
		||||
      const prev = getLinks(response).refs.find(link => link.rel === 'prev').uri;
 | 
			
		||||
 | 
			
		||||
      dispatch(expandFollowingSuccess(id, response.data, prev));
 | 
			
		||||
      dispatch(fetchRelationships(response.data.map(item => item.id)));
 | 
			
		||||
    }).catch(error => {
 | 
			
		||||
      dispatch(expandFollowingFail(id, error));
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function expandFollowingRequest(id) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOWING_EXPAND_REQUEST,
 | 
			
		||||
    id
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function expandFollowingSuccess(id, accounts, prev) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOWING_EXPAND_SUCCESS,
 | 
			
		||||
    id,
 | 
			
		||||
    accounts,
 | 
			
		||||
    prev
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function expandFollowingFail(id, error) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: FOLLOWING_EXPAND_FAIL,
 | 
			
		||||
    id,
 | 
			
		||||
    error
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -386,20 +479,20 @@ export function fetchRelationships(account_ids) {
 | 
			
		|||
export function fetchRelationshipsRequest(ids) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: RELATIONSHIPS_FETCH_REQUEST,
 | 
			
		||||
    ids: ids
 | 
			
		||||
    ids
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function fetchRelationshipsSuccess(relationships) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: RELATIONSHIPS_FETCH_SUCCESS,
 | 
			
		||||
    relationships: relationships
 | 
			
		||||
    relationships
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function fetchRelationshipsFail(error) {
 | 
			
		||||
  return {
 | 
			
		||||
    type: RELATIONSHIPS_FETCH_FAIL,
 | 
			
		||||
    error: error
 | 
			
		||||
    error
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,9 @@
 | 
			
		|||
import axios from 'axios';
 | 
			
		||||
import LinkHeader from 'http-link-header';
 | 
			
		||||
 | 
			
		||||
export const getLinks = response => {
 | 
			
		||||
  return LinkHeader.parse(response.headers.link);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default getState => axios.create({
 | 
			
		||||
  headers: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,6 @@ const UploadForm = React.createClass({
 | 
			
		|||
  propTypes: {
 | 
			
		||||
    media: ImmutablePropTypes.list.isRequired,
 | 
			
		||||
    is_uploading: React.PropTypes.bool,
 | 
			
		||||
    onSelectFile: React.PropTypes.func.isRequired,
 | 
			
		||||
    onRemoveFile: React.PropTypes.func.isRequired
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,13 +1,16 @@
 | 
			
		|||
import { connect }            from 'react-redux';
 | 
			
		||||
import PureRenderMixin        from 'react-addons-pure-render-mixin';
 | 
			
		||||
import ImmutablePropTypes     from 'react-immutable-proptypes';
 | 
			
		||||
import LoadingIndicator       from '../../components/loading_indicator';
 | 
			
		||||
import { fetchFollowers }     from '../../actions/accounts';
 | 
			
		||||
import { ScrollContainer }    from 'react-router-scroll';
 | 
			
		||||
import AccountContainer       from './containers/account_container';
 | 
			
		||||
import { connect } from 'react-redux';
 | 
			
		||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
 | 
			
		||||
import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
			
		||||
import LoadingIndicator from '../../components/loading_indicator';
 | 
			
		||||
import {
 | 
			
		||||
  fetchFollowers,
 | 
			
		||||
  expandFollowers
 | 
			
		||||
} from '../../actions/accounts';
 | 
			
		||||
import { ScrollContainer } from 'react-router-scroll';
 | 
			
		||||
import AccountContainer from './containers/account_container';
 | 
			
		||||
 | 
			
		||||
const mapStateToProps = (state, props) => ({
 | 
			
		||||
  accountIds: state.getIn(['user_lists', 'followers', Number(props.params.accountId)])
 | 
			
		||||
  accountIds: state.getIn(['user_lists', 'followers', Number(props.params.accountId), 'items'])
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const Followers = React.createClass({
 | 
			
		||||
| 
						 | 
				
			
			@ -30,6 +33,14 @@ const Followers = React.createClass({
 | 
			
		|||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  handleScroll (e) {
 | 
			
		||||
    const { scrollTop, scrollHeight, clientHeight } = e.target;
 | 
			
		||||
 | 
			
		||||
    if (scrollTop === scrollHeight - clientHeight) {
 | 
			
		||||
      this.props.dispatch(expandFollowers(Number(this.props.params.accountId)));
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  render () {
 | 
			
		||||
    const { accountIds } = this.props;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -39,8 +50,10 @@ const Followers = React.createClass({
 | 
			
		|||
 | 
			
		||||
    return (
 | 
			
		||||
      <ScrollContainer scrollKey='followers'>
 | 
			
		||||
        <div className='scrollable'>
 | 
			
		||||
          {accountIds.map(id => <AccountContainer key={id} id={id} withNote={false} />)}
 | 
			
		||||
        <div className='scrollable' onScroll={this.handleScroll}>
 | 
			
		||||
          <div>
 | 
			
		||||
            {accountIds.map(id => <AccountContainer key={id} id={id} withNote={false} />)}
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </ScrollContainer>
 | 
			
		||||
    );
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,13 +1,16 @@
 | 
			
		|||
import { connect }            from 'react-redux';
 | 
			
		||||
import PureRenderMixin        from 'react-addons-pure-render-mixin';
 | 
			
		||||
import ImmutablePropTypes     from 'react-immutable-proptypes';
 | 
			
		||||
import LoadingIndicator       from '../../components/loading_indicator';
 | 
			
		||||
import { fetchFollowing }     from '../../actions/accounts';
 | 
			
		||||
import { ScrollContainer }    from 'react-router-scroll';
 | 
			
		||||
import AccountContainer       from '../followers/containers/account_container';
 | 
			
		||||
import { connect } from 'react-redux';
 | 
			
		||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
 | 
			
		||||
import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
			
		||||
import LoadingIndicator from '../../components/loading_indicator';
 | 
			
		||||
import {
 | 
			
		||||
  fetchFollowing,
 | 
			
		||||
  expandFollowing
 | 
			
		||||
} from '../../actions/accounts';
 | 
			
		||||
import { ScrollContainer } from 'react-router-scroll';
 | 
			
		||||
import AccountContainer from '../followers/containers/account_container';
 | 
			
		||||
 | 
			
		||||
const mapStateToProps = (state, props) => ({
 | 
			
		||||
  accountIds: state.getIn(['user_lists', 'following', Number(props.params.accountId)])
 | 
			
		||||
  accountIds: state.getIn(['user_lists', 'following', Number(props.params.accountId), 'items'])
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const Following = React.createClass({
 | 
			
		||||
| 
						 | 
				
			
			@ -30,6 +33,14 @@ const Following = React.createClass({
 | 
			
		|||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  handleScroll (e) {
 | 
			
		||||
    const { scrollTop, scrollHeight, clientHeight } = e.target;
 | 
			
		||||
 | 
			
		||||
    if (scrollTop === scrollHeight - clientHeight) {
 | 
			
		||||
      this.props.dispatch(expandFollowing(Number(this.props.params.accountId)));
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  render () {
 | 
			
		||||
    const { accountIds } = this.props;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -39,8 +50,10 @@ const Following = React.createClass({
 | 
			
		|||
 | 
			
		||||
    return (
 | 
			
		||||
      <ScrollContainer scrollKey='following'>
 | 
			
		||||
        <div className='scrollable'>
 | 
			
		||||
          {accountIds.map(id => <AccountContainer key={id} id={id} withNote={false} />)}
 | 
			
		||||
        <div className='scrollable' onScroll={this.handleScroll}>
 | 
			
		||||
          <div>
 | 
			
		||||
            {accountIds.map(id => <AccountContainer key={id} id={id} withNote={false} />)}
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </ScrollContainer>
 | 
			
		||||
    );
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,9 @@ import {
 | 
			
		|||
  ACCOUNT_SET_SELF,
 | 
			
		||||
  ACCOUNT_FETCH_SUCCESS,
 | 
			
		||||
  FOLLOWERS_FETCH_SUCCESS,
 | 
			
		||||
  FOLLOWERS_EXPAND_SUCCESS,
 | 
			
		||||
  FOLLOWING_FETCH_SUCCESS,
 | 
			
		||||
  FOLLOWING_EXPAND_SUCCESS,
 | 
			
		||||
  ACCOUNT_TIMELINE_FETCH_SUCCESS,
 | 
			
		||||
  ACCOUNT_TIMELINE_EXPAND_SUCCESS
 | 
			
		||||
} from '../actions/accounts';
 | 
			
		||||
| 
						 | 
				
			
			@ -65,7 +67,9 @@ export default function accounts(state = initialState, action) {
 | 
			
		|||
      return normalizeAccount(state, action.account);
 | 
			
		||||
    case SUGGESTIONS_FETCH_SUCCESS:
 | 
			
		||||
    case FOLLOWERS_FETCH_SUCCESS:
 | 
			
		||||
    case FOLLOWERS_EXPAND_SUCCESS:
 | 
			
		||||
    case FOLLOWING_FETCH_SUCCESS:
 | 
			
		||||
    case FOLLOWING_EXPAND_SUCCESS:
 | 
			
		||||
    case REBLOGS_FETCH_SUCCESS:
 | 
			
		||||
    case FAVOURITES_FETCH_SUCCESS:
 | 
			
		||||
    case COMPOSE_SUGGESTIONS_READY:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,8 @@
 | 
			
		|||
import {
 | 
			
		||||
  FOLLOWERS_FETCH_SUCCESS,
 | 
			
		||||
  FOLLOWING_FETCH_SUCCESS
 | 
			
		||||
  FOLLOWERS_EXPAND_SUCCESS,
 | 
			
		||||
  FOLLOWING_FETCH_SUCCESS,
 | 
			
		||||
  FOLLOWING_EXPAND_SUCCESS
 | 
			
		||||
} from '../actions/accounts';
 | 
			
		||||
import { SUGGESTIONS_FETCH_SUCCESS } from '../actions/suggestions';
 | 
			
		||||
import {
 | 
			
		||||
| 
						 | 
				
			
			@ -17,12 +19,29 @@ const initialState = Immutable.Map({
 | 
			
		|||
  favourited_by: Immutable.Map()
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const normalizeList = (state, type, id, accounts, prev) => {
 | 
			
		||||
  return state.setIn([type, id], Immutable.Map({
 | 
			
		||||
    prev,
 | 
			
		||||
    items: Immutable.List(accounts.map(item => item.id))
 | 
			
		||||
  }));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const appendToList = (state, type, id, accounts, prev) => {
 | 
			
		||||
  return state.updateIn([type, id], map => {
 | 
			
		||||
    return map.set('prev', prev).update('items', list => list.push(...accounts.map(item => item.id)));
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default function userLists(state = initialState, action) {
 | 
			
		||||
  switch(action.type) {
 | 
			
		||||
    case FOLLOWERS_FETCH_SUCCESS:
 | 
			
		||||
      return state.setIn(['followers', action.id], Immutable.List(action.accounts.map(item => item.id)));
 | 
			
		||||
      return normalizeList(state, 'followers', action.id, action.accounts, action.prev);
 | 
			
		||||
    case FOLLOWERS_EXPAND_SUCCESS:
 | 
			
		||||
      return appendToList(state, 'followers', action.id, action.accounts, action.prev);
 | 
			
		||||
    case FOLLOWING_FETCH_SUCCESS:
 | 
			
		||||
      return state.setIn(['following', action.id], Immutable.List(action.accounts.map(item => item.id)));
 | 
			
		||||
      return normalizeList(state, 'following', action.id, action.accounts, action.prev);
 | 
			
		||||
    case FOLLOWING_EXPAND_SUCCESS:
 | 
			
		||||
      return appendToList(state, 'following', action.id, action.accounts, action.prev);
 | 
			
		||||
    case SUGGESTIONS_FETCH_SUCCESS:
 | 
			
		||||
      return state.set('suggestions', Immutable.List(action.accounts.map(item => item.id)));
 | 
			
		||||
    case REBLOGS_FETCH_SUCCESS:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,6 +43,7 @@
 | 
			
		|||
  "dependencies": {
 | 
			
		||||
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
 | 
			
		||||
    "emojione": "^2.2.6",
 | 
			
		||||
    "http-link-header": "^0.5.0",
 | 
			
		||||
    "react-autosuggest": "^7.0.1",
 | 
			
		||||
    "react-decoration": "^1.4.0",
 | 
			
		||||
    "react-motion": "^0.4.5",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2399,6 +2399,10 @@ http-errors@~1.5.0:
 | 
			
		|||
    setprototypeof "1.0.1"
 | 
			
		||||
    statuses ">= 1.3.0 < 2"
 | 
			
		||||
 | 
			
		||||
http-link-header:
 | 
			
		||||
  version "0.5.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/http-link-header/-/http-link-header-0.5.0.tgz#68598d92c55d3dac7d3e6ae405142fecf7bd3303"
 | 
			
		||||
 | 
			
		||||
http-signature@~1.1.0:
 | 
			
		||||
  version "1.1.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue