123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- // @ts-check
- import { connectStream } from '../stream';
- import {
- updateTimeline,
- deleteFromTimelines,
- expandHomeTimeline,
- connectTimeline,
- disconnectTimeline,
- fillHomeTimelineGaps,
- fillPublicTimelineGaps,
- fillCommunityTimelineGaps,
- fillListTimelineGaps,
- } from './timelines';
- import { updateNotifications, expandNotifications } from './notifications';
- import { updateConversations } from './conversations';
- import { updateStatus } from './statuses';
- import {
- fetchAnnouncements,
- updateAnnouncements,
- updateReaction as updateAnnouncementsReaction,
- deleteAnnouncement,
- } from './announcements';
- import { getLocale } from '../locales';
- const { messages } = getLocale();
- /**
- * @param {number} max
- * @return {number}
- */
- const randomUpTo = max =>
- Math.floor(Math.random() * Math.floor(max));
- /**
- * @param {string} timelineId
- * @param {string} channelName
- * @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}
- */
- export const connectTimelineStream = (timelineId, channelName, params = {}, options = {}) =>
- connectStream(channelName, params, (dispatch, getState) => {
- const locale = getState().getIn(['meta', 'locale']);
- let pollingId;
- /**
- * @param {function(Function, Function): void} fallback
- */
- const useFallback = fallback => {
- fallback(dispatch, () => {
- pollingId = setTimeout(() => useFallback(fallback), 20000 + randomUpTo(20000));
- });
- };
- return {
- onConnect() {
- dispatch(connectTimeline(timelineId));
- if (pollingId) {
- clearTimeout(pollingId);
- pollingId = null;
- }
- if (options.fillGaps) {
- dispatch(options.fillGaps());
- }
- },
- onDisconnect() {
- dispatch(disconnectTimeline(timelineId));
- if (options.fallback) {
- pollingId = setTimeout(() => useFallback(options.fallback), randomUpTo(40000));
- }
- },
- onReceive (data) {
- switch(data.event) {
- case 'update':
- dispatch(updateTimeline(timelineId, JSON.parse(data.payload), options.accept));
- break;
- case 'status.update':
- dispatch(updateStatus(JSON.parse(data.payload)));
- break;
- case 'delete':
- dispatch(deleteFromTimelines(data.payload));
- break;
- case 'notification':
- dispatch(updateNotifications(JSON.parse(data.payload), messages, locale));
- break;
- case 'conversation':
- dispatch(updateConversations(JSON.parse(data.payload)));
- break;
- case 'announcement':
- dispatch(updateAnnouncements(JSON.parse(data.payload)));
- break;
- case 'announcement.reaction':
- dispatch(updateAnnouncementsReaction(JSON.parse(data.payload)));
- break;
- case 'announcement.delete':
- dispatch(deleteAnnouncement(data.payload));
- break;
- }
- },
- };
- });
- /**
- * @param {Function} dispatch
- * @param {function(): void} done
- */
- const refreshHomeTimelineAndNotification = (dispatch, done) => {
- dispatch(expandHomeTimeline({}, () =>
- dispatch(expandNotifications({}, () =>
- dispatch(fetchAnnouncements(done))))));
- };
- /**
- * @return {function(): void}
- */
- export const connectUserStream = () =>
- connectTimelineStream('home', 'user', {}, { fallback: refreshHomeTimelineAndNotification, fillGaps: fillHomeTimelineGaps });
- /**
- * @param {Object} options
- * @param {boolean} [options.onlyMedia]
- * @return {function(): void}
- */
- export const connectCommunityStream = ({ onlyMedia } = {}) =>
- connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`, {}, { fillGaps: () => (fillCommunityTimelineGaps({ onlyMedia })) });
- /**
- * @param {Object} options
- * @param {boolean} [options.onlyMedia]
- * @param {boolean} [options.onlyRemote]
- * @return {function(): void}
- */
- export const connectPublicStream = ({ onlyMedia, onlyRemote } = {}) =>
- connectTimelineStream(`public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`, `public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`, {}, { fillGaps: () => fillPublicTimelineGaps({ onlyMedia, onlyRemote }) });
- /**
- * @param {string} columnId
- * @param {string} tagName
- * @param {boolean} onlyLocal
- * @param {function(object): boolean} accept
- * @return {function(): void}
- */
- export const connectHashtagStream = (columnId, tagName, onlyLocal, accept) =>
- connectTimelineStream(`hashtag:${columnId}${onlyLocal ? ':local' : ''}`, `hashtag${onlyLocal ? ':local' : ''}`, { tag: tagName }, { accept });
- /**
- * @return {function(): void}
- */
- export const connectDirectStream = () =>
- connectTimelineStream('direct', 'direct');
- /**
- * @param {string} listId
- * @return {function(): void}
- */
- export const connectListStream = listId =>
- connectTimelineStream(`list:${listId}`, 'list', { list: listId }, { fillGaps: () => fillListTimelineGaps(listId) });
|