about summary refs log tree commit diff
path: root/app/assets/javascripts/components/reducers/timelines.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/components/reducers/timelines.jsx')
-rw-r--r--app/assets/javascripts/components/reducers/timelines.jsx91
1 files changed, 63 insertions, 28 deletions
diff --git a/app/assets/javascripts/components/reducers/timelines.jsx b/app/assets/javascripts/components/reducers/timelines.jsx
index b73c83e0f..6f2d26dcb 100644
--- a/app/assets/javascripts/components/reducers/timelines.jsx
+++ b/app/assets/javascripts/components/reducers/timelines.jsx
@@ -1,9 +1,12 @@
 import {
   TIMELINE_REFRESH_REQUEST,
   TIMELINE_REFRESH_SUCCESS,
+  TIMELINE_REFRESH_FAIL,
   TIMELINE_UPDATE,
   TIMELINE_DELETE,
   TIMELINE_EXPAND_SUCCESS,
+  TIMELINE_EXPAND_REQUEST,
+  TIMELINE_EXPAND_FAIL,
   TIMELINE_SCROLL_TOP
 } from '../actions/timelines';
 import {
@@ -13,37 +16,43 @@ import {
   UNFAVOURITE_SUCCESS
 } from '../actions/interactions';
 import {
-  ACCOUNT_FETCH_SUCCESS,
+  ACCOUNT_TIMELINE_FETCH_REQUEST,
   ACCOUNT_TIMELINE_FETCH_SUCCESS,
+  ACCOUNT_TIMELINE_FETCH_FAIL,
+  ACCOUNT_TIMELINE_EXPAND_REQUEST,
   ACCOUNT_TIMELINE_EXPAND_SUCCESS,
+  ACCOUNT_TIMELINE_EXPAND_FAIL,
   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 +91,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 +104,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 +117,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 +131,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) => {
@@ -145,14 +162,19 @@ const updateTimeline = (state, timeline, status, references) => {
   return state;
 };
 
-const deleteStatus = (state, id, accountId, references) => {
+const deleteStatus = (state, id, accountId, references, reblogOf) => {
+  if (reblogOf) {
+    // If we are deleting a reblog, just replace reblog with its original
+    return state.updateIn(['home', 'items'], list => list.map(item => item === id ? reblogOf : item));
+  }
+
   // Remove references from timelines
   ['home', 'mentions', 'public', 'tag'].forEach(function (timeline) {
     state = state.updateIn([timeline, 'items'], list => list.filterNot(item => item === id));
   });
 
   // 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 => {
@@ -202,8 +224,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;
@@ -211,27 +236,37 @@ const resetTimeline = (state, timeline, id) => {
 
 export default function timelines(state = initialState, action) {
   switch(action.type) {
-    case TIMELINE_REFRESH_REQUEST:
-      return resetTimeline(state, action.timeline, action.id);
-    case TIMELINE_REFRESH_SUCCESS:
-      return normalizeTimeline(state, action.timeline, Immutable.fromJS(action.statuses));
-    case TIMELINE_EXPAND_SUCCESS:
-      return appendNormalizedTimeline(state, action.timeline, Immutable.fromJS(action.statuses));
-    case TIMELINE_UPDATE:
-      return updateTimeline(state, action.timeline, Immutable.fromJS(action.status), action.references);
-    case TIMELINE_DELETE:
-      return deleteStatus(state, action.id, action.accountId, action.references);
-    case CONTEXT_FETCH_SUCCESS:
-      return normalizeContext(state, action.id, Immutable.fromJS(action.ancestors), Immutable.fromJS(action.descendants));
-    case ACCOUNT_TIMELINE_FETCH_SUCCESS:
-      return normalizeAccountTimeline(state, action.id, Immutable.fromJS(action.statuses), action.replace);
-    case ACCOUNT_TIMELINE_EXPAND_SUCCESS:
-      return appendNormalizedAccountTimeline(state, action.id, Immutable.fromJS(action.statuses));
-    case ACCOUNT_BLOCK_SUCCESS:
-      return filterTimelines(state, action.relationship, action.statuses);
-    case TIMELINE_SCROLL_TOP:
-      return state.setIn([action.timeline, 'top'], action.top);
-    default:
-      return state;
+  case TIMELINE_REFRESH_REQUEST:
+  case TIMELINE_EXPAND_REQUEST:
+    return resetTimeline(state, action.timeline, action.id);
+  case TIMELINE_REFRESH_FAIL:
+  case TIMELINE_EXPAND_FAIL:
+    return state.setIn([action.timeline, 'isLoading'], false);
+  case TIMELINE_REFRESH_SUCCESS:
+    return normalizeTimeline(state, action.timeline, Immutable.fromJS(action.statuses));
+  case TIMELINE_EXPAND_SUCCESS:
+    return appendNormalizedTimeline(state, action.timeline, Immutable.fromJS(action.statuses));
+  case TIMELINE_UPDATE:
+    return updateTimeline(state, action.timeline, Immutable.fromJS(action.status), action.references);
+  case TIMELINE_DELETE:
+    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_FAIL:
+  case ACCOUNT_TIMELINE_EXPAND_FAIL:
+    return state.updateIn(['accounts_timelines', action.id], Immutable.Map(), map => map.set('isLoading', false));
+  case ACCOUNT_TIMELINE_FETCH_SUCCESS:
+    return normalizeAccountTimeline(state, action.id, Immutable.fromJS(action.statuses), action.replace);
+  case ACCOUNT_TIMELINE_EXPAND_SUCCESS:
+    return appendNormalizedAccountTimeline(state, action.id, Immutable.fromJS(action.statuses));
+  case ACCOUNT_BLOCK_SUCCESS:
+    return filterTimelines(state, action.relationship, action.statuses);
+  case TIMELINE_SCROLL_TOP:
+    return state.setIn([action.timeline, 'top'], action.top);
+  default:
+    return state;
   }
 };