Skip to content

Commit

Permalink
fix: unarchived conversation is missing after reload [WPB-3753] (#15580)
Browse files Browse the repository at this point in the history
* fix: unarchived conversation is missing after reload

* refactor: add comment and rename var

* test: add cases to mergeConversations method

* refactor: clarify var names
  • Loading branch information
PatrykBuniX authored Aug 10, 2023
1 parent 259dfb9 commit 3e10832
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 32 deletions.
59 changes: 58 additions & 1 deletion src/script/conversation/ConversationMapper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ describe('ConversationMapper', () => {
});
});

describe('mergeConversation', () => {
describe('mergeConversations', () => {
function getDataWithReadReceiptMode(
localReceiptMode: RECEIPT_MODE,
remoteReceiptMode: RECEIPT_MODE,
Expand Down Expand Up @@ -541,6 +541,63 @@ describe('ConversationMapper', () => {
});
});

it('returns the local data if the remote data is not present', () => {
const localData: Partial<ConversationDatabaseData> = {
archived_state: false,
archived_timestamp: 1487239601118,
cleared_timestamp: 0,
ephemeral_timer: 0,
global_message_timer: 0,
id: 'de7466b0-985c-4dc3-ad57-17877db45b4c',
is_guest: false,
is_managed: false,
last_event_timestamp: 1488387380633,
last_read_timestamp: 1488387380633,
last_server_timestamp: 1488387380633,
muted_state: NOTIFICATION_STATE.EVERYTHING,
muted_timestamp: 0,
name: 'Family Gathering',
others: ['532af01e-1e24-4366-aacf-33b67d4ee376'],
receipt_mode: RECEIPT_MODE.ON,
status: 0,
team_id: '5316fe03-24ee-4b19-b789-6d026bd3ce5f',
type: 2,
verification_state: 0,
};

const [merged_conversation] = ConversationMapper.mergeConversations(
[localData] as ConversationDatabaseData[],
{found: []} as RemoteConversations,
);

expect(merged_conversation).toEqual(localData);
});

it('returns the remote data if the local data is not present', () => {
const [merged_conversation] = ConversationMapper.mergeConversations([], {
found: [remoteData],
} as RemoteConversations);

const mergedConversation = {
accessModes: remoteData.access,
archived_state: false,
archived_timestamp: 1487239601118,
creator: '532af01e-1e24-4366-aacf-33b67d4ee376',
id: 'de7466b0-985c-4dc3-ad57-17877db45b4c',
last_event_timestamp: 1,
last_server_timestamp: 1,
muted_state: 0,
muted_timestamp: 0,
name: 'Family Gathering',
others: ['532af01e-1e24-4366-aacf-33b67d4ee376'],
roles: {},
team_id: '5316fe03-24ee-4b19-b789-6d026bd3ce5f',
type: 2,
};

expect(merged_conversation).toEqual(mergedConversation);
});

it('updates local archive and muted timestamps if time of remote data is newer', () => {
const localData: Partial<ConversationDatabaseData> = {
archived_state: false,
Expand Down
67 changes: 36 additions & 31 deletions src/script/conversation/ConversationMapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,11 @@ import {
DefaultConversationRoleName,
RemoteConversations,
} from '@wireapp/api-client/lib/conversation';
import {QualifiedId} from '@wireapp/api-client/lib/user';
import ko from 'knockout';
import {isObject} from 'underscore';

import {LegalHoldStatus} from '@wireapp/protocol-messaging';

import {matchQualifiedIds, QualifiedEntity} from 'Util/QualifiedId';

import {ACCESS_STATE} from './AccessState';
import {ConversationStatus} from './ConversationStatus';

Expand Down Expand Up @@ -296,40 +293,48 @@ export class ConversationMapper {
return conversationEntity;
}

/**
* Will merge the locally stored conversations with the new conversations fetched from the backend.
* @param localConversations locally stored conversations
* @param remoteConversations new conversations fetched from backend
* @returns the new conversations from backend merged with the locally stored conversations
*/
static mergeConversations(
localConversations: ConversationDatabaseData[],
remoteConversations: RemoteConversations,
): ConversationDatabaseData[] {
localConversations = localConversations.filter(conversationData => conversationData);

const failedConversations = (remoteConversations.failed ?? []).reduce(
(prev: ConversationDatabaseData[], curr: QualifiedId) => {
const convo = localConversations.find(conversationId => matchQualifiedIds(conversationId, curr));
return convo ? [...prev, convo] : prev;
},
[],
);
const foundRemoteConversations = remoteConversations.found;

const localArchives = localConversations.filter(
conversationData =>
conversationData.archived_state &&
remoteConversations.found?.findIndex(remote => remote.qualified_id.id === conversationData.id) === -1,
);
if (!foundRemoteConversations) {
return localConversations;
}

const foundRemoteConversations = remoteConversations.found.map(
(remoteConversationData: ConversationBackendData, index: number) => {
const remoteConversationId: QualifiedEntity = remoteConversationData.qualified_id || {
domain: '',
id: remoteConversationData.id,
};
const localConversationData =
localConversations.find(conversationId => matchQualifiedIds(conversationId, remoteConversationId)) ||
(remoteConversationId as ConversationDatabaseData);

return this.mergeSingleConversation(localConversationData, remoteConversationData, index);
},
);
return [...foundRemoteConversations, ...failedConversations, ...localArchives];
const conversationsMap = new Map<string, ConversationDatabaseData>();

for (const localConversation of localConversations) {
const conversationId = localConversation.qualified_id?.id || localConversation.id;
conversationsMap.set(conversationId, localConversation);
}

for (let i = 0; i < foundRemoteConversations.length; i++) {
const remoteConversation = foundRemoteConversations[i];
const conversationId = remoteConversation.qualified_id?.id || remoteConversation.id;
const localConversation = conversationsMap.get(conversationId);

if (localConversation) {
conversationsMap.set(conversationId, this.mergeSingleConversation(localConversation, remoteConversation, i));
continue;
}

const localConversationData = (remoteConversation.qualified_id || {
id: conversationId,
domain: '',
}) as ConversationDatabaseData;

conversationsMap.set(conversationId, this.mergeSingleConversation(localConversationData, remoteConversation, i));
}

return Array.from(conversationsMap.values());
}

/**
Expand Down

0 comments on commit 3e10832

Please sign in to comment.