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', () => {
it('updates lastMessage even in race conditions with db', async () => {
const ourNumber = '+15550000000';
const ourUuid = window.getGuid();
// Creating a fake conversation
const conversation = new window.Whisper.Conversation({
id: '8c45efca-67a4-4026-b990-9537d5d1a08f',
@ -12,6 +15,13 @@ describe('Conversations', () => {
});
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
const now = Date.now();

View file

@ -3089,11 +3089,21 @@ export class ConversationModel extends window.Backbone.Model<
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([
window.Signal.Data.getLastConversationPreview(this.id, {
window.Signal.Data.getLastConversationPreview({
conversationId,
ourConversationId,
Message: window.Whisper.Message,
}),
window.Signal.Data.getLastConversationActivity(this.id, {
window.Signal.Data.getLastConversationActivity({
conversationId,
ourConversationId,
Message: window.Whisper.Message,
}),
]);

View file

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

View file

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

View file

@ -2795,19 +2795,44 @@ async function getNewestMessageForConversation(conversationId: string) {
return row;
}
async function getLastConversationActivity(
conversationId: string
): Promise<MessageType | null> {
async function getLastConversationActivity({
conversationId,
ourConversationId,
}: {
conversationId: string;
ourConversationId: string;
}): Promise<MessageType | null> {
const db = getInstance();
const row = await db.get(
`SELECT * FROM messages WHERE
conversationId = $conversationId AND
(type IS NULL 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)
(type IS NULL
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
LIMIT 1;`,
{
$conversationId: conversationId,
$ourConversationId: ourConversationId,
}
);
@ -2817,18 +2842,39 @@ async function getLastConversationActivity(
return jsonToObject(row.json);
}
async function getLastConversationPreview(
conversationId: string
): Promise<MessageType | null> {
async function getLastConversationPreview({
conversationId,
ourConversationId,
}: {
conversationId: string;
ourConversationId: string;
}): Promise<MessageType | null> {
const db = getInstance();
const row = await db.get(
`SELECT * FROM messages WHERE
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
LIMIT 1;`,
{
$conversationId: conversationId,
$ourConversationId: ourConversationId,
}
);