diff --git a/app/assets/javascripts/components/components/status_list.jsx b/app/assets/javascripts/components/components/status_list.jsx index 6c71a31e8..345944e4d 100644 --- a/app/assets/javascripts/components/components/status_list.jsx +++ b/app/assets/javascripts/components/components/status_list.jsx @@ -15,6 +15,7 @@ const StatusList = React.createClass({ trackScroll: React.PropTypes.bool, isLoading: React.PropTypes.bool, isUnread: React.PropTypes.bool, + hasMore: React.PropTypes.bool, prepend: React.PropTypes.node, emptyMessage: React.PropTypes.node }, @@ -73,13 +74,13 @@ const StatusList = React.createClass({ }, render () { - const { statusIds, onScrollToBottom, trackScroll, isLoading, isUnread, prepend, emptyMessage } = this.props; + const { statusIds, onScrollToBottom, trackScroll, isLoading, isUnread, hasMore, prepend, emptyMessage } = this.props; let loadMore = ''; let scrollableArea = ''; let unread = ''; - if (!isLoading && statusIds.size > 0) { + if (!isLoading && statusIds.size > 0 && hasMore) { loadMore = ; } diff --git a/app/assets/javascripts/components/containers/status_container.jsx b/app/assets/javascripts/components/containers/status_container.jsx index fc096a375..81265bc50 100644 --- a/app/assets/javascripts/components/containers/status_container.jsx +++ b/app/assets/javascripts/components/containers/status_container.jsx @@ -18,45 +18,12 @@ import { openMedia } from '../actions/modal'; import { createSelector } from 'reselect' import { isMobile } from '../is_mobile' -const mapStateToProps = (state, props) => ({ - statusBase: state.getIn(['statuses', props.id]), - me: state.getIn(['meta', 'me']) -}); +const makeMapStateToProps = () => { + const getStatus = makeGetStatus(); -const makeMapStateToPropsInner = () => { - const getStatus = (() => { - return createSelector( - [ - (_, base) => base, - (state, base) => (base ? state.getIn(['accounts', base.get('account')]) : null), - (state, base) => (base ? state.getIn(['statuses', base.get('reblog')], null) : null) - ], - - (base, account, reblog) => (base ? base.set('account', account).set('reblog', reblog) : null) - ); - })(); - - const mapStateToProps = (state, { statusBase }) => ({ - status: getStatus(state, statusBase) - }); - - return mapStateToProps; -}; - -const makeMapStateToPropsLast = () => { - const getStatus = (() => { - return createSelector( - [ - (_, status) => status, - (state, status) => (status ? state.getIn(['accounts', status.getIn(['reblog', 'account'])], null) : null) - ], - - (status, reblogAccount) => (status && status.get('reblog') ? status.setIn(['reblog', 'account'], reblogAccount) : status) - ); - })(); - - const mapStateToProps = (state, { status }) => ({ - status: getStatus(state, status) + const mapStateToProps = (state, props) => ({ + status: getStatus(state, props.id), + me: state.getIn(['meta', 'me']) }); return mapStateToProps; @@ -106,8 +73,4 @@ const mapDispatchToProps = (dispatch) => ({ }); -export default connect(mapStateToProps, mapDispatchToProps)( - connect(makeMapStateToPropsInner)( - connect(makeMapStateToPropsLast)(Status) - ) -); +export default connect(makeMapStateToProps, mapDispatchToProps)(Status); diff --git a/app/assets/javascripts/components/features/account_timeline/index.jsx b/app/assets/javascripts/components/features/account_timeline/index.jsx index 349510295..f92e1b49c 100644 --- a/app/assets/javascripts/components/features/account_timeline/index.jsx +++ b/app/assets/javascripts/components/features/account_timeline/index.jsx @@ -16,6 +16,7 @@ import Immutable from 'immutable'; const mapStateToProps = (state, props) => ({ statusIds: state.getIn(['timelines', 'accounts_timelines', Number(props.params.accountId), 'items'], Immutable.List()), isLoading: state.getIn(['timelines', 'accounts_timelines', Number(props.params.accountId), 'isLoading']), + hasMore: !!state.getIn(['timelines', 'accounts_timelines', Number(props.params.accountId), 'next']), me: state.getIn(['meta', 'me']) }); @@ -26,6 +27,7 @@ const AccountTimeline = React.createClass({ dispatch: React.PropTypes.func.isRequired, statusIds: ImmutablePropTypes.list, isLoading: React.PropTypes.bool, + hasMore: React.PropTypes.bool, me: React.PropTypes.number.isRequired }, @@ -48,7 +50,7 @@ const AccountTimeline = React.createClass({ }, render () { - const { statusIds, isLoading, me } = this.props; + const { statusIds, isLoading, hasMore, me } = this.props; if (!statusIds && isLoading) { return ( @@ -66,6 +68,7 @@ const AccountTimeline = React.createClass({ prepend={} statusIds={statusIds} isLoading={isLoading} + hasMore={hasMore} me={me} onScrollToBottom={this.handleScrollToBottom} /> diff --git a/app/assets/javascripts/components/features/ui/containers/status_list_container.jsx b/app/assets/javascripts/components/features/ui/containers/status_list_container.jsx index bb6df1133..f249240d8 100644 --- a/app/assets/javascripts/components/features/ui/containers/status_list_container.jsx +++ b/app/assets/javascripts/components/features/ui/containers/status_list_container.jsx @@ -40,7 +40,8 @@ const makeMapStateToProps = () => { const mapStateToProps = (state, props) => ({ statusIds: getStatusIds(state, props), isLoading: state.getIn(['timelines', props.type, 'isLoading'], true), - isUnread: state.getIn(['timelines', props.type, 'unread']) > 0 + isUnread: state.getIn(['timelines', props.type, 'unread']) > 0, + hasMore: !!state.getIn(['timelines', props.type, 'next']) }); return mapStateToProps; diff --git a/app/assets/javascripts/components/selectors/index.jsx b/app/assets/javascripts/components/selectors/index.jsx index 20debe604..faa7f92d0 100644 --- a/app/assets/javascripts/components/selectors/index.jsx +++ b/app/assets/javascripts/components/selectors/index.jsx @@ -17,37 +17,32 @@ export const makeGetAccount = () => { }); }; -const getStatusBase = (state, id) => state.getIn(['statuses', id], null); - export const makeGetStatus = () => { - return createSelector([getStatusBase, getStatuses, getAccounts], (base, statuses, accounts) => { - if (base === null) { - return null; + return createSelector( + [ + (state, id) => state.getIn(['statuses', id]), + (state, id) => state.getIn(['statuses', state.getIn(['statuses', id, 'reblog'])]), + (state, id) => state.getIn(['accounts', state.getIn(['statuses', id, 'account'])]), + (state, id) => state.getIn(['accounts', state.getIn(['statuses', state.getIn(['statuses', id, 'reblog']), 'account'])]), + ], + + (statusBase, statusReblog, accountBase, accountReblog) => { + if (!statusBase) { + return null; + } + + if (statusReblog) { + statusReblog = statusReblog.set('account', accountReblog); + } else { + statusReblog = null; + } + + return statusBase.withMutations(map => { + map.set('reblog', statusReblog); + map.set('account', accountBase); + }); } - - return assembleStatus(base.get('id'), statuses, accounts); - }); -}; - -const assembleStatus = (id, statuses, accounts) => { - let status = statuses.get(id, null); - let reblog = null; - - if (status === null) { - return null; - } - - if (status.get('reblog', null) !== null) { - reblog = statuses.get(status.get('reblog'), null); - - if (reblog !== null) { - reblog = reblog.set('account', accounts.get(reblog.get('account'))); - } else { - return null; - } - } - - return status.set('reblog', reblog).set('account', accounts.get(status.get('account'))); + ); }; const getAlertsBase = state => state.get('alerts');