Refactor outbound delivery state
This commit is contained in:
parent
831ec98418
commit
9c48a95eb5
29 changed files with 3200 additions and 697 deletions
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { isNumber, isObject, map, reduce } from 'lodash';
|
||||
import { isNumber, isObject, map, omit, reduce } from 'lodash';
|
||||
import filesize from 'filesize';
|
||||
|
||||
import {
|
||||
|
@ -46,6 +46,15 @@ import {
|
|||
GetConversationByIdType,
|
||||
isMissingRequiredProfileSharing,
|
||||
} from './conversations';
|
||||
import {
|
||||
SendStatus,
|
||||
isDelivered,
|
||||
isMessageJustForMe,
|
||||
isRead,
|
||||
isSent,
|
||||
maxStatus,
|
||||
someSendStatus,
|
||||
} from '../../messages/MessageSendState';
|
||||
|
||||
const THREE_HOURS = 3 * 60 * 60 * 1000;
|
||||
|
||||
|
@ -220,7 +229,9 @@ export function isOutgoing(
|
|||
return message.type === 'outgoing';
|
||||
}
|
||||
|
||||
export function hasErrors(message: MessageAttributesType): boolean {
|
||||
export function hasErrors(
|
||||
message: Pick<MessageAttributesType, 'errors'>
|
||||
): boolean {
|
||||
return message.errors ? message.errors.length > 0 : false;
|
||||
}
|
||||
|
||||
|
@ -358,7 +369,7 @@ export function getPropsForMessage(
|
|||
bodyRanges: processBodyRanges(message.bodyRanges, conversationSelector),
|
||||
canDeleteForEveryone: canDeleteForEveryone(message),
|
||||
canDownload: canDownload(message, conversationSelector),
|
||||
canReply: canReply(message, conversationSelector),
|
||||
canReply: canReply(message, ourConversationId, conversationSelector),
|
||||
contact: getPropsForEmbeddedContact(message, regionCode, accountSelector),
|
||||
conversationColor: conversation?.conversationColor ?? ConversationColors[0],
|
||||
conversationId: message.conversationId,
|
||||
|
@ -382,7 +393,11 @@ export function getPropsForMessage(
|
|||
quote: getPropsForQuote(message, conversationSelector, ourConversationId),
|
||||
reactions,
|
||||
selectedReaction,
|
||||
status: getMessagePropStatus(message, readReceiptSetting),
|
||||
status: getMessagePropStatus(
|
||||
message,
|
||||
ourConversationId,
|
||||
readReceiptSetting
|
||||
),
|
||||
text: createNonBreakingLastSeparator(message.body),
|
||||
textPending: message.bodyPending,
|
||||
timestamp: message.sent_at,
|
||||
|
@ -882,38 +897,54 @@ function createNonBreakingLastSeparator(text?: string): string {
|
|||
}
|
||||
|
||||
export function getMessagePropStatus(
|
||||
message: MessageAttributesType,
|
||||
message: Pick<
|
||||
MessageAttributesType,
|
||||
'type' | 'errors' | 'sendStateByConversationId'
|
||||
>,
|
||||
ourConversationId: string,
|
||||
readReceiptSetting: boolean
|
||||
): LastMessageStatus | undefined {
|
||||
const { sent } = message;
|
||||
const sentTo = message.sent_to || [];
|
||||
|
||||
if (hasErrors(message)) {
|
||||
if (getLastChallengeError(message)) {
|
||||
return 'paused';
|
||||
}
|
||||
if (sent || sentTo.length > 0) {
|
||||
return 'partial-sent';
|
||||
}
|
||||
return 'error';
|
||||
}
|
||||
if (!isOutgoing(message)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const readBy = message.read_by || [];
|
||||
if (readReceiptSetting && readBy.length > 0) {
|
||||
return 'read';
|
||||
}
|
||||
const { delivered } = message;
|
||||
const deliveredTo = message.delivered_to || [];
|
||||
if (delivered || deliveredTo.length > 0) {
|
||||
return 'delivered';
|
||||
}
|
||||
if (sent || sentTo.length > 0) {
|
||||
return 'sent';
|
||||
if (getLastChallengeError(message)) {
|
||||
return 'paused';
|
||||
}
|
||||
|
||||
const { sendStateByConversationId = {} } = message;
|
||||
|
||||
if (isMessageJustForMe(sendStateByConversationId, ourConversationId)) {
|
||||
const status =
|
||||
sendStateByConversationId[ourConversationId]?.status ??
|
||||
SendStatus.Pending;
|
||||
const sent = isSent(status);
|
||||
if (hasErrors(message)) {
|
||||
return sent ? 'partial-sent' : 'error';
|
||||
}
|
||||
return sent ? 'read' : 'sending';
|
||||
}
|
||||
|
||||
const sendStates = Object.values(
|
||||
omit(sendStateByConversationId, ourConversationId)
|
||||
);
|
||||
const highestSuccessfulStatus = sendStates.reduce(
|
||||
(result: SendStatus, { status }) => maxStatus(result, status),
|
||||
SendStatus.Pending
|
||||
);
|
||||
|
||||
if (hasErrors(message)) {
|
||||
return isSent(highestSuccessfulStatus) ? 'partial-sent' : 'error';
|
||||
}
|
||||
if (readReceiptSetting && isRead(highestSuccessfulStatus)) {
|
||||
return 'read';
|
||||
}
|
||||
if (isDelivered(highestSuccessfulStatus)) {
|
||||
return 'delivered';
|
||||
}
|
||||
if (isSent(highestSuccessfulStatus)) {
|
||||
return 'sent';
|
||||
}
|
||||
return 'sending';
|
||||
}
|
||||
|
||||
|
@ -1066,12 +1097,16 @@ function processQuoteAttachment(
|
|||
export function canReply(
|
||||
message: Pick<
|
||||
MessageAttributesType,
|
||||
'conversationId' | 'deletedForEveryone' | 'sent_to' | 'type'
|
||||
| 'conversationId'
|
||||
| 'deletedForEveryone'
|
||||
| 'sendStateByConversationId'
|
||||
| 'type'
|
||||
>,
|
||||
ourConversationId: string,
|
||||
conversationSelector: GetConversationByIdType
|
||||
): boolean {
|
||||
const conversation = getConversation(message, conversationSelector);
|
||||
const { deletedForEveryone, sent_to: sentTo } = message;
|
||||
const { deletedForEveryone, sendStateByConversationId } = message;
|
||||
|
||||
if (!conversation) {
|
||||
return false;
|
||||
|
@ -1100,7 +1135,10 @@ export function canReply(
|
|||
|
||||
// We can reply if this is outgoing and sent to at least one recipient
|
||||
if (isOutgoing(message)) {
|
||||
return (sentTo || []).length > 0;
|
||||
return (
|
||||
isMessageJustForMe(sendStateByConversationId, ourConversationId) ||
|
||||
someSendStatus(omit(sendStateByConversationId, ourConversationId), isSent)
|
||||
);
|
||||
}
|
||||
|
||||
// We can reply to incoming messages
|
||||
|
@ -1188,7 +1226,7 @@ export function getAttachmentsForMessage(
|
|||
}
|
||||
|
||||
export function getLastChallengeError(
|
||||
message: MessageAttributesType
|
||||
message: Pick<MessageAttributesType, 'errors'>
|
||||
): ShallowChallengeError | undefined {
|
||||
const { errors } = message;
|
||||
if (!errors) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue