99 lines
3.1 KiB
TypeScript
99 lines
3.1 KiB
TypeScript
// Copyright 2021 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
import { ReactionModel } from '../messageModifiers/Reactions';
|
|
import { ReactionSource } from './ReactionSource';
|
|
import { getMessageById } from '../messages/getMessageById';
|
|
import { getSourceUuid, isStory } from '../messages/helpers';
|
|
import { strictAssert } from '../util/assert';
|
|
import { isDirectConversation } from '../util/whatTypeOfConversation';
|
|
import { incrementMessageCounter } from '../util/incrementMessageCounter';
|
|
import { repeat, zipObject } from '../util/iterables';
|
|
import { SendStatus } from '../messages/MessageSendState';
|
|
import { UUID } from '../types/UUID';
|
|
|
|
export async function enqueueReactionForSend({
|
|
emoji,
|
|
messageId,
|
|
remove,
|
|
}: Readonly<{
|
|
emoji: string;
|
|
messageId: string;
|
|
remove: boolean;
|
|
}>): Promise<void> {
|
|
const message = await getMessageById(messageId);
|
|
strictAssert(message, 'enqueueReactionForSend: no message found');
|
|
|
|
const targetAuthorUuid = getSourceUuid(message.attributes);
|
|
strictAssert(
|
|
targetAuthorUuid,
|
|
`enqueueReactionForSend: message ${message.idForLogging()} had no source UUID`
|
|
);
|
|
|
|
const targetTimestamp = message.get('sent_at') || message.get('timestamp');
|
|
strictAssert(
|
|
targetTimestamp,
|
|
`enqueueReactionForSend: message ${message.idForLogging()} had no timestamp`
|
|
);
|
|
|
|
const timestamp = Date.now();
|
|
const messageConversation = message.getConversation();
|
|
strictAssert(
|
|
messageConversation,
|
|
'enqueueReactionForSend: No conversation extracted from target message'
|
|
);
|
|
|
|
const targetConversation =
|
|
isStory(message.attributes) &&
|
|
isDirectConversation(messageConversation.attributes)
|
|
? window.ConversationController.get(targetAuthorUuid)
|
|
: messageConversation;
|
|
strictAssert(
|
|
targetConversation,
|
|
'enqueueReactionForSend: Did not find a targetConversation'
|
|
);
|
|
|
|
const storyMessage = isStory(message.attributes)
|
|
? message.attributes
|
|
: undefined;
|
|
|
|
// Only used in story scenarios, where we use a whole message to represent the reaction
|
|
const storyReactionMessage = storyMessage
|
|
? new window.Whisper.Message({
|
|
id: UUID.generate().toString(),
|
|
type: 'outgoing',
|
|
conversationId: targetConversation.id,
|
|
sent_at: timestamp,
|
|
received_at: incrementMessageCounter(),
|
|
received_at_ms: timestamp,
|
|
timestamp,
|
|
expireTimer: targetConversation.get('expireTimer'),
|
|
sendStateByConversationId: zipObject(
|
|
targetConversation.getMemberConversationIds(),
|
|
repeat({
|
|
status: SendStatus.Pending,
|
|
updatedAt: Date.now(),
|
|
})
|
|
),
|
|
storyId: message.id,
|
|
storyReaction: {
|
|
emoji,
|
|
targetAuthorUuid,
|
|
targetTimestamp,
|
|
},
|
|
})
|
|
: undefined;
|
|
|
|
const reaction = new ReactionModel({
|
|
emoji,
|
|
fromId: window.ConversationController.getOurConversationIdOrThrow(),
|
|
remove,
|
|
source: ReactionSource.FromThisDevice,
|
|
storyReactionMessage,
|
|
targetAuthorUuid,
|
|
targetTimestamp,
|
|
timestamp,
|
|
});
|
|
|
|
await message.handleReaction(reaction, { storyMessage });
|
|
}
|