Fix load more feature on the Account media gallery (#3293)

* Add load more button for large screens
* Fix `next` state value on the first loading
* Don't load if `isLoading || !hasMore`
* Start load on near the bottom
master
unarist 8 years ago committed by Eugen Rochko
parent 3b59f9c6c2
commit 807c192fcf
  1. 26
      app/javascript/mastodon/features/account_gallery/index.js
  2. 6
      app/javascript/mastodon/reducers/timelines.js
  3. 1
      app/javascript/styles/components.scss

@ -17,6 +17,7 @@ import MediaItem from './components/media_item';
import HeaderContainer from '../account_timeline/containers/header_container'; import HeaderContainer from '../account_timeline/containers/header_container';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import { ScrollContainer } from 'react-router-scroll'; import { ScrollContainer } from 'react-router-scroll';
import LoadMore from '../../components/load_more';
const mapStateToProps = (state, props) => ({ const mapStateToProps = (state, props) => ({
medias: getAccountGallery(state, Number(props.params.accountId)), medias: getAccountGallery(state, Number(props.params.accountId)),
@ -48,16 +49,30 @@ class AccountGallery extends ImmutablePureComponent {
} }
} }
handleScrollToBottom = () => {
if (this.props.hasMore) {
this.props.dispatch(expandAccountMediaTimeline(Number(this.props.params.accountId)));
}
}
handleScroll = (e) => { handleScroll = (e) => {
const { scrollTop, scrollHeight, clientHeight } = e.target; const { scrollTop, scrollHeight, clientHeight } = e.target;
const offset = scrollHeight - scrollTop - clientHeight;
if (scrollTop === scrollHeight - clientHeight) { if (150 > offset && !this.props.isLoading) {
this.props.dispatch(expandAccountMediaTimeline(Number(this.props.params.accountId))); this.handleScrollToBottom();
} }
} }
handleLoadMore = (e) => {
e.preventDefault();
this.handleScrollToBottom();
}
render () { render () {
const { medias, autoPlayGif, isLoading } = this.props; const { medias, autoPlayGif, isLoading, hasMore } = this.props;
let loadMore = null;
if (!medias && isLoading) { if (!medias && isLoading) {
return ( return (
@ -67,6 +82,10 @@ class AccountGallery extends ImmutablePureComponent {
); );
} }
if (!isLoading && medias.size > 0 && hasMore) {
loadMore = <LoadMore onClick={this.handleLoadMore} />;
}
return ( return (
<Column> <Column>
<ColumnBackButton /> <ColumnBackButton />
@ -87,6 +106,7 @@ class AccountGallery extends ImmutablePureComponent {
autoPlayGif={autoPlayGif} autoPlayGif={autoPlayGif}
/> />
)} )}
{loadMore}
</div> </div>
</div> </div>
</ScrollContainer> </ScrollContainer>

@ -155,7 +155,7 @@ const normalizeAccountTimeline = (state, accountId, statuses, replace = false) =
.update('items', Immutable.List(), list => (replace ? ids : ids.concat(list)))); .update('items', Immutable.List(), list => (replace ? ids : ids.concat(list))));
}; };
const normalizeAccountMediaTimeline = (state, accountId, statuses, next) => { const normalizeAccountMediaTimeline = (state, accountId, statuses) => {
let ids = Immutable.List(); let ids = Immutable.List();
statuses.forEach((status, i) => { statuses.forEach((status, i) => {
@ -165,7 +165,7 @@ const normalizeAccountMediaTimeline = (state, accountId, statuses, next) => {
return state.updateIn(['accounts_media_timelines', accountId], Immutable.Map(), map => map return state.updateIn(['accounts_media_timelines', accountId], Immutable.Map(), map => map
.set('isLoading', false) .set('isLoading', false)
.set('next', next) .set('next', true)
.update('items', Immutable.List(), list => ids.concat(list))); .update('items', Immutable.List(), list => ids.concat(list)));
}; };
@ -345,7 +345,7 @@ export default function timelines(state = initialState, action) {
case ACCOUNT_MEDIA_TIMELINE_EXPAND_FAIL: case ACCOUNT_MEDIA_TIMELINE_EXPAND_FAIL:
return state.updateIn(['accounts_media_timelines', action.id], Immutable.Map(), map => map.set('isLoading', false)); return state.updateIn(['accounts_media_timelines', action.id], Immutable.Map(), map => map.set('isLoading', false));
case ACCOUNT_MEDIA_TIMELINE_FETCH_SUCCESS: case ACCOUNT_MEDIA_TIMELINE_FETCH_SUCCESS:
return normalizeAccountMediaTimeline(state, action.id, Immutable.fromJS(action.statuses), action.next); return normalizeAccountMediaTimeline(state, action.id, Immutable.fromJS(action.statuses));
case ACCOUNT_MEDIA_TIMELINE_EXPAND_SUCCESS: case ACCOUNT_MEDIA_TIMELINE_EXPAND_SUCCESS:
return appendNormalizedAccountMediaTimeline(state, action.id, Immutable.fromJS(action.statuses), action.next); return appendNormalizedAccountMediaTimeline(state, action.id, Immutable.fromJS(action.statuses), action.next);
case ACCOUNT_BLOCK_SUCCESS: case ACCOUNT_BLOCK_SUCCESS:

@ -1962,6 +1962,7 @@ button.icon-button.active i.fa-retweet {
text-align: center; text-align: center;
padding: 15px; padding: 15px;
text-decoration: none; text-decoration: none;
clear: both;
&:hover { &:hover {
background: lighten($ui-base-color, 2%); background: lighten($ui-base-color, 2%);

Loading…
Cancel
Save