You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
149 lines
4.9 KiB
TypeScript
149 lines
4.9 KiB
TypeScript
/**
|
|
* This is strictly use to resolve conflicts between local state and the opengroup poll updates
|
|
* Currently only supports message reactions 26/08/2022
|
|
*/
|
|
|
|
import { filter, findIndex, remove } from 'lodash';
|
|
import { Reactions } from '../../../../util/reactions';
|
|
import { OpenGroupReactionMessageV4 } from '../opengroupV2/OpenGroupServerPoller';
|
|
|
|
export enum ChangeType {
|
|
REACTIONS = 0,
|
|
}
|
|
|
|
type ReactionAction = 'ADD' | 'REMOVE' | 'CLEAR';
|
|
|
|
type ReactionChange = {
|
|
messageId: number; // will be serverId of the reacted message
|
|
emoji: string;
|
|
action: ReactionAction;
|
|
};
|
|
|
|
export type SogsV3Mutation = {
|
|
seqno: number | null; // null until mutating API request returns
|
|
server: string; // serverUrl
|
|
room: string; // roomId
|
|
changeType: ChangeType;
|
|
metadata: ReactionChange; // For now we only support message reactions
|
|
};
|
|
|
|
// we don't want to export this, we want to export functions that manipulate it
|
|
const sogsMutationCache: Array<SogsV3Mutation> = [];
|
|
|
|
// for testing purposes only
|
|
export function getMutationCache() {
|
|
return sogsMutationCache;
|
|
}
|
|
|
|
function verifyEntry(entry: SogsV3Mutation): boolean {
|
|
return Boolean(
|
|
entry.server &&
|
|
entry.room &&
|
|
entry.changeType === ChangeType.REACTIONS &&
|
|
entry.metadata.messageId &&
|
|
entry.metadata.emoji &&
|
|
(entry.metadata.action === 'ADD' ||
|
|
entry.metadata.action === 'REMOVE' ||
|
|
entry.metadata.action === 'CLEAR')
|
|
);
|
|
}
|
|
|
|
export function addToMutationCache(entry: SogsV3Mutation) {
|
|
if (!verifyEntry(entry)) {
|
|
window.log.error('SOGS Mutation Cache: Entry verification on add failed!', entry);
|
|
} else {
|
|
sogsMutationCache.push(entry);
|
|
window.log.info('SOGS Mutation Cache: Entry added!', entry);
|
|
}
|
|
}
|
|
|
|
export function updateMutationCache(entry: SogsV3Mutation, seqno: number) {
|
|
if (!verifyEntry(entry)) {
|
|
window.log.error('SOGS Mutation Cache: Entry verification on update failed!', entry);
|
|
} else {
|
|
const entryIndex = findIndex(sogsMutationCache, entry);
|
|
if (entryIndex >= 0) {
|
|
sogsMutationCache[entryIndex].seqno = seqno;
|
|
window.log.info('SOGS Mutation Cache: Entry updated!', sogsMutationCache[entryIndex]);
|
|
} else {
|
|
window.log.error('SOGS Mutation Cache: Updated failed! Cannot find entry', entry);
|
|
}
|
|
}
|
|
}
|
|
|
|
// return is for testing purposes only
|
|
export async function processMessagesUsingCache(
|
|
server: string,
|
|
room: string,
|
|
message: OpenGroupReactionMessageV4
|
|
): Promise<OpenGroupReactionMessageV4> {
|
|
const updatedReactions = message.reactions;
|
|
|
|
const roomMatches: Array<SogsV3Mutation> = filter(sogsMutationCache, { server, room });
|
|
for (let i = 0; i < roomMatches.length; i++) {
|
|
const matchSeqno = roomMatches[i].seqno;
|
|
if (message.seqno && matchSeqno && matchSeqno <= message.seqno) {
|
|
const removedEntry = roomMatches.splice(i, 1)[0];
|
|
window.log.info(
|
|
`SOGS Mutation Cache: Entry ignored and removed in ${server}/${room} for message ${message.id}`,
|
|
removedEntry
|
|
);
|
|
remove(sogsMutationCache, removedEntry);
|
|
}
|
|
}
|
|
|
|
for (const reaction of Object.keys(message.reactions)) {
|
|
const reactionMatches = filter(roomMatches, {
|
|
server,
|
|
room,
|
|
changeType: ChangeType.REACTIONS,
|
|
metadata: {
|
|
messageId: message.id,
|
|
emoji: reaction,
|
|
},
|
|
});
|
|
|
|
for (const reactionMatch of reactionMatches) {
|
|
switch (reactionMatch.metadata.action) {
|
|
case 'ADD':
|
|
updatedReactions[reaction].you = true;
|
|
updatedReactions[reaction].count += 1;
|
|
window.log.info(
|
|
`SOGS Mutation Cache: Added our reaction based on the cache in ${server}/${room} for message ${message.id}`,
|
|
updatedReactions[reaction]
|
|
);
|
|
break;
|
|
case 'REMOVE':
|
|
updatedReactions[reaction].you = false;
|
|
updatedReactions[reaction].count -= 1;
|
|
window.log.info(
|
|
`SOGS Mutation Cache: Removed our reaction based on the cache in ${server}/${room} for message ${message.id}`,
|
|
updatedReactions[reaction]
|
|
);
|
|
break;
|
|
case 'CLEAR':
|
|
// tslint:disable-next-line: no-dynamic-delete
|
|
delete updatedReactions[reaction];
|
|
window.log.info(
|
|
`SOGS Mutation Cache: Cleared all ${reaction} reactions based on the cache in ${server}/${room} for message ${message.id}`
|
|
);
|
|
break;
|
|
default:
|
|
window.log.warn(
|
|
`SOGS Mutation Cache: Unsupported metadata action in OpenGroupMessageV4 in ${server}/${room} for message ${message.id}`,
|
|
reactionMatch
|
|
);
|
|
}
|
|
const removedEntry = remove(sogsMutationCache, reactionMatch);
|
|
window.log.info(
|
|
`SOGS Mutation Cache: Entry removed in ${server}/${room} for message ${message.id}`,
|
|
removedEntry
|
|
);
|
|
}
|
|
}
|
|
|
|
message.reactions = updatedReactions;
|
|
await Reactions.handleOpenGroupMessageReactions(message.reactions, message.id);
|
|
return message;
|
|
}
|