From cf4fe6cab86384971d4b7bd634f48b0a462efd48 Mon Sep 17 00:00:00 2001 From: unarist Date: Fri, 26 May 2017 00:09:13 +0900 Subject: [PATCH] More use of next link header on account (media) timelines (#3311) This will reduce requests on who have only few statuses. - Use next link header to detect more items from first request - Omit next link header if result items are fewer than requested count (It had omit it only if result was empty before) --- app/controllers/api/v1/accounts_controller.rb | 2 +- app/javascript/mastodon/actions/accounts.js | 12 ++++++++---- app/javascript/mastodon/reducers/timelines.js | 14 +++++++------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index d323522ff6..bd6fb6a2a8 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -62,7 +62,7 @@ class Api::V1::AccountsController < ApiController set_maps(@statuses) - next_path = statuses_api_v1_account_url(statuses_pagination_params(max_id: @statuses.last.id)) unless @statuses.empty? + next_path = statuses_api_v1_account_url(statuses_pagination_params(max_id: @statuses.last.id)) if @statuses.size == limit_param(DEFAULT_STATUSES_LIMIT) prev_path = statuses_api_v1_account_url(statuses_pagination_params(since_id: @statuses.first.id)) unless @statuses.empty? set_pagination_headers(next_path, prev_path) diff --git a/app/javascript/mastodon/actions/accounts.js b/app/javascript/mastodon/actions/accounts.js index d093815e2f..48ab7b6ede 100644 --- a/app/javascript/mastodon/actions/accounts.js +++ b/app/javascript/mastodon/actions/accounts.js @@ -115,7 +115,8 @@ export function fetchAccountTimeline(id, replace = false) { dispatch(fetchAccountTimelineRequest(id, skipLoading)); api(getState).get(`/api/v1/accounts/${id}/statuses`, { params }).then(response => { - dispatch(fetchAccountTimelineSuccess(id, response.data, replace, skipLoading)); + const next = getLinks(response).refs.find(link => link.rel === 'next'); + dispatch(fetchAccountTimelineSuccess(id, response.data, replace, skipLoading, next)); }).catch(error => { dispatch(fetchAccountTimelineFail(id, error, skipLoading)); }); @@ -138,7 +139,8 @@ export function fetchAccountMediaTimeline(id, replace = false) { dispatch(fetchAccountMediaTimelineRequest(id, skipLoading)); api(getState).get(`/api/v1/accounts/${id}/statuses`, { params }).then(response => { - dispatch(fetchAccountMediaTimelineSuccess(id, response.data, replace, skipLoading)); + const next = getLinks(response).refs.find(link => link.rel === 'next'); + dispatch(fetchAccountMediaTimelineSuccess(id, response.data, replace, skipLoading, next)); }).catch(error => { dispatch(fetchAccountMediaTimelineFail(id, error, skipLoading)); }); @@ -283,13 +285,14 @@ export function fetchAccountTimelineRequest(id, skipLoading) { }; }; -export function fetchAccountTimelineSuccess(id, statuses, replace, skipLoading) { +export function fetchAccountTimelineSuccess(id, statuses, replace, skipLoading, next) { return { type: ACCOUNT_TIMELINE_FETCH_SUCCESS, id, statuses, replace, skipLoading, + next, }; }; @@ -311,13 +314,14 @@ export function fetchAccountMediaTimelineRequest(id, skipLoading) { }; }; -export function fetchAccountMediaTimelineSuccess(id, statuses, replace, skipLoading) { +export function fetchAccountMediaTimelineSuccess(id, statuses, replace, skipLoading, next) { return { type: ACCOUNT_MEDIA_TIMELINE_FETCH_SUCCESS, id, statuses, replace, skipLoading, + next, }; }; diff --git a/app/javascript/mastodon/reducers/timelines.js b/app/javascript/mastodon/reducers/timelines.js index 49eb4756c5..ed89f76bc0 100644 --- a/app/javascript/mastodon/reducers/timelines.js +++ b/app/javascript/mastodon/reducers/timelines.js @@ -140,7 +140,7 @@ const appendNormalizedTimeline = (state, timeline, statuses, next) => { return state.updateIn([timeline, 'items'], Immutable.List(), list => list.concat(moreIds)); }; -const normalizeAccountTimeline = (state, accountId, statuses, replace = false) => { +const normalizeAccountTimeline = (state, accountId, statuses, replace, next) => { let ids = Immutable.List(); statuses.forEach((status, i) => { @@ -151,11 +151,11 @@ const normalizeAccountTimeline = (state, accountId, statuses, replace = false) = return state.updateIn(['accounts_timelines', accountId], Immutable.Map(), map => map .set('isLoading', false) .set('loaded', true) - .set('next', true) + .set('next', next) .update('items', Immutable.List(), list => (replace ? ids : ids.concat(list)))); }; -const normalizeAccountMediaTimeline = (state, accountId, statuses) => { +const normalizeAccountMediaTimeline = (state, accountId, statuses, replace, next) => { let ids = Immutable.List(); statuses.forEach((status, i) => { @@ -165,8 +165,8 @@ const normalizeAccountMediaTimeline = (state, accountId, statuses) => { return state.updateIn(['accounts_media_timelines', accountId], Immutable.Map(), map => map .set('isLoading', false) - .set('next', true) - .update('items', Immutable.List(), list => ids.concat(list))); + .set('next', next) + .update('items', Immutable.List(), list => (replace ? ids : ids.concat(list)))); }; const appendNormalizedAccountTimeline = (state, accountId, statuses, next) => { @@ -335,7 +335,7 @@ export default function timelines(state = initialState, action) { 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); + return normalizeAccountTimeline(state, action.id, Immutable.fromJS(action.statuses), action.replace, action.next); case ACCOUNT_TIMELINE_EXPAND_SUCCESS: return appendNormalizedAccountTimeline(state, action.id, Immutable.fromJS(action.statuses), action.next); case ACCOUNT_MEDIA_TIMELINE_FETCH_REQUEST: @@ -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)); + return normalizeAccountMediaTimeline(state, action.id, Immutable.fromJS(action.statuses), action.replace, action.next); case ACCOUNT_MEDIA_TIMELINE_EXPAND_SUCCESS: return appendNormalizedAccountMediaTimeline(state, action.id, Immutable.fromJS(action.statuses), action.next); case ACCOUNT_BLOCK_SUCCESS: