about summary refs log tree commit diff
diff options
context:
space:
mode:
authorunarist <m.unarist@gmail.com>2017-05-25 12:22:46 +0900
committerEugen Rochko <eugen@zeonfederated.com>2017-05-25 05:22:46 +0200
commit807c192fcf3a6cd0f4c712ec43130fbffddcc6c6 (patch)
tree8956d82961a88cb8205e43d14a88fc017374a738
parent3b59f9c6c254e34d95d917857ccbe79f6e1104b0 (diff)
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
-rw-r--r--app/javascript/mastodon/features/account_gallery/index.js26
-rw-r--r--app/javascript/mastodon/reducers/timelines.js6
-rw-r--r--app/javascript/styles/components.scss1
3 files changed, 27 insertions, 6 deletions
diff --git a/app/javascript/mastodon/features/account_gallery/index.js b/app/javascript/mastodon/features/account_gallery/index.js
index 6ddfcb0a0..a15419ac7 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 {
     }
   }
 
+  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 (scrollTop === scrollHeight - clientHeight) {
-      this.props.dispatch(expandAccountMediaTimeline(Number(this.props.params.accountId)));
+    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 = <LoadMore onClick={this.handleLoadMore} />;
+    }
+
     return (
       <Column>
         <ColumnBackButton />
@@ -87,6 +106,7 @@ class AccountGallery extends ImmutablePureComponent {
                   autoPlayGif={autoPlayGif}
                 />
               )}
+              {loadMore}
             </div>
           </div>
         </ScrollContainer>
diff --git a/app/javascript/mastodon/reducers/timelines.js b/app/javascript/mastodon/reducers/timelines.js
index 2e95d645e..49eb4756c 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 3971a85bc..38fbda5a9 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%);