]> cat aescling's git repositories - mastodon.git/blob - app/javascript/mastodon/actions/streaming.js
Add support for editing for published statuses (#16697)
[mastodon.git] / app / javascript / mastodon / actions / streaming.js
1 // @ts-check
2
3 import { connectStream } from '../stream';
4 import {
5 updateTimeline,
6 deleteFromTimelines,
7 expandHomeTimeline,
8 connectTimeline,
9 disconnectTimeline,
10 } from './timelines';
11 import { updateNotifications, expandNotifications } from './notifications';
12 import { updateConversations } from './conversations';
13 import { updateStatus } from './statuses';
14 import {
15 fetchAnnouncements,
16 updateAnnouncements,
17 updateReaction as updateAnnouncementsReaction,
18 deleteAnnouncement,
19 } from './announcements';
20 import { fetchFilters } from './filters';
21 import { getLocale } from '../locales';
22
23 const { messages } = getLocale();
24
25 /**
26 * @param {number} max
27 * @return {number}
28 */
29 const randomUpTo = max =>
30 Math.floor(Math.random() * Math.floor(max));
31
32 /**
33 * @param {string} timelineId
34 * @param {string} channelName
35 * @param {Object.<string, string>} params
36 * @param {Object} options
37 * @param {function(Function, Function): void} [options.fallback]
38 * @param {function(object): boolean} [options.accept]
39 * @return {function(): void}
40 */
41 export const connectTimelineStream = (timelineId, channelName, params = {}, options = {}) =>
42 connectStream(channelName, params, (dispatch, getState) => {
43 const locale = getState().getIn(['meta', 'locale']);
44
45 let pollingId;
46
47 /**
48 * @param {function(Function, Function): void} fallback
49 */
50 const useFallback = fallback => {
51 fallback(dispatch, () => {
52 pollingId = setTimeout(() => useFallback(fallback), 20000 + randomUpTo(20000));
53 });
54 };
55
56 return {
57 onConnect() {
58 dispatch(connectTimeline(timelineId));
59
60 if (pollingId) {
61 clearTimeout(pollingId);
62 pollingId = null;
63 }
64 },
65
66 onDisconnect() {
67 dispatch(disconnectTimeline(timelineId));
68
69 if (options.fallback) {
70 pollingId = setTimeout(() => useFallback(options.fallback), randomUpTo(40000));
71 }
72 },
73
74 onReceive (data) {
75 switch(data.event) {
76 case 'update':
77 dispatch(updateTimeline(timelineId, JSON.parse(data.payload), options.accept));
78 break;
79 case 'status.update':
80 dispatch(updateStatus(JSON.parse(data.payload)));
81 break;
82 case 'delete':
83 dispatch(deleteFromTimelines(data.payload));
84 break;
85 case 'notification':
86 dispatch(updateNotifications(JSON.parse(data.payload), messages, locale));
87 break;
88 case 'conversation':
89 dispatch(updateConversations(JSON.parse(data.payload)));
90 break;
91 case 'filters_changed':
92 dispatch(fetchFilters());
93 break;
94 case 'announcement':
95 dispatch(updateAnnouncements(JSON.parse(data.payload)));
96 break;
97 case 'announcement.reaction':
98 dispatch(updateAnnouncementsReaction(JSON.parse(data.payload)));
99 break;
100 case 'announcement.delete':
101 dispatch(deleteAnnouncement(data.payload));
102 break;
103 }
104 },
105 };
106 });
107
108 /**
109 * @param {Function} dispatch
110 * @param {function(): void} done
111 */
112 const refreshHomeTimelineAndNotification = (dispatch, done) => {
113 dispatch(expandHomeTimeline({}, () =>
114 dispatch(expandNotifications({}, () =>
115 dispatch(fetchAnnouncements(done))))));
116 };
117
118 /**
119 * @return {function(): void}
120 */
121 export const connectUserStream = () =>
122 connectTimelineStream('home', 'user', {}, { fallback: refreshHomeTimelineAndNotification });
123
124 /**
125 * @param {Object} options
126 * @param {boolean} [options.onlyMedia]
127 * @return {function(): void}
128 */
129 export const connectCommunityStream = ({ onlyMedia } = {}) =>
130 connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`);
131
132 /**
133 * @param {Object} options
134 * @param {boolean} [options.onlyMedia]
135 * @param {boolean} [options.onlyRemote]
136 * @return {function(): void}
137 */
138 export const connectPublicStream = ({ onlyMedia, onlyRemote } = {}) =>
139 connectTimelineStream(`public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`, `public${onlyRemote ? ':remote' : ''}${onlyMedia ? ':media' : ''}`);
140
141 /**
142 * @param {string} columnId
143 * @param {string} tagName
144 * @param {boolean} onlyLocal
145 * @param {function(object): boolean} accept
146 * @return {function(): void}
147 */
148 export const connectHashtagStream = (columnId, tagName, onlyLocal, accept) =>
149 connectTimelineStream(`hashtag:${columnId}${onlyLocal ? ':local' : ''}`, `hashtag${onlyLocal ? ':local' : ''}`, { tag: tagName }, { accept });
150
151 /**
152 * @return {function(): void}
153 */
154 export const connectDirectStream = () =>
155 connectTimelineStream('direct', 'direct');
156
157 /**
158 * @param {string} listId
159 * @return {function(): void}
160 */
161 export const connectListStream = listId =>
162 connectTimelineStream(`list:${listId}`, 'list', { list: listId });
This page took 0.102789 seconds and 4 git commands to generate.