From b4692f151301661861171265b69569af7e1520fa Mon Sep 17 00:00:00 2001 From: unarist Date: Thu, 25 May 2017 12:22:46 +0900 Subject: [PATCH] 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 --- .../features/account_gallery/index.js | 30 +++++++++++++++---- app/javascript/mastodon/reducers/timelines.js | 6 ++-- app/javascript/styles/components.scss | 1 + 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/app/javascript/mastodon/features/account_gallery/index.js b/app/javascript/mastodon/features/account_gallery/index.js index 6ddfcb0a0c..a15419ac73 100644 --- a/app/javascript/mastodon/features/account_gallery/index.js +++ b/app/javascript/mastodon/features/account_gallery/index.js @@ -17,6 +17,7 @@ import MediaItem from './components/media_item'; import HeaderContainer from '../account_timeline/containers/header_container'; import { FormattedMessage } from 'react-intl'; import { ScrollContainer } from 'react-router-scroll'; +import LoadMore from '../../components/load_more'; const mapStateToProps = (state, props) => ({ medias: getAccountGallery(state, Number(props.params.accountId)), @@ -48,16 +49,30 @@ class AccountGallery extends ImmutablePureComponent { } } - handleScroll = (e) => { - const { scrollTop, scrollHeight, clientHeight } = e.target; - - if (scrollTop === scrollHeight - clientHeight) { + handleScrollToBottom = () => { + if (this.props.hasMore) { this.props.dispatch(expandAccountMediaTimeline(Number(this.props.params.accountId))); } } + handleScroll = (e) => { + const { scrollTop, scrollHeight, clientHeight } = e.target; + const offset = scrollHeight - scrollTop - clientHeight; + + if (150 > offset && !this.props.isLoading) { + this.handleScrollToBottom(); + } + } + + handleLoadMore = (e) => { + e.preventDefault(); + this.handleScrollToBottom(); + } + render () { - const { medias, autoPlayGif, isLoading } = this.props; + const { medias, autoPlayGif, isLoading, hasMore } = this.props; + + let loadMore = null; if (!medias && isLoading) { return ( @@ -67,6 +82,10 @@ class AccountGallery extends ImmutablePureComponent { ); } + if (!isLoading && medias.size > 0 && hasMore) { + loadMore = ; + } + return ( @@ -87,6 +106,7 @@ class AccountGallery extends ImmutablePureComponent { autoPlayGif={autoPlayGif} /> )} + {loadMore} diff --git a/app/javascript/mastodon/reducers/timelines.js b/app/javascript/mastodon/reducers/timelines.js index 2e95d645e5..49eb4756c5 100644 --- a/app/javascript/mastodon/reducers/timelines.js +++ b/app/javascript/mastodon/reducers/timelines.js @@ -155,7 +155,7 @@ const normalizeAccountTimeline = (state, accountId, statuses, replace = false) = .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(); 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 .set('isLoading', false) - .set('next', next) + .set('next', true) .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: return state.updateIn(['accounts_media_timelines', action.id], Immutable.Map(), map => map.set('isLoading', false)); 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: return appendNormalizedAccountMediaTimeline(state, action.id, Immutable.fromJS(action.statuses), action.next); case ACCOUNT_BLOCK_SUCCESS: diff --git a/app/javascript/styles/components.scss b/app/javascript/styles/components.scss index 3971a85bc4..38fbda5a94 100644 --- a/app/javascript/styles/components.scss +++ b/app/javascript/styles/components.scss @@ -1962,6 +1962,7 @@ button.icon-button.active i.fa-retweet { text-align: center; padding: 15px; text-decoration: none; + clear: both; &:hover { background: lighten($ui-base-color, 2%);