Don't change left pane preview or order when someone leaves group

This commit is contained in:
Scott Nonnenberg 2021-01-20 09:31:44 -08:00 committed by GitHub
parent 1356625391
commit be9721c72d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 121 additions and 45 deletions

View file

@ -3,6 +3,9 @@
describe('Conversations', () => { describe('Conversations', () => {
it('updates lastMessage even in race conditions with db', async () => { it('updates lastMessage even in race conditions with db', async () => {
const ourNumber = '+15550000000';
const ourUuid = window.getGuid();
// Creating a fake conversation // Creating a fake conversation
const conversation = new window.Whisper.Conversation({ const conversation = new window.Whisper.Conversation({
id: '8c45efca-67a4-4026-b990-9537d5d1a08f', id: '8c45efca-67a4-4026-b990-9537d5d1a08f',
@ -12,6 +15,13 @@ describe('Conversations', () => {
}); });
const destinationE164 = '+15557654321'; const destinationE164 = '+15557654321';
window.textsecure.storage.user.setNumberAndDeviceId(
ourNumber,
2,
'my device'
);
window.textsecure.storage.user.setUuidAndDeviceId(ourUuid, 2);
window.ConversationController._initialFetchComplete = true;
// Creating a fake message // Creating a fake message
const now = Date.now(); const now = Date.now();

View file

@ -3089,11 +3089,21 @@ export class ConversationModel extends window.Backbone.Model<
return; return;
} }
const ourConversationId = window.ConversationController.getOurConversationId();
if (!ourConversationId) {
throw new Error('updateLastMessage: Failed to fetch ourConversationId');
}
const conversationId = this.id;
let [previewMessage, activityMessage] = await Promise.all([ let [previewMessage, activityMessage] = await Promise.all([
window.Signal.Data.getLastConversationPreview(this.id, { window.Signal.Data.getLastConversationPreview({
conversationId,
ourConversationId,
Message: window.Whisper.Message, Message: window.Whisper.Message,
}), }),
window.Signal.Data.getLastConversationActivity(this.id, { window.Signal.Data.getLastConversationActivity({
conversationId,
ourConversationId,
Message: window.Whisper.Message, Message: window.Whisper.Message,
}), }),
]); ]);

View file

@ -1031,27 +1031,37 @@ async function getNewerMessagesByConversation(
return new MessageCollection(handleMessageJSON(messages)); return new MessageCollection(handleMessageJSON(messages));
} }
async function getLastConversationActivity( async function getLastConversationActivity({
conversationId: string, conversationId,
options: { ourConversationId,
Message: typeof MessageModel; Message,
} }: {
): Promise<MessageModel | undefined> { conversationId: string;
const { Message } = options; ourConversationId: string;
const result = await channels.getLastConversationActivity(conversationId); Message: typeof MessageModel;
}): Promise<MessageModel | undefined> {
const result = await channels.getLastConversationActivity({
conversationId,
ourConversationId,
});
if (result) { if (result) {
return new Message(result); return new Message(result);
} }
return undefined; return undefined;
} }
async function getLastConversationPreview( async function getLastConversationPreview({
conversationId: string, conversationId,
options: { ourConversationId,
Message: typeof MessageModel; Message,
} }: {
): Promise<MessageModel | undefined> { conversationId: string;
const { Message } = options; ourConversationId: string;
const result = await channels.getLastConversationPreview(conversationId); Message: typeof MessageModel;
}): Promise<MessageModel | undefined> {
const result = await channels.getLastConversationPreview({
conversationId,
ourConversationId,
});
if (result) { if (result) {
return new Message(result); return new Message(result);
} }

View file

@ -225,12 +225,14 @@ export type ServerInterface = DataInterface & {
conversationId: string, conversationId: string,
options?: { limit?: number; receivedAt?: number; sentAt?: number } options?: { limit?: number; receivedAt?: number; sentAt?: number }
) => Promise<Array<MessageTypeUnhydrated>>; ) => Promise<Array<MessageTypeUnhydrated>>;
getLastConversationActivity: ( getLastConversationActivity: (options: {
conversationId: string conversationId: string;
) => Promise<MessageType | undefined>; ourConversationId: string;
getLastConversationPreview: ( }) => Promise<MessageType | undefined>;
conversationId: string getLastConversationPreview: (options: {
) => Promise<MessageType | undefined>; conversationId: string;
ourConversationId: string;
}) => Promise<MessageType | undefined>;
getNextExpiringMessage: () => Promise<MessageType>; getNextExpiringMessage: () => Promise<MessageType>;
getNextTapToViewMessageToAgeOut: () => Promise<MessageType>; getNextTapToViewMessageToAgeOut: () => Promise<MessageType>;
getOutgoingWithoutExpiresAt: () => Promise<Array<MessageType>>; getOutgoingWithoutExpiresAt: () => Promise<Array<MessageType>>;
@ -323,18 +325,16 @@ export type ClientInterface = DataInterface & {
MessageCollection: typeof MessageModelCollectionType; MessageCollection: typeof MessageModelCollectionType;
} }
) => Promise<MessageModelCollectionType>; ) => Promise<MessageModelCollectionType>;
getLastConversationActivity: ( getLastConversationActivity: (options: {
conversationId: string, conversationId: string;
options: { ourConversationId: string;
Message: typeof MessageModel; Message: typeof MessageModel;
} }) => Promise<MessageModel | undefined>;
) => Promise<MessageModel | undefined>; getLastConversationPreview: (options: {
getLastConversationPreview: ( conversationId: string;
conversationId: string, ourConversationId: string;
options: { Message: typeof MessageModel;
Message: typeof MessageModel; }) => Promise<MessageModel | undefined>;
}
) => Promise<MessageModel | undefined>;
getNextExpiringMessage: (options: { getNextExpiringMessage: (options: {
Message: typeof MessageModel; Message: typeof MessageModel;
}) => Promise<MessageModel | null>; }) => Promise<MessageModel | null>;

View file

@ -2795,19 +2795,44 @@ async function getNewestMessageForConversation(conversationId: string) {
return row; return row;
} }
async function getLastConversationActivity( async function getLastConversationActivity({
conversationId: string conversationId,
): Promise<MessageType | null> { ourConversationId,
}: {
conversationId: string;
ourConversationId: string;
}): Promise<MessageType | null> {
const db = getInstance(); const db = getInstance();
const row = await db.get( const row = await db.get(
`SELECT * FROM messages WHERE `SELECT * FROM messages WHERE
conversationId = $conversationId AND conversationId = $conversationId AND
(type IS NULL OR type NOT IN ('profile-change', 'verified-change', 'message-history-unsynced', 'keychange', 'group-v1-migration')) AND (type IS NULL
(json_extract(json, '$.expirationTimerUpdate.fromSync') IS NULL OR json_extract(json, '$.expirationTimerUpdate.fromSync') != 1) OR
type NOT IN (
'profile-change',
'verified-change',
'message-history-unsynced',
'keychange',
'group-v1-migration'
)
) AND
(
json_extract(json, '$.expirationTimerUpdate.fromSync') IS NULL
OR
json_extract(json, '$.expirationTimerUpdate.fromSync') != 1
) AND NOT
(
type = 'group-v2-change' AND
json_extract(json, '$.groupV2Change.from') != $ourConversationId AND
json_extract(json, '$.groupV2Change.details.length') = 1 AND
json_extract(json, '$.groupV2Change.details[0].type') != 'member-remove' AND
json_extract(json, '$.groupV2Change.details[0].conversationId') != $ourConversationId
)
ORDER BY received_at DESC, sent_at DESC ORDER BY received_at DESC, sent_at DESC
LIMIT 1;`, LIMIT 1;`,
{ {
$conversationId: conversationId, $conversationId: conversationId,
$ourConversationId: ourConversationId,
} }
); );
@ -2817,18 +2842,39 @@ async function getLastConversationActivity(
return jsonToObject(row.json); return jsonToObject(row.json);
} }
async function getLastConversationPreview( async function getLastConversationPreview({
conversationId: string conversationId,
): Promise<MessageType | null> { ourConversationId,
}: {
conversationId: string;
ourConversationId: string;
}): Promise<MessageType | null> {
const db = getInstance(); const db = getInstance();
const row = await db.get( const row = await db.get(
`SELECT * FROM messages WHERE `SELECT * FROM messages WHERE
conversationId = $conversationId AND conversationId = $conversationId AND
(type IS NULL OR type NOT IN ('profile-change', 'verified-change', 'message-history-unsynced', 'group-v1-migration')) (
type IS NULL
OR
type NOT IN (
'profile-change',
'verified-change',
'message-history-unsynced',
'group-v1-migration'
)
) AND NOT
(
type = 'group-v2-change' AND
json_extract(json, '$.groupV2Change.from') != $ourConversationId AND
json_extract(json, '$.groupV2Change.details.length') = 1 AND
json_extract(json, '$.groupV2Change.details[0].type') != 'member-remove' AND
json_extract(json, '$.groupV2Change.details[0].conversationId') != $ourConversationId
)
ORDER BY received_at DESC, sent_at DESC ORDER BY received_at DESC, sent_at DESC
LIMIT 1;`, LIMIT 1;`,
{ {
$conversationId: conversationId, $conversationId: conversationId,
$ourConversationId: ourConversationId,
} }
); );