soapbox/app/soapbox/actions/streaming.ts

175 wiersze
5.9 KiB
TypeScript
Czysty Zwykły widok Historia

import { getSettings } from 'soapbox/actions/settings';
import messages from 'soapbox/locales/messages';
2022-09-22 21:28:05 +00:00
import { updatePageItem, appendPageItem } from 'soapbox/utils/queries';
2022-08-25 19:56:53 +00:00
import { play, soundCache } from 'soapbox/utils/sounds';
import { connectStream } from '../stream';
import {
deleteAnnouncement,
fetchAnnouncements,
updateAnnouncements,
updateReaction as updateAnnouncementsReaction,
} from './announcements';
import { updateConversations } from './conversations';
import { fetchFilters } from './filters';
import { MARKER_FETCH_SUCCESS } from './markers';
import { updateNotificationsQueue, expandNotifications } from './notifications';
import { updateStatus } from './statuses';
import {
// deleteFromTimelines,
expandHomeTimeline,
connectTimeline,
disconnectTimeline,
processTimelineUpdate,
} from './timelines';
import type { AppDispatch, RootState } from 'soapbox/store';
2022-09-21 22:52:20 +00:00
import type { APIEntity, Chat, ChatMessage } from 'soapbox/types/entities';
const STREAMING_CHAT_UPDATE = 'STREAMING_CHAT_UPDATE';
const STREAMING_FOLLOW_RELATIONSHIPS_UPDATE = 'STREAMING_FOLLOW_RELATIONSHIPS_UPDATE';
const validLocale = (locale: string) => Object.keys(messages).includes(locale);
const getLocale = (state: RootState) => {
const locale = getSettings(state).get('locale') as string;
return validLocale(locale) ? locale : 'en';
};
const updateFollowRelationships = (relationships: APIEntity) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const me = getState().me;
return dispatch({
type: STREAMING_FOLLOW_RELATIONSHIPS_UPDATE,
me,
...relationships,
});
};
2022-09-21 22:52:20 +00:00
interface ChatPayload extends Omit<Chat, 'last_message'> {
last_message: ChatMessage | null,
}
const updateChat = (payload: ChatPayload) => {
const { last_message: lastMessage } = payload;
2022-09-22 21:28:05 +00:00
updatePageItem<Chat>(['chats', 'search'], payload as any, (o, n) => o.id === n.id);
2022-09-21 22:52:20 +00:00
if (lastMessage) {
2022-09-22 21:28:05 +00:00
appendPageItem(['chats', 'messages', payload.id], lastMessage);
}
2022-09-21 22:52:20 +00:00
};
const connectTimelineStream = (
timelineId: string,
path: string,
pollingRefresh: ((dispatch: AppDispatch, done?: () => void) => void) | null = null,
accept: ((status: APIEntity) => boolean) | null = null,
) => connectStream(path, pollingRefresh, (dispatch: AppDispatch, getState: () => RootState) => {
const locale = getLocale(getState());
return {
onConnect() {
dispatch(connectTimeline(timelineId));
},
onDisconnect() {
dispatch(disconnectTimeline(timelineId));
},
onReceive(data: any) {
switch (data.event) {
case 'update':
dispatch(processTimelineUpdate(timelineId, JSON.parse(data.payload), accept));
break;
case 'status.update':
dispatch(updateStatus(JSON.parse(data.payload)));
break;
2022-06-23 19:58:38 +00:00
// FIXME: We think delete & redraft is causing jumpy timelines.
// Fix that in ScrollableList then re-enable this!
//
// case 'delete':
// dispatch(deleteFromTimelines(data.payload));
// break;
case 'notification':
messages[locale]().then(messages => {
dispatch(updateNotificationsQueue(JSON.parse(data.payload), messages, locale, window.location.pathname));
}).catch(error => {
console.error(error);
});
break;
case 'conversation':
dispatch(updateConversations(JSON.parse(data.payload)));
break;
case 'filters_changed':
dispatch(fetchFilters());
break;
case 'pleroma:chat_update':
2022-09-21 22:52:20 +00:00
case 'chat_message': // TruthSocial
updateChat(JSON.parse(data.payload));
play(soundCache.chat);
break;
case 'pleroma:follow_relationships_update':
dispatch(updateFollowRelationships(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;
case 'marker':
dispatch({ type: MARKER_FETCH_SUCCESS, marker: JSON.parse(data.payload) });
break;
}
},
};
});
const refreshHomeTimelineAndNotification = (dispatch: AppDispatch, done?: () => void) =>
dispatch(expandHomeTimeline({}, () =>
dispatch(expandNotifications({}, () =>
dispatch(fetchAnnouncements(done))))));
const connectUserStream = () =>
connectTimelineStream('home', 'user', refreshHomeTimelineAndNotification);
const connectCommunityStream = ({ onlyMedia }: Record<string, any> = {}) =>
connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`);
const connectPublicStream = ({ onlyMedia }: Record<string, any> = {}) =>
connectTimelineStream(`public${onlyMedia ? ':media' : ''}`, `public${onlyMedia ? ':media' : ''}`);
const connectRemoteStream = (instance: string, { onlyMedia }: Record<string, any> = {}) =>
connectTimelineStream(`remote${onlyMedia ? ':media' : ''}:${instance}`, `public:remote${onlyMedia ? ':media' : ''}&instance=${instance}`);
const connectHashtagStream = (id: string, tag: string, accept: (status: APIEntity) => boolean) =>
connectTimelineStream(`hashtag:${id}`, `hashtag&tag=${tag}`, null, accept);
const connectDirectStream = () =>
connectTimelineStream('direct', 'direct');
const connectListStream = (id: string) =>
connectTimelineStream(`list:${id}`, `list&list=${id}`);
const connectGroupStream = (id: string) =>
connectTimelineStream(`group:${id}`, `group&group=${id}`);
export {
STREAMING_CHAT_UPDATE,
STREAMING_FOLLOW_RELATIONSHIPS_UPDATE,
connectTimelineStream,
connectUserStream,
connectCommunityStream,
connectPublicStream,
connectRemoteStream,
connectHashtagStream,
connectDirectStream,
connectListStream,
connectGroupStream,
};