Refactor outbound delivery state
This commit is contained in:
parent
831ec98418
commit
9c48a95eb5
29 changed files with 3200 additions and 697 deletions
|
@ -3,13 +3,15 @@
|
|||
|
||||
/* eslint-disable max-classes-per-file */
|
||||
|
||||
import { union } from 'lodash';
|
||||
import { isEqual } from 'lodash';
|
||||
import { Collection, Model } from 'backbone';
|
||||
|
||||
import { ConversationModel } from '../models/conversations';
|
||||
import { MessageModel } from '../models/messages';
|
||||
import { MessageModelCollectionType } from '../model-types.d';
|
||||
import { isIncoming } from '../state/selectors/message';
|
||||
import { getOwn } from '../util/getOwn';
|
||||
import { SendActionType, sendStateReducer } from '../messages/MessageSendState';
|
||||
|
||||
type DeliveryReceiptAttributesType = {
|
||||
timestamp: number;
|
||||
|
@ -82,48 +84,67 @@ export class DeliveryReceipts extends Collection<DeliveryReceiptModel> {
|
|||
}
|
||||
|
||||
async onReceipt(receipt: DeliveryReceiptModel): Promise<void> {
|
||||
try {
|
||||
const messages = await window.Signal.Data.getMessagesBySentAt(
|
||||
receipt.get('timestamp'),
|
||||
{
|
||||
MessageCollection: window.Whisper.MessageCollection,
|
||||
}
|
||||
);
|
||||
const deliveredTo = receipt.get('deliveredTo');
|
||||
const timestamp = receipt.get('timestamp');
|
||||
|
||||
const message = await getTargetMessage(
|
||||
receipt.get('deliveredTo'),
|
||||
messages
|
||||
);
|
||||
try {
|
||||
const messages = await window.Signal.Data.getMessagesBySentAt(timestamp, {
|
||||
MessageCollection: window.Whisper.MessageCollection,
|
||||
});
|
||||
|
||||
const message = await getTargetMessage(deliveredTo, messages);
|
||||
if (!message) {
|
||||
window.log.info(
|
||||
'No message for delivery receipt',
|
||||
receipt.get('deliveredTo'),
|
||||
receipt.get('timestamp')
|
||||
deliveredTo,
|
||||
timestamp
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const deliveries = message.get('delivered') || 0;
|
||||
const deliveredTo = message.get('delivered_to') || [];
|
||||
const expirationStartTimestamp = message.get('expirationStartTimestamp');
|
||||
message.set({
|
||||
delivered_to: union(deliveredTo, [receipt.get('deliveredTo')]),
|
||||
delivered: deliveries + 1,
|
||||
expirationStartTimestamp: expirationStartTimestamp || Date.now(),
|
||||
sent: true,
|
||||
});
|
||||
const oldSendStateByConversationId =
|
||||
message.get('sendStateByConversationId') || {};
|
||||
const oldSendState = getOwn(oldSendStateByConversationId, deliveredTo);
|
||||
if (oldSendState) {
|
||||
const newSendState = sendStateReducer(oldSendState, {
|
||||
type: SendActionType.GotDeliveryReceipt,
|
||||
updatedAt: timestamp,
|
||||
});
|
||||
|
||||
window.Signal.Util.queueUpdateMessage(message.attributes);
|
||||
// The send state may not change. This can happen if the message was marked read
|
||||
// before we got the delivery receipt, or if we got double delivery receipts, or
|
||||
// things like that.
|
||||
if (!isEqual(oldSendState, newSendState)) {
|
||||
message.set('sendStateByConversationId', {
|
||||
...oldSendStateByConversationId,
|
||||
[deliveredTo]: newSendState,
|
||||
});
|
||||
|
||||
// notify frontend listeners
|
||||
const conversation = window.ConversationController.get(
|
||||
message.get('conversationId')
|
||||
);
|
||||
const updateLeftPane = conversation
|
||||
? conversation.debouncedUpdateLastMessage
|
||||
: undefined;
|
||||
if (updateLeftPane) {
|
||||
updateLeftPane();
|
||||
await window.Signal.Data.updateMessageSendState({
|
||||
messageId: message.id,
|
||||
destinationConversationId: deliveredTo,
|
||||
...newSendState,
|
||||
});
|
||||
|
||||
// notify frontend listeners
|
||||
const conversation = window.ConversationController.get(
|
||||
message.get('conversationId')
|
||||
);
|
||||
const updateLeftPane = conversation
|
||||
? conversation.debouncedUpdateLastMessage
|
||||
: undefined;
|
||||
if (updateLeftPane) {
|
||||
updateLeftPane();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
window.log.warn(
|
||||
`Got a delivery receipt from someone (${deliveredTo}), but the message (sent at ${message.get(
|
||||
'sent_at'
|
||||
)}) wasn't sent to them. It was sent to ${
|
||||
Object.keys(oldSendStateByConversationId).length
|
||||
} recipients`
|
||||
);
|
||||
}
|
||||
|
||||
this.remove(receipt);
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
|
||||
/* eslint-disable max-classes-per-file */
|
||||
|
||||
import { isEqual } from 'lodash';
|
||||
import { Collection, Model } from 'backbone';
|
||||
|
||||
import { ConversationModel } from '../models/conversations';
|
||||
import { MessageModel } from '../models/messages';
|
||||
import { MessageModelCollectionType } from '../model-types.d';
|
||||
import { isOutgoing } from '../state/selectors/message';
|
||||
import { getOwn } from '../util/getOwn';
|
||||
import { SendActionType, sendStateReducer } from '../messages/MessageSendState';
|
||||
|
||||
type ReadReceiptAttributesType = {
|
||||
reader: string;
|
||||
|
@ -86,46 +89,64 @@ export class ReadReceipts extends Collection<ReadReceiptModel> {
|
|||
}
|
||||
|
||||
async onReceipt(receipt: ReadReceiptModel): Promise<void> {
|
||||
const reader = receipt.get('reader');
|
||||
const timestamp = receipt.get('timestamp');
|
||||
|
||||
try {
|
||||
const messages = await window.Signal.Data.getMessagesBySentAt(
|
||||
receipt.get('timestamp'),
|
||||
{
|
||||
MessageCollection: window.Whisper.MessageCollection,
|
||||
}
|
||||
);
|
||||
const messages = await window.Signal.Data.getMessagesBySentAt(timestamp, {
|
||||
MessageCollection: window.Whisper.MessageCollection,
|
||||
});
|
||||
|
||||
const message = await getTargetMessage(receipt.get('reader'), messages);
|
||||
|
||||
if (!message) {
|
||||
window.log.info(
|
||||
'No message for read receipt',
|
||||
receipt.get('reader'),
|
||||
receipt.get('timestamp')
|
||||
);
|
||||
window.log.info('No message for read receipt', reader, timestamp);
|
||||
return;
|
||||
}
|
||||
|
||||
const readBy = message.get('read_by') || [];
|
||||
const expirationStartTimestamp = message.get('expirationStartTimestamp');
|
||||
const oldSendStateByConversationId =
|
||||
message.get('sendStateByConversationId') || {};
|
||||
const oldSendState = getOwn(oldSendStateByConversationId, reader);
|
||||
if (oldSendState) {
|
||||
const newSendState = sendStateReducer(oldSendState, {
|
||||
type: SendActionType.GotReadReceipt,
|
||||
updatedAt: timestamp,
|
||||
});
|
||||
|
||||
readBy.push(receipt.get('reader'));
|
||||
message.set({
|
||||
read_by: readBy,
|
||||
expirationStartTimestamp: expirationStartTimestamp || Date.now(),
|
||||
sent: true,
|
||||
});
|
||||
// The send state may not change. This can happen if we get read receipts after
|
||||
// we get viewed receipts, or if we get double read receipts, or things like
|
||||
// that.
|
||||
if (!isEqual(oldSendState, newSendState)) {
|
||||
message.set('sendStateByConversationId', {
|
||||
...oldSendStateByConversationId,
|
||||
[reader]: newSendState,
|
||||
});
|
||||
|
||||
window.Signal.Util.queueUpdateMessage(message.attributes);
|
||||
await window.Signal.Data.updateMessageSendState({
|
||||
messageId: message.id,
|
||||
destinationConversationId: reader,
|
||||
...newSendState,
|
||||
});
|
||||
|
||||
// notify frontend listeners
|
||||
const conversation = window.ConversationController.get(
|
||||
message.get('conversationId')
|
||||
);
|
||||
const updateLeftPane = conversation
|
||||
? conversation.debouncedUpdateLastMessage
|
||||
: undefined;
|
||||
if (updateLeftPane) {
|
||||
updateLeftPane();
|
||||
// notify frontend listeners
|
||||
const conversation = window.ConversationController.get(
|
||||
message.get('conversationId')
|
||||
);
|
||||
const updateLeftPane = conversation
|
||||
? conversation.debouncedUpdateLastMessage
|
||||
: undefined;
|
||||
if (updateLeftPane) {
|
||||
updateLeftPane();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
window.log.warn(
|
||||
`Got a read receipt from someone (${reader}), but the message (sent at ${message.get(
|
||||
'sent_at'
|
||||
)}) wasn't sent to them. It was sent to ${
|
||||
Object.keys(oldSendStateByConversationId).length
|
||||
} recipients`
|
||||
);
|
||||
}
|
||||
|
||||
this.remove(receipt);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue