about summary refs log tree commit diff
path: root/app/javascript/mastodon/actions/timelines.js
diff options
context:
space:
mode:
authorEugen Rochko <eugen@zeonfederated.com>2017-06-11 17:07:35 +0200
committerGitHub <noreply@github.com>2017-06-11 17:07:35 +0200
commit47bf7a8047ce59b899d147e4483168f9852eeb7c (patch)
tree79dd51ed84b1ed350cd754c8fca988dd6718a93a /app/javascript/mastodon/actions/timelines.js
parent85d405c810a3bfc146c7901d770444419f32e46f (diff)
Fix #3665 - Refactor timelines reducer (#3686)
* Move ancestors/descendants out of timelines reducer

* Refactor timelines reducer

All types of timelines now have a flat structure and use the same
reducer functions and actions

* Reintroduce some missing behaviours

* Fix wrong import in reports

* Fix includes typo

* Fix issue related to "next" pagination in timelines and notifications

* Fix bug with timeline's initial state, expandNotifications
Diffstat (limited to 'app/javascript/mastodon/actions/timelines.js')
-rw-r--r--app/javascript/mastodon/actions/timelines.js76
1 files changed, 37 insertions, 39 deletions
diff --git a/app/javascript/mastodon/actions/timelines.js b/app/javascript/mastodon/actions/timelines.js
index 98e441cd1..cb4410eba 100644
--- a/app/javascript/mastodon/actions/timelines.js
+++ b/app/javascript/mastodon/actions/timelines.js
@@ -56,91 +56,89 @@ export function deleteFromTimelines(id) {
   };
 };
 
-export function refreshTimelineRequest(timeline, id, skipLoading) {
+export function refreshTimelineRequest(timeline, skipLoading) {
   return {
     type: TIMELINE_REFRESH_REQUEST,
     timeline,
-    id,
     skipLoading,
   };
 };
 
-export function refreshTimeline(timeline, id = null) {
+export function refreshTimeline(timelineId, path, params = {}) {
   return function (dispatch, getState) {
-    if (getState().getIn(['timelines', timeline, 'isLoading'])) {
+    const timeline = getState().getIn(['timelines', timelineId], Immutable.Map());
+
+    if (timeline.get('isLoading') || timeline.get('online')) {
       return;
     }
 
-    const ids      = getState().getIn(['timelines', timeline, 'items'], Immutable.List());
+    const ids      = timeline.get('items', Immutable.List());
     const newestId = ids.size > 0 ? ids.first() : null;
-    let params     = getState().getIn(['timelines', timeline, 'params'], {});
-    const path     = getState().getIn(['timelines', timeline, 'path'])(id);
-
-    let skipLoading = false;
 
-    if (newestId !== null && getState().getIn(['timelines', timeline, 'loaded']) && (id === null || getState().getIn(['timelines', timeline, 'id']) === id)) {
-      if (id === null && getState().getIn(['timelines', timeline, 'online'])) {
-        // Skip refreshing when timeline is live anyway
-        return;
-      }
+    let skipLoading = timeline.get('loaded');
 
-      params          = { ...params, since_id: newestId };
-      skipLoading     = true;
-    } else if (getState().getIn(['timelines', timeline, 'loaded'])) {
-      skipLoading = true;
+    if (newestId !== null) {
+      params.since_id = newestId;
     }
 
-    dispatch(refreshTimelineRequest(timeline, id, skipLoading));
+    dispatch(refreshTimelineRequest(timelineId, skipLoading));
 
     api(getState).get(path, { params }).then(response => {
       const next = getLinks(response).refs.find(link => link.rel === 'next');
-      dispatch(refreshTimelineSuccess(timeline, response.data, skipLoading, next ? next.uri : null));
+      dispatch(refreshTimelineSuccess(timelineId, response.data, skipLoading, next ? next.uri : null));
     }).catch(error => {
-      dispatch(refreshTimelineFail(timeline, error, skipLoading));
+      dispatch(refreshTimelineFail(timelineId, error, skipLoading));
     });
   };
 };
 
+export const refreshHomeTimeline         = () => refreshTimeline('home', '/api/v1/timelines/home');
+export const refreshPublicTimeline       = () => refreshTimeline('public', '/api/v1/timelines/public');
+export const refreshCommunityTimeline    = () => refreshTimeline('community', '/api/v1/timelines/public', { local: true });
+export const refreshAccountTimeline      = accountId => refreshTimeline(`account:${accountId}`, `/api/v1/accounts/${accountId}/statuses`);
+export const refreshAccountMediaTimeline = accountId => refreshTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { only_media: true });
+export const refreshHashtagTimeline      = hashtag => refreshTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`);
+
 export function refreshTimelineFail(timeline, error, skipLoading) {
   return {
     type: TIMELINE_REFRESH_FAIL,
     timeline,
     error,
     skipLoading,
+    skipAlert: error.response.status === 404,
   };
 };
 
-export function expandTimeline(timeline) {
+export function expandTimeline(timelineId, path, params = {}) {
   return (dispatch, getState) => {
-    if (getState().getIn(['timelines', timeline, 'isLoading'])) {
-      return;
-    }
+    const timeline = getState().getIn(['timelines', timelineId], Immutable.Map());
+    const ids      = timeline.get('items', Immutable.List());
 
-    if (getState().getIn(['timelines', timeline, 'items']).size === 0) {
+    if (timeline.get('isLoading') || ids.size === 0) {
       return;
     }
 
-    const path   = getState().getIn(['timelines', timeline, 'path'])(getState().getIn(['timelines', timeline, 'id']));
-    const params = getState().getIn(['timelines', timeline, 'params'], {});
-    const lastId = getState().getIn(['timelines', timeline, 'items']).last();
+    params.max_id = ids.last();
+    params.limit  = 10;
 
-    dispatch(expandTimelineRequest(timeline));
+    dispatch(expandTimelineRequest(timelineId));
 
-    api(getState).get(path, {
-      params: {
-        ...params,
-        max_id: lastId,
-        limit: 10,
-      },
-    }).then(response => {
+    api(getState).get(path, { params }).then(response => {
       const next = getLinks(response).refs.find(link => link.rel === 'next');
-      dispatch(expandTimelineSuccess(timeline, response.data, next ? next.uri : null));
+      dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null));
     }).catch(error => {
-      dispatch(expandTimelineFail(timeline, error));
+      dispatch(expandTimelineFail(timelineId, error));
     });
   };
 };
 
+export const expandHomeTimeline         = () => expandTimeline('home', '/api/v1/timelines/home');
+export const expandPublicTimeline       = () => expandTimeline('public', '/api/v1/timelines/public');
+export const expandCommunityTimeline    = () => expandTimeline('community', '/api/v1/timelines/public', { local: true });
+export const expandAccountTimeline      = accountId => expandTimeline(`account:${accountId}`, `/api/v1/accounts/${accountId}/statuses`);
+export const expandAccountMediaTimeline = accountId => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { only_media: true });
+export const expandHashtagTimeline      = hashtag => expandTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`);
+
 export function expandTimelineRequest(timeline) {
   return {
     type: TIMELINE_EXPAND_REQUEST,