Improve status reselect, do not display "load more" when no next link available

This commit is contained in:
Eugen Rochko 2017-02-22 16:30:09 +01:00
parent c77a54fe0a
commit c96fd24f48
5 changed files with 39 additions and 76 deletions

View File

@ -15,6 +15,7 @@ const StatusList = React.createClass({
trackScroll: React.PropTypes.bool, trackScroll: React.PropTypes.bool,
isLoading: React.PropTypes.bool, isLoading: React.PropTypes.bool,
isUnread: React.PropTypes.bool, isUnread: React.PropTypes.bool,
hasMore: React.PropTypes.bool,
prepend: React.PropTypes.node, prepend: React.PropTypes.node,
emptyMessage: React.PropTypes.node emptyMessage: React.PropTypes.node
}, },
@ -73,13 +74,13 @@ const StatusList = React.createClass({
}, },
render () { 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 loadMore = '';
let scrollableArea = ''; let scrollableArea = '';
let unread = ''; let unread = '';
if (!isLoading && statusIds.size > 0) { if (!isLoading && statusIds.size > 0 && hasMore) {
loadMore = <LoadMore onClick={this.handleLoadMore} />; loadMore = <LoadMore onClick={this.handleLoadMore} />;
} }

View File

@ -18,45 +18,12 @@ import { openMedia } from '../actions/modal';
import { createSelector } from 'reselect' import { createSelector } from 'reselect'
import { isMobile } from '../is_mobile' import { isMobile } from '../is_mobile'
const mapStateToProps = (state, props) => ({ const makeMapStateToProps = () => {
statusBase: state.getIn(['statuses', props.id]), const getStatus = makeGetStatus();
me: state.getIn(['meta', 'me'])
});
const makeMapStateToPropsInner = () => { const mapStateToProps = (state, props) => ({
const getStatus = (() => { status: getStatus(state, props.id),
return createSelector( me: state.getIn(['meta', 'me'])
[
(_, 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)
}); });
return mapStateToProps; return mapStateToProps;
@ -106,8 +73,4 @@ const mapDispatchToProps = (dispatch) => ({
}); });
export default connect(mapStateToProps, mapDispatchToProps)( export default connect(makeMapStateToProps, mapDispatchToProps)(Status);
connect(makeMapStateToPropsInner)(
connect(makeMapStateToPropsLast)(Status)
)
);

View File

@ -16,6 +16,7 @@ import Immutable from 'immutable';
const mapStateToProps = (state, props) => ({ const mapStateToProps = (state, props) => ({
statusIds: state.getIn(['timelines', 'accounts_timelines', Number(props.params.accountId), 'items'], Immutable.List()), statusIds: state.getIn(['timelines', 'accounts_timelines', Number(props.params.accountId), 'items'], Immutable.List()),
isLoading: state.getIn(['timelines', 'accounts_timelines', Number(props.params.accountId), 'isLoading']), 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']) me: state.getIn(['meta', 'me'])
}); });
@ -26,6 +27,7 @@ const AccountTimeline = React.createClass({
dispatch: React.PropTypes.func.isRequired, dispatch: React.PropTypes.func.isRequired,
statusIds: ImmutablePropTypes.list, statusIds: ImmutablePropTypes.list,
isLoading: React.PropTypes.bool, isLoading: React.PropTypes.bool,
hasMore: React.PropTypes.bool,
me: React.PropTypes.number.isRequired me: React.PropTypes.number.isRequired
}, },
@ -48,7 +50,7 @@ const AccountTimeline = React.createClass({
}, },
render () { render () {
const { statusIds, isLoading, me } = this.props; const { statusIds, isLoading, hasMore, me } = this.props;
if (!statusIds && isLoading) { if (!statusIds && isLoading) {
return ( return (
@ -66,6 +68,7 @@ const AccountTimeline = React.createClass({
prepend={<HeaderContainer accountId={this.props.params.accountId} />} prepend={<HeaderContainer accountId={this.props.params.accountId} />}
statusIds={statusIds} statusIds={statusIds}
isLoading={isLoading} isLoading={isLoading}
hasMore={hasMore}
me={me} me={me}
onScrollToBottom={this.handleScrollToBottom} onScrollToBottom={this.handleScrollToBottom}
/> />

View File

@ -40,7 +40,8 @@ const makeMapStateToProps = () => {
const mapStateToProps = (state, props) => ({ const mapStateToProps = (state, props) => ({
statusIds: getStatusIds(state, props), statusIds: getStatusIds(state, props),
isLoading: state.getIn(['timelines', props.type, 'isLoading'], true), 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; return mapStateToProps;

View File

@ -17,37 +17,32 @@ export const makeGetAccount = () => {
}); });
}; };
const getStatusBase = (state, id) => state.getIn(['statuses', id], null);
export const makeGetStatus = () => { export const makeGetStatus = () => {
return createSelector([getStatusBase, getStatuses, getAccounts], (base, statuses, accounts) => { return createSelector(
if (base === null) { [
return null; (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'); const getAlertsBase = state => state.get('alerts');