From d9022884c6c4e066b1e6ee8d9c07c220c031454e Mon Sep 17 00:00:00 2001
From: Eugen Rochko <eugen@zeonfederated.com>
Date: Tue, 24 Jan 2017 04:12:10 +0100
Subject: Smarter infinite scroll

---
 .../javascripts/components/reducers/timelines.jsx  | 30 ++++++++++++++++++----
 1 file changed, 25 insertions(+), 5 deletions(-)

(limited to 'app/assets/javascripts/components/reducers/timelines.jsx')

diff --git a/app/assets/javascripts/components/reducers/timelines.jsx b/app/assets/javascripts/components/reducers/timelines.jsx
index c5e3a253f..6b1093651 100644
--- a/app/assets/javascripts/components/reducers/timelines.jsx
+++ b/app/assets/javascripts/components/reducers/timelines.jsx
@@ -4,6 +4,7 @@ import {
   TIMELINE_UPDATE,
   TIMELINE_DELETE,
   TIMELINE_EXPAND_SUCCESS,
+  TIMELINE_EXPAND_REQUEST,
   TIMELINE_SCROLL_TOP
 } from '../actions/timelines';
 import {
@@ -13,37 +14,41 @@ import {
   UNFAVOURITE_SUCCESS
 } from '../actions/interactions';
 import {
-  ACCOUNT_FETCH_SUCCESS,
+  ACCOUNT_TIMELINE_FETCH_REQUEST,
   ACCOUNT_TIMELINE_FETCH_SUCCESS,
+  ACCOUNT_TIMELINE_EXPAND_REQUEST,
   ACCOUNT_TIMELINE_EXPAND_SUCCESS,
   ACCOUNT_BLOCK_SUCCESS
 } from '../actions/accounts';
 import {
-  STATUS_FETCH_SUCCESS,
   CONTEXT_FETCH_SUCCESS
 } from '../actions/statuses';
 import Immutable from 'immutable';
 
 const initialState = Immutable.Map({
   home: Immutable.Map({
+    isLoading: false,
     loaded: false,
     top: true,
     items: Immutable.List()
   }),
 
   mentions: Immutable.Map({
+    isLoading: false,
     loaded: false,
     top: true,
     items: Immutable.List()
   }),
 
   public: Immutable.Map({
+    isLoading: false,
     loaded: false,
     top: true,
     items: Immutable.List()
   }),
 
   tag: Immutable.Map({
+    isLoading: false,
     id: null,
     loaded: false,
     top: true,
@@ -82,6 +87,7 @@ const normalizeTimeline = (state, timeline, statuses, replace = false) => {
   });
 
   state = state.setIn([timeline, 'loaded'], true);
+  state = state.setIn([timeline, 'isLoading'], false);
 
   return state.updateIn([timeline, 'items'], Immutable.List(), list => (loaded ? list.unshift(...ids) : ids));
 };
@@ -94,6 +100,8 @@ const appendNormalizedTimeline = (state, timeline, statuses) => {
     moreIds = moreIds.set(i, status.get('id'));
   });
 
+  state = state.setIn([timeline, 'isLoading'], false);
+
   return state.updateIn([timeline, 'items'], Immutable.List(), list => list.push(...moreIds));
 };
 
@@ -105,7 +113,10 @@ const normalizeAccountTimeline = (state, accountId, statuses, replace = false) =
     ids   = ids.set(i, status.get('id'));
   });
 
-  return state.updateIn(['accounts_timelines', accountId], Immutable.List([]), list => (replace ? ids : list.unshift(...ids)));
+  return state.updateIn(['accounts_timelines', accountId], Immutable.Map(), map => map
+    .set('isLoading', false)
+    .set('loaded', true)
+    .update('items', Immutable.List(), list => (replace ? ids : list.unshift(...ids))));
 };
 
 const appendNormalizedAccountTimeline = (state, accountId, statuses) => {
@@ -116,7 +127,9 @@ const appendNormalizedAccountTimeline = (state, accountId, statuses) => {
     moreIds = moreIds.set(i, status.get('id'));
   });
 
-  return state.updateIn(['accounts_timelines', accountId], Immutable.List([]), list => list.push(...moreIds));
+  return state.updateIn(['accounts_timelines', accountId], Immutable.Map(), map => map
+    .set('isLoading', false)
+    .update('items', list => list.push(...moreIds)));
 };
 
 const updateTimeline = (state, timeline, status, references) => {
@@ -157,7 +170,7 @@ const deleteStatus = (state, id, accountId, references, reblogOf) => {
   });
 
   // Remove references from account timelines
-  state = state.updateIn(['accounts_timelines', accountId], Immutable.List([]), list => list.filterNot(item => item === id));
+  state = state.updateIn(['accounts_timelines', accountId, 'items'], Immutable.List([]), list => list.filterNot(item => item === id));
 
   // Remove references from context
   state.getIn(['descendants', id], Immutable.List()).forEach(descendantId => {
@@ -207,8 +220,11 @@ const resetTimeline = (state, timeline, id) => {
   if (timeline === 'tag' && state.getIn([timeline, 'id']) !== id) {
     state = state.update(timeline, map => map
         .set('id', id)
+        .set('isLoading', true)
         .set('loaded', false)
         .update('items', list => list.clear()));
+  } else {
+    state = state.setIn([timeline, 'isLoading'], true);
   }
 
   return state;
@@ -217,6 +233,7 @@ const resetTimeline = (state, timeline, id) => {
 export default function timelines(state = initialState, action) {
   switch(action.type) {
     case TIMELINE_REFRESH_REQUEST:
+    case TIMELINE_EXPAND_REQUEST:
       return resetTimeline(state, action.timeline, action.id);
     case TIMELINE_REFRESH_SUCCESS:
       return normalizeTimeline(state, action.timeline, Immutable.fromJS(action.statuses));
@@ -228,6 +245,9 @@ export default function timelines(state = initialState, action) {
       return deleteStatus(state, action.id, action.accountId, action.references, action.reblogOf);
     case CONTEXT_FETCH_SUCCESS:
       return normalizeContext(state, action.id, Immutable.fromJS(action.ancestors), Immutable.fromJS(action.descendants));
+    case ACCOUNT_TIMELINE_FETCH_REQUEST:
+    case ACCOUNT_TIMELINE_EXPAND_REQUEST:
+      return state.updateIn(['accounts_timelines', action.id], Immutable.Map(), map => map.set('isLoading', true));
     case ACCOUNT_TIMELINE_FETCH_SUCCESS:
       return normalizeAccountTimeline(state, action.id, Immutable.fromJS(action.statuses), action.replace);
     case ACCOUNT_TIMELINE_EXPAND_SUCCESS:
-- 
cgit 

