Sort left pane via receivedAt/receivedAtMs, even via edits

This commit is contained in:
Scott Nonnenberg 2024-03-25 12:21:14 -07:00 committed by GitHub
parent a39e46db5c
commit 6bc6cc64c4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 55 additions and 11 deletions

9
ts/model-types.d.ts vendored
View file

@ -116,7 +116,8 @@ export type MessageReactionType = {
}; };
// Note: when adding to the set of things that can change via edits, sendNormalMessage.ts // Note: when adding to the set of things that can change via edits, sendNormalMessage.ts
// needs more usage of get/setPropForTimestamp. // needs more usage of get/setPropForTimestamp. Also, these fields must match the fields
// in MessageAttributesType.
export type EditHistoryType = { export type EditHistoryType = {
attachments?: Array<AttachmentType>; attachments?: Array<AttachmentType>;
body?: string; body?: string;
@ -126,6 +127,8 @@ export type EditHistoryType = {
quote?: QuotedMessageType; quote?: QuotedMessageType;
sendStateByConversationId?: SendStateByConversationId; sendStateByConversationId?: SendStateByConversationId;
timestamp: number; timestamp: number;
received_at: number;
received_at_ms?: number;
}; };
export type MessageAttributesType = { export type MessageAttributesType = {
@ -152,6 +155,8 @@ export type MessageAttributesType = {
isViewOnce?: boolean; isViewOnce?: boolean;
editHistory?: Array<EditHistoryType>; editHistory?: Array<EditHistoryType>;
editMessageTimestamp?: number; editMessageTimestamp?: number;
editMessageReceivedAt?: number;
editMessageReceivedAtMs?: number;
key_changed?: string; key_changed?: string;
local?: boolean; local?: boolean;
logger?: unknown; logger?: unknown;
@ -334,6 +339,8 @@ export type ConversationAttributesType = {
lastMessagePrefix?: string; lastMessagePrefix?: string;
lastMessageAuthor?: string | null; lastMessageAuthor?: string | null;
lastMessageStatus?: LastMessageStatus | null; lastMessageStatus?: LastMessageStatus | null;
lastMessageReceivedAt?: number;
lastMessageReceivedAtMs?: number;
markedUnread?: boolean; markedUnread?: boolean;
messageCount?: number; messageCount?: number;
messageCountBeforeMessageRequests?: number | null; messageCountBeforeMessageRequests?: number | null;

View file

@ -4173,16 +4173,23 @@ export class ConversationModel extends window.Backbone
return; return;
} }
const currentTimestamp = this.get('timestamp') || null; let timestamp = this.get('timestamp') || null;
let lastMessageReceivedAt = this.get('lastMessageReceivedAt');
let timestamp = currentTimestamp; let lastMessageReceivedAtMs = this.get('lastMessageReceivedAtMs');
if (activityMessage) { if (activityMessage) {
const receivedAt = activityMessage.get('received_at_ms'); timestamp =
timestamp = receivedAt activityMessage.get('editMessageTimestamp') ||
? Math.min(activityMessage.get('sent_at'), receivedAt) activityMessage.get('sent_at') ||
: activityMessage.get('sent_at'); timestamp;
lastMessageReceivedAt =
activityMessage.get('editMessageReceivedAt') ||
activityMessage.get('received_at') ||
lastMessageReceivedAt;
lastMessageReceivedAtMs =
activityMessage.get('editMessageReceivedAtMs') ||
activityMessage.get('received_at_ms') ||
lastMessageReceivedAtMs;
} }
timestamp = timestamp || currentTimestamp;
const notificationData = previewMessage?.getNotificationData(); const notificationData = previewMessage?.getNotificationData();
@ -4196,6 +4203,8 @@ export class ConversationModel extends window.Backbone
(previewMessage (previewMessage
? getMessagePropStatus(previewMessage.attributes, ourConversationId) ? getMessagePropStatus(previewMessage.attributes, ourConversationId)
: null) || null, : null) || null,
lastMessageReceivedAt,
lastMessageReceivedAtMs,
timestamp, timestamp,
lastMessageDeletedForEveryone: previewMessage lastMessageDeletedForEveryone: previewMessage
? previewMessage.get('deletedForEveryone') ? previewMessage.get('deletedForEveryone')

View file

@ -282,6 +282,8 @@ export type ConversationType = ReadonlyDeep<
isVerified?: boolean; isVerified?: boolean;
activeAt?: number; activeAt?: number;
timestamp?: number; timestamp?: number;
lastMessageReceivedAt?: number;
lastMessageReceivedAtMs?: number;
inboxPosition?: number; inboxPosition?: number;
left?: boolean; left?: boolean;
lastMessage?: LastMessageType; lastMessage?: LastMessageType;

View file

@ -303,8 +303,9 @@ const collator = new Intl.Collator();
// phone numbers and contacts from scratch here again. // phone numbers and contacts from scratch here again.
export const _getConversationComparator = () => { export const _getConversationComparator = () => {
return (left: ConversationType, right: ConversationType): number => { return (left: ConversationType, right: ConversationType): number => {
const leftTimestamp = left.timestamp; // These two fields can be sorted with each other; they are timestamps
const rightTimestamp = right.timestamp; const leftTimestamp = left.lastMessageReceivedAtMs || left.timestamp;
const rightTimestamp = right.lastMessageReceivedAtMs || right.timestamp;
if (leftTimestamp && !rightTimestamp) { if (leftTimestamp && !rightTimestamp) {
return -1; return -1;
} }
@ -315,6 +316,19 @@ export const _getConversationComparator = () => {
return rightTimestamp - leftTimestamp; return rightTimestamp - leftTimestamp;
} }
// This field looks like a timestamp, but is actually a counter
const leftCounter = left.lastMessageReceivedAt;
const rightCounter = right.lastMessageReceivedAt;
if (leftCounter && !rightCounter) {
return -1;
}
if (rightCounter && !leftCounter) {
return 1;
}
if (leftCounter && rightCounter && leftCounter !== rightCounter) {
return rightCounter - leftCounter;
}
if ( if (
typeof left.inboxPosition === 'number' && typeof left.inboxPosition === 'number' &&
typeof right.inboxPosition === 'number' typeof right.inboxPosition === 'number'

View file

@ -129,10 +129,14 @@ describe('MessageReceipts', () => {
{ {
sendStateByConversationId: defaultSendState, sendStateByConversationId: defaultSendState,
timestamp: editedSentAt, timestamp: editedSentAt,
received_at: 2,
received_at_ms: Date.now(),
}, },
{ {
sendStateByConversationId: defaultSendState, sendStateByConversationId: defaultSendState,
timestamp: sentAt, timestamp: sentAt,
received_at: 1,
received_at_ms: Date.now(),
}, },
], ],
}; };

View file

@ -186,6 +186,8 @@ export function getConversation(model: ConversationModel): ConversationType {
isVerified: model.isVerified(), isVerified: model.isVerified(),
isFetchingUUID: model.isFetchingUUID, isFetchingUUID: model.isFetchingUUID,
lastMessage: getLastMessage(attributes), lastMessage: getLastMessage(attributes),
lastMessageReceivedAt: attributes.lastMessageReceivedAt,
lastMessageReceivedAtMs: attributes.lastMessageReceivedAtMs,
lastUpdated: dropNull(timestamp), lastUpdated: dropNull(timestamp),
left: Boolean(attributes.left), left: Boolean(attributes.left),
markedUnread: attributes.markedUnread, markedUnread: attributes.markedUnread,

View file

@ -121,6 +121,8 @@ export async function handleEditMessage(
quote: mainMessage.quote, quote: mainMessage.quote,
sendStateByConversationId: { ...mainMessage.sendStateByConversationId }, sendStateByConversationId: { ...mainMessage.sendStateByConversationId },
timestamp: mainMessage.timestamp, timestamp: mainMessage.timestamp,
received_at: mainMessage.received_at,
received_at_ms: mainMessage.received_at_ms,
}, },
]; ];
@ -253,6 +255,8 @@ export async function handleEditMessage(
sendStateByConversationId: sendStateByConversationId:
upgradedEditedMessageData.sendStateByConversationId, upgradedEditedMessageData.sendStateByConversationId,
timestamp: upgradedEditedMessageData.timestamp, timestamp: upgradedEditedMessageData.timestamp,
received_at: upgradedEditedMessageData.received_at,
received_at_ms: upgradedEditedMessageData.received_at_ms,
quote: nextEditedMessageQuote, quote: nextEditedMessageQuote,
}; };
@ -268,6 +272,8 @@ export async function handleEditMessage(
bodyRanges: editedMessage.bodyRanges, bodyRanges: editedMessage.bodyRanges,
editHistory, editHistory,
editMessageTimestamp: upgradedEditedMessageData.timestamp, editMessageTimestamp: upgradedEditedMessageData.timestamp,
editMessageReceivedAt: upgradedEditedMessageData.received_at,
editMessageReceivedAtMs: upgradedEditedMessageData.received_at_ms,
preview: editedMessage.preview, preview: editedMessage.preview,
quote: editedMessage.quote, quote: editedMessage.quote,
}); });