Group notifications/reposts fetched from the same page
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
@ -141,47 +141,50 @@ const isBroken = (status: APIEntity) => {
|
||||
}
|
||||
};
|
||||
|
||||
const importFetchedStatuses = (statuses: APIEntity[]) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const accounts: APIEntity[] = [];
|
||||
const normalStatuses: APIEntity[] = [];
|
||||
const polls: APIEntity[] = [];
|
||||
const importFetchedStatuses = (statuses: APIEntity[]) => (dispatch: AppDispatch) => {
|
||||
const accounts: APIEntity[] = [];
|
||||
const normalStatuses: APIEntity[] = [];
|
||||
const polls: APIEntity[] = [];
|
||||
|
||||
function processStatus(status: APIEntity) {
|
||||
// Skip broken statuses
|
||||
if (isBroken(status)) return;
|
||||
function processStatus(status: APIEntity) {
|
||||
// Skip broken statuses
|
||||
if (isBroken(status)) return;
|
||||
|
||||
normalStatuses.push(status);
|
||||
accounts.push(status.account);
|
||||
normalStatuses.push(status);
|
||||
|
||||
if (status.reblog?.id) {
|
||||
processStatus(status.reblog);
|
||||
}
|
||||
|
||||
// Fedibird quotes
|
||||
if (status.quote?.id) {
|
||||
processStatus(status.quote);
|
||||
}
|
||||
|
||||
if (status.pleroma?.quote?.id) {
|
||||
processStatus(status.pleroma.quote);
|
||||
}
|
||||
|
||||
if (status.poll?.id) {
|
||||
polls.push(status.poll);
|
||||
}
|
||||
|
||||
if (status.group?.id) {
|
||||
dispatch(importFetchedGroup(status.group));
|
||||
}
|
||||
accounts.push(status.account);
|
||||
if (status.accounts) {
|
||||
accounts.push(...status.accounts);
|
||||
}
|
||||
|
||||
statuses.forEach(processStatus);
|
||||
if (status.reblog?.id) {
|
||||
processStatus(status.reblog);
|
||||
}
|
||||
|
||||
dispatch(importPolls(polls));
|
||||
dispatch(importFetchedAccounts(accounts));
|
||||
dispatch(importStatuses(normalStatuses));
|
||||
};
|
||||
// Fedibird quotes
|
||||
if (status.quote?.id) {
|
||||
processStatus(status.quote);
|
||||
}
|
||||
|
||||
if (status.pleroma?.quote?.id) {
|
||||
processStatus(status.pleroma.quote);
|
||||
}
|
||||
|
||||
if (status.poll?.id) {
|
||||
polls.push(status.poll);
|
||||
}
|
||||
|
||||
if (status.group?.id) {
|
||||
dispatch(importFetchedGroup(status.group));
|
||||
}
|
||||
}
|
||||
|
||||
statuses.forEach(processStatus);
|
||||
|
||||
dispatch(importPolls(polls));
|
||||
dispatch(importFetchedAccounts(accounts));
|
||||
dispatch(importStatuses(normalStatuses));
|
||||
};
|
||||
|
||||
const importFetchedPoll = (poll: APIEntity) =>
|
||||
(dispatch: AppDispatch) => {
|
||||
|
||||
@ -60,7 +60,6 @@ type FilterType = keyof typeof FILTER_TYPES;
|
||||
|
||||
defineMessages({
|
||||
mention: { id: 'notification.mention', defaultMessage: '{name} mentioned you' },
|
||||
group: { id: 'notifications.group', defaultMessage: '{count, plural, one {# notification} other {# notifications}}' },
|
||||
});
|
||||
|
||||
const fetchRelatedRelationships = (dispatch: AppDispatch, notifications: APIEntity[]) => {
|
||||
@ -188,6 +187,42 @@ const noOp = () => new Promise(f => f(undefined));
|
||||
|
||||
let abortExpandNotifications = new AbortController();
|
||||
|
||||
const STATUS_NOTIFICATION_TYPES = [
|
||||
'favourite',
|
||||
'reblog',
|
||||
// WIP separate notifications for each reaction?
|
||||
// 'pleroma:emoji_reaction',
|
||||
'pleroma:event_reminder',
|
||||
'pleroma:participation_accepted',
|
||||
'pleroma:participation_request',
|
||||
];
|
||||
|
||||
const deduplicateNotifications = (notifications: any[]) => {
|
||||
const deduplicatedNotifications: any[] = [];
|
||||
|
||||
for (const notification of notifications) {
|
||||
if (STATUS_NOTIFICATION_TYPES.includes(notification.type)) {
|
||||
const existingNotification = deduplicatedNotifications
|
||||
.find(deduplicatedNotification => deduplicatedNotification.type === notification.type && deduplicatedNotification.status?.id === notification.status?.id);
|
||||
|
||||
if (existingNotification) {
|
||||
if (existingNotification?.accounts) {
|
||||
existingNotification.accounts.push(notification.account);
|
||||
} else {
|
||||
existingNotification.accounts = [existingNotification.account, notification.account];
|
||||
}
|
||||
existingNotification.id += '+' + notification.id;
|
||||
} else {
|
||||
deduplicatedNotifications.push(notification);
|
||||
}
|
||||
} else {
|
||||
deduplicatedNotifications.push(notification);
|
||||
}
|
||||
}
|
||||
|
||||
return deduplicatedNotifications;
|
||||
};
|
||||
|
||||
const expandNotifications = ({ maxId }: Record<string, any> = {}, done: () => any = noOp, abort?: boolean) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
if (!isLoggedIn(getState)) return dispatch(noOp);
|
||||
@ -259,7 +294,9 @@ const expandNotifications = ({ maxId }: Record<string, any> = {}, done: () => an
|
||||
const statusesFromGroups = (Object.values(entries.statuses) as Status[]).filter((status) => !!status.group);
|
||||
dispatch(fetchGroupRelationships(statusesFromGroups.map((status: any) => status.group?.id)));
|
||||
|
||||
dispatch(expandNotificationsSuccess(response.data, next ? next.uri : null, isLoadingMore));
|
||||
const deduplicatedNotifications = deduplicateNotifications(response.data);
|
||||
|
||||
dispatch(expandNotificationsSuccess(deduplicatedNotifications, next ? next.uri : null, isLoadingMore));
|
||||
fetchRelatedRelationships(dispatch, response.data);
|
||||
done();
|
||||
}).catch(error => {
|
||||
|
||||
@ -146,6 +146,27 @@ const parseTags = (tags: Record<string, any[]> = {}, mode: 'any' | 'all' | 'none
|
||||
});
|
||||
};
|
||||
|
||||
const deduplicateStatuses = (statuses: any[]) => {
|
||||
const deduplicatedStatuses: any[] = [];
|
||||
|
||||
for (const status of statuses) {
|
||||
const reblogged = status.reblog && deduplicatedStatuses.find((deduplicatedStatuses) => deduplicatedStatuses.reblog?.id === status.reblog.id);
|
||||
|
||||
if (reblogged) {
|
||||
if (reblogged.accounts) {
|
||||
reblogged.accounts.push(status.account);
|
||||
} else {
|
||||
reblogged.accounts = [reblogged.account, status.account];
|
||||
}
|
||||
reblogged.id += ':' + status.id;
|
||||
} else {
|
||||
deduplicatedStatuses.push(status);
|
||||
}
|
||||
}
|
||||
|
||||
return deduplicatedStatuses;
|
||||
};
|
||||
|
||||
const expandTimeline = (timelineId: string, path: string, params: Record<string, any> = {}, done = noOp) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const timeline = getState().timelines.get(timelineId) || {} as Record<string, any>;
|
||||
@ -172,12 +193,15 @@ const expandTimeline = (timelineId: string, path: string, params: Record<string,
|
||||
return api(getState).get(path, { params }).then(response => {
|
||||
dispatch(importFetchedStatuses(response.data));
|
||||
|
||||
const statuses = deduplicateStatuses(response.data);
|
||||
dispatch(importFetchedStatuses(statuses.filter(status => status.accounts)));
|
||||
|
||||
const statusesFromGroups = (response.data as Status[]).filter((status) => !!status.group);
|
||||
dispatch(fetchGroupRelationships(statusesFromGroups.map((status: any) => status.group?.id)));
|
||||
|
||||
dispatch(expandTimelineSuccess(
|
||||
timelineId,
|
||||
response.data,
|
||||
statuses,
|
||||
getNextLink(response),
|
||||
getPrevLink(response),
|
||||
response.status === 206,
|
||||
|
||||
Reference in New Issue
Block a user