expandHomeTimeline,
connectTimeline,
disconnectTimeline,
+ fillHomeTimelineGaps,
+ fillPublicTimelineGaps,
+ fillCommunityTimelineGaps,
+ fillListTimelineGaps,
} from './timelines';
import { updateNotifications, expandNotifications } from './notifications';
import { updateConversations } from './conversations';
* @param {Object.<string, string>} params
* @param {Object} options
* @param {function(Function, Function): void} [options.fallback]
+ * @param {function(): void} [options.fillGaps]
* @param {function(object): boolean} [options.accept]
* @return {function(): void}
*/
clearTimeout(pollingId);
pollingId = null;
}
+
+ if (options.fillGaps) {
+ dispatch(options.fillGaps());
+ }
},
onDisconnect() {
* @return {function(): void}
*/
export const connectUserStream = () =>
- connectTimelineStream('home', 'user', {}, { fallback: refreshHomeTimelineAndNotification });
+ connectTimelineStream('home', 'user', {}, { fallback: refreshHomeTimelineAndNotification, fillGaps: fillHomeTimelineGaps });
/**
* @param {Object} options
* @return {function(): void}
*/
export const connectCommunityStream = ({ onlyMedia } = {}) =>
- connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`);
+ connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`, {}, { fillGaps: () => (fillCommunityTimelineGaps({ onlyMedia })) });
/**
* @param {Object} options
* @return {function(): void}
*/
export const connectPublicStream = ({ onlyMedia, onlyRemote, allowLocalOnly } = {}) =>
- connectTimelineStream(`public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`, `public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`);
+ connectTimelineStream(`public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`, `public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`, {}, { fillGaps: () => fillPublicTimelineGaps({ onlyMedia, onlyRemote, allowLocalOnly }) });
/**
* @param {string} columnId
* @return {function(): void}
*/
export const connectListStream = listId =>
- connectTimelineStream(`list:${listId}`, 'list', { list: listId });
+ connectTimelineStream(`list:${listId}`, 'list', { list: listId }, { fillGaps: () => fillListTimelineGaps(listId) });
};
};
+export function fillTimelineGaps(timelineId, path, params = {}, done = noOp) {
+ return (dispatch, getState) => {
+ const timeline = getState().getIn(['timelines', timelineId], ImmutableMap());
+ const items = timeline.get('items');
+ const nullIndexes = items.map((statusId, index) => statusId === null ? index : null);
+ const gaps = nullIndexes.map(index => index > 0 ? items.get(index - 1) : null);
+
+ // Only expand at most two gaps to avoid doing too many requests
+ done = gaps.take(2).reduce((done, maxId) => {
+ return (() => dispatch(expandTimeline(timelineId, path, { ...params, maxId }, done)));
+ }, done);
+
+ done();
+ };
+}
+
export const expandHomeTimeline = ({ maxId } = {}, done = noOp) => expandTimeline('home', '/api/v1/timelines/home', { max_id: maxId }, done);
export const expandPublicTimeline = ({ maxId, onlyMedia, onlyRemote, allowLocalOnly } = {}, done = noOp) => expandTimeline(`public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { remote: !!onlyRemote, allow_local_only: !!allowLocalOnly, max_id: maxId, only_media: !!onlyMedia }, done);
export const expandCommunityTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, max_id: maxId, only_media: !!onlyMedia }, done);
}, done);
};
+export const fillHomeTimelineGaps = (done = noOp) => fillTimelineGaps('home', '/api/v1/timelines/home', {}, done);
+export const fillPublicTimelineGaps = ({ onlyMedia, onlyRemote, allowLocalOnly } = {}, done = noOp) => fillTimelineGaps(`public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { remote: !!onlyRemote, only_media: !!onlyMedia, allow_local_only: !!allowLocalOnly }, done);
+export const fillCommunityTimelineGaps = ({ onlyMedia } = {}, done = noOp) => fillTimelineGaps(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, only_media: !!onlyMedia }, done);
+export const fillListTimelineGaps = (id, done = noOp) => fillTimelineGaps(`list:${id}`, `/api/v1/timelines/list/${id}`, {}, done);
+
export function expandTimelineRequest(timeline, isLoadingMore) {
return {
type: TIMELINE_EXPAND_REQUEST,