fedibird-fe/app/javascript/mastodon/actions/streaming.js

193 lines
6.4 KiB
JavaScript
Raw Normal View History

// @ts-check
2017-11-15 15:04:15 +00:00
import { connectStream } from '../stream';
import {
updateTimeline,
deleteFromTimelines,
2021-07-16 06:38:50 +00:00
expireFromTimelines,
expandHomeTimeline,
connectTimeline,
disconnectTimeline,
} from './timelines';
2021-09-14 07:28:52 +00:00
import { fetchRelationships, fetchAccounts } from './accounts';
2021-04-12 12:43:25 +00:00
import { getHomeVisibilities } from 'mastodon/selectors';
import { updateNotifications, expandNotifications } from './notifications';
import { updateConversations } from './conversations';
2021-05-19 05:58:27 +00:00
import { updateEmojiReaction } from './interactions';
import {
fetchAnnouncements,
updateAnnouncements,
updateReaction as updateAnnouncementsReaction,
deleteAnnouncement,
} from './announcements';
import { fetchFilters } from './filters';
import { getLocale } from '../locales';
2023-01-08 16:07:46 +00:00
import { deleteScheduledStatusSuccess } from './scheduled_statuses';
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(object): boolean} [options.accept]
* @return {function(): void}
*/
export const connectTimelineStream = (timelineId, channelName, params = {}, options = {}) =>
connectStream(channelName, params, (dispatch, getState) => {
2017-11-15 15:04:15 +00:00
const locale = getState().getIn(['meta', 'locale']);
let pollingId;
/**
2021-04-12 12:43:25 +00:00
* @param {function(Function, Function, Function): void} fallback
*/
const useFallback = fallback => {
2021-04-12 12:43:25 +00:00
fallback(dispatch, getState, () => {
pollingId = setTimeout(() => useFallback(fallback), 20000 + randomUpTo(20000));
});
};
2017-11-15 15:04:15 +00:00
return {
onConnect() {
dispatch(connectTimeline(timelineId));
if (pollingId) {
clearTimeout(pollingId);
pollingId = null;
}
},
2017-11-15 15:04:15 +00:00
onDisconnect() {
dispatch(disconnectTimeline(timelineId));
if (options.fallback) {
pollingId = setTimeout(() => useFallback(options.fallback), randomUpTo(40000));
}
},
2017-11-15 15:04:15 +00:00
onReceive (data) {
switch(data.event) {
case 'update':
dispatch(updateTimeline(timelineId, JSON.parse(data.payload), options.accept));
break;
case 'delete':
dispatch(deleteFromTimelines(data.payload));
break;
2021-07-16 06:38:50 +00:00
case 'expire':
dispatch(expireFromTimelines(data.payload));
break;
2023-01-08 16:07:46 +00:00
case 'scheduled_status':
dispatch(deleteScheduledStatusSuccess(data.payload));
break;
case 'notification':
dispatch(updateNotifications(JSON.parse(data.payload), messages, locale));
break;
case 'conversation':
dispatch(updateConversations(JSON.parse(data.payload)));
break;
case 'filters_changed':
dispatch(fetchFilters());
break;
2021-05-19 05:58:27 +00:00
case 'emoji_reaction':
2021-09-14 07:28:52 +00:00
const emojiReaction = JSON.parse(data.payload);
dispatch(fetchRelationships(emojiReaction.account_ids));
dispatch(fetchAccounts(emojiReaction.account_ids));
dispatch(updateEmojiReaction(emojiReaction));
2021-05-19 05:58:27 +00:00
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;
}
},
};
2017-11-15 15:04:15 +00:00
});
/**
* @param {Function} dispatch
* @param {function(): void} done
*/
2021-04-12 12:43:25 +00:00
const refreshHomeTimelineAndNotification = (dispatch, getState, done) => {
const visibilities = getHomeVisibilities(getState());
dispatch(expandHomeTimeline({ visibilities }, () =>
dispatch(expandNotifications({}, () =>
dispatch(fetchAnnouncements(done))))));
};
/**
* @return {function(): void}
*/
export const connectUserStream = () =>
connectTimelineStream('home', 'user', {}, { fallback: refreshHomeTimelineAndNotification });
/**
2019-11-13 22:42:56 +00:00
* @param {string} domain
* @param {Object} options
* @param {boolean} [options.onlyMedia]
* @param {boolean} [options.withoutMedia]
* @param {boolean} [options.withoutBot]
2019-11-13 22:42:56 +00:00
* @return {function(): void}
*/
export const connectDomainStream = (domain, { onlyMedia, withoutMedia, withoutBot } = {}) =>
connectTimelineStream(`domain${withoutBot ? ':nobot' : ':bot'}${withoutMedia ? ':nomedia' : ''}${onlyMedia ? ':media' : ''}:${domain}`, `public:domain${withoutBot ? ':nobot' : ':bot'}${withoutMedia ? ':nomedia' : ''}${onlyMedia ? ':media' : ''}`, { domain: domain });
2019-11-13 22:42:56 +00:00
2020-07-12 13:00:23 +00:00
/**
* @param {string} id
* @param {Object} options
* @param {boolean} [options.onlyMedia]
* @param {boolean} [options.withoutMedia]
2020-07-12 13:00:23 +00:00
* @param {string} [options.tagged]
* @return {function(): void}
*/
export const connectGroupStream = (id, { onlyMedia, withoutMedia, tagged } = {}) =>
connectTimelineStream(`group:${id}${withoutMedia ? ':nomedia' : ''}${onlyMedia ? ':media' : ''}${tagged ? `:${tagged}` : ''}`, `group${withoutMedia ? ':nomedia' : ''}${onlyMedia ? ':media' : ''}`, { id: id, tagged: tagged });
2020-07-12 13:00:23 +00:00
2019-11-13 22:42:56 +00:00
/**
* @param {Object} options
* @param {boolean} [options.onlyRemote]
2019-11-13 22:42:56 +00:00
* @param {boolean} [options.onlyMedia]
* @param {boolean} [options.withoutMedia]
* @param {boolean} [options.withoutBot]
* @return {function(): void}
*/
export const connectPublicStream = ({ onlyMedia, withoutMedia, withoutBot, onlyRemote } = {}) =>
connectTimelineStream(`public${onlyRemote ? ':remote' : ''}${withoutBot ? ':nobot' : ':bot'}${withoutMedia ? ':nomedia' : ''}${onlyMedia ? ':media' : ''}`, `public${onlyRemote ? ':remote' : ''}${withoutBot ? ':nobot' : ':bot'}${withoutMedia ? ':nomedia' : ''}${onlyMedia ? ':media' : ''}`);
/**
* @param {string} columnId
* @param {string} tagName
* @param {function(object): boolean} accept
* @return {function(): void}
*/
2019-08-15 14:45:25 +00:00
export const connectHashtagStream = (columnId, tagName, accept) =>
connectTimelineStream(`hashtag:${columnId}`, 'hashtag', { 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 });