Skip to content

Commit

Permalink
Revert "fix(map-reactions/message-saga): improve mapping of reactions…
Browse files Browse the repository at this point in the history
… to mess…"

This reverts commit c62819f.
  • Loading branch information
domw30 authored Nov 5, 2024
1 parent dc880e3 commit 6cac9b4
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 101 deletions.
10 changes: 1 addition & 9 deletions src/store/messages/saga.fetch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,7 @@ describe(fetch, () => {
const messageResponse = { hasMore: false, messages: [] };

const { storeState } = await subject(fetch, { payload: { channelId: channel.id } })
.provide([
[matchers.call.fn(chatClient.getMessagesByChannelId), messageResponse],
[matchers.call.fn(mapMessagesAndPreview), messageResponse.messages],
])
.provide([[matchers.call.fn(chatClient.getMessagesByChannelId), messageResponse]])
.withReducer(rootReducer, initialChannelState(channel))
.run();

Expand All @@ -65,12 +62,8 @@ describe(fetch, () => {

it('sets hasLoadedMessages on channel', async () => {
const channel = { id: 'channel-id', hasLoadedMessages: false };
const messageResponse = { hasMore: false, messages: [] };

const { storeState } = await subject(fetch, { payload: { channelId: channel.id } })
.provide([
[matchers.call.fn(mapMessagesAndPreview), messageResponse.messages],
])
.withReducer(rootReducer, initialChannelState(channel))
.run();

Expand All @@ -93,7 +86,6 @@ describe(fetch, () => {
.withReducer(rootReducer, initialState as any)
.provide([
[call([chatClient, chatClient.getMessagesByChannelId], channel.id, referenceTimestamp), messageResponse],
[matchers.call.fn(mapMessagesAndPreview), messageResponse.messages],
])
.run();

Expand Down
51 changes: 0 additions & 51 deletions src/store/messages/saga.receiveNewMessage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { denormalize as denormalizeChannel } from '../channels';
import { expectSaga, stubResponse } from '../../test/saga';
import { markConversationAsRead } from '../channels/saga';
import { StoreBuilder } from '../test/store';
import { getMessageEmojiReactions } from '../../lib/chat';

describe(receiveNewMessage, () => {
function subject(...args: Parameters<typeof expectSaga>) {
Expand All @@ -30,11 +29,7 @@ describe(receiveNewMessage, () => {
const initialState = new StoreBuilder().withConversationList({ id: channelId, messages: existingMessages });

const { storeState } = await subject(receiveNewMessage, { payload: { channelId, message } })
.provide([
stubResponse(call(getMessageEmojiReactions, channelId), [{}]),
])
.withReducer(rootReducer, initialState.build())

.run();

const channel = denormalizeChannel(channelId, storeState);
Expand All @@ -50,9 +45,6 @@ describe(receiveNewMessage, () => {
.withUsers({ userId: 'user-1', matrixId: 'matrix-id', firstName: 'the real user' });

const { storeState } = await subject(receiveNewMessage, { payload: { channelId, message } })
.provide([
stubResponse(call(getMessageEmojiReactions, channelId), [{}]),
])
.withReducer(rootReducer, initialState.build())
.run();

Expand All @@ -68,7 +60,6 @@ describe(receiveNewMessage, () => {

const { storeState } = await subject(receiveNewMessage, { payload: { channelId, message } })
.provide([
stubResponse(call(getMessageEmojiReactions, channelId), [{}]),
stubResponse(call(getPreview, 'www.google.com'), stubPreview),
])
.withReducer(rootReducer, initialState.build())
Expand All @@ -78,25 +69,6 @@ describe(receiveNewMessage, () => {
expect(channel.messages[0].preview).toEqual(stubPreview);
});

it('adds the reactions to the message', async () => {
const channelId = 'channel-id';
const message = { id: 'message-id', message: 'www.google.com' };
const stubPreview = { id: 'simulated-preview' };
const stubReactions = [{ eventId: 'message-id', key: '😂' }];
const initialState = new StoreBuilder().withConversationList({ id: channelId });

const { storeState } = await subject(receiveNewMessage, { payload: { channelId, message } })
.provide([
stubResponse(call(getMessageEmojiReactions, channelId), stubReactions),
stubResponse(call(getPreview, 'www.google.com'), stubPreview),
])
.withReducer(rootReducer, initialState.build())
.run();

const channel = denormalizeChannel(channelId, storeState);
expect(channel.messages[0].reactions).toEqual({ '😂': 1 });
});

it('does nothing if the channel does not exist', async () => {
const channelId = 'non-existing-channel-id';
const initialState = new StoreBuilder().withConversationList({ id: 'other-channel' });
Expand All @@ -110,17 +82,13 @@ describe(receiveNewMessage, () => {
it('favors the new version if message already exists', async () => {
const channelId = 'channel-id';
const message = { id: 'new-message', message: 'the new message' };

const existingMessages = [
{ id: 'new-message', message: 'message_0001' },
{ id: 'other-message', message: 'message_0002' },
] as any;
const initialState = new StoreBuilder().withConversationList({ id: channelId, messages: existingMessages });

const { storeState } = await subject(receiveNewMessage, { payload: { channelId, message } })
.provide([
stubResponse(call(getMessageEmojiReactions, channelId), [{}]),
])
.withReducer(rootReducer, initialState.build())
.run();

Expand All @@ -134,9 +102,6 @@ describe(receiveNewMessage, () => {
const conversationState = new StoreBuilder().withConversationList({ id: 'channel-id' });

await subject(receiveNewMessage, { payload: { channelId: 'channel-id', message } })
.provide([
stubResponse(call(getMessageEmojiReactions, 'channel-id'), [{}]),
])
.withReducer(rootReducer, conversationState.build())
.not.call(markConversationAsRead, 'channel-id')
.run();
Expand All @@ -160,9 +125,6 @@ describe(receiveNewMessage, () => {
});

const { storeState } = await subject(receiveNewMessage, { payload: { channelId, message } })
.provide([
stubResponse(call(getMessageEmojiReactions, channelId), [{}]),
])
.withReducer(rootReducer, initialState.build())
.run();

Expand All @@ -187,9 +149,6 @@ describe(receiveNewMessage, () => {
});

const { storeState } = await subject(receiveNewMessage, { payload: { channelId, message } })
.provide([
stubResponse(call(getMessageEmojiReactions, channelId), [{}]),
])
.withReducer(rootReducer, initialState.build())
.run();

Expand Down Expand Up @@ -218,9 +177,6 @@ describe(receiveNewMessage, () => {
const initialState = new StoreBuilder().withConversationList({ id: channelId, messages: existingMessages });

const { storeState } = await subject(batchedReceiveNewMessage, eventPayloads)
.provide([
stubResponse(call(getMessageEmojiReactions, channelId), [{}]),
])
.withReducer(rootReducer, initialState.build())
.run();

Expand All @@ -246,10 +202,6 @@ describe(receiveNewMessage, () => {
);

const { storeState } = await subject(batchedReceiveNewMessage, eventPayloads)
.provide([
stubResponse(call(getMessageEmojiReactions, channelId1), [{}]),
stubResponse(call(getMessageEmojiReactions, channelId2), [{}]),
])
.withReducer(rootReducer, initialState.build())
.run();

Expand All @@ -274,9 +226,6 @@ describe(receiveNewMessage, () => {
const initialState = new StoreBuilder().withConversationList({ id: channelId, messages: existingMessages });

const { storeState } = await subject(batchedReceiveNewMessage, eventPayloads)
.provide([
stubResponse(call(getMessageEmojiReactions, channelId), [{}]),
])
.withReducer(rootReducer, initialState.build())
.run();

Expand Down
118 changes: 87 additions & 31 deletions src/store/messages/saga.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
sendBrowserNotification,
receiveUpdateMessage,
replaceOptimisticMessage,
applyEmojiReactions,
onMessageEmojiReactionChange,
updateMessageEmojiReaction,
sendEmojiReaction,
Expand Down Expand Up @@ -288,7 +289,7 @@ describe(receiveUpdateMessage, () => {
const { storeState } = await expectSaga(receiveUpdateMessage, {
payload: { channelId: 'channel-1', message: editedMessage },
})
.provide([...successResponses(), [call(getMessageEmojiReactions, 'channel-1'), [{}]]])
.provide([...successResponses()])
.withReducer(rootReducer, initialState.build())
.run();

Expand All @@ -306,9 +307,7 @@ describe(receiveUpdateMessage, () => {
payload: { channelId: 'channel-1', message: editedMessage },
})
.provide([
[call(getMessageEmojiReactions, 'channel-1'), [{}]],
[call(getPreview, editedMessage.message), preview],

...successResponses(),
])
.withReducer(rootReducer, initialState.build())
Expand All @@ -317,34 +316,6 @@ describe(receiveUpdateMessage, () => {
expect(storeState.normalized.messages[message.id]).toEqual({ ...editedMessage, preview });
});

it('adds the reactions if they exist', async () => {
const message = { id: 8667728016, message: 'original message' };
const editedMessage = { id: 8667728016, message: 'edited message with reaction' };
const reactions = [
{ eventId: 8667728016, key: '😂' },
{ eventId: 8667728016, key: '👍' },
];

const expectedReactions = {
'😂': 1,
'👍': 1,
};

const initialState = new StoreBuilder().withConversationList({ id: 'channel-1', messages: [message] as any });

const { storeState } = await expectSaga(receiveUpdateMessage, {
payload: { channelId: 'channel-1', message: editedMessage },
})
.provide([
[call(getMessageEmojiReactions, 'channel-1'), reactions],
...successResponses(),
])
.withReducer(rootReducer, initialState.build())
.run();

expect(storeState.normalized.messages[message.id]).toEqual({ ...editedMessage, reactions: expectedReactions });
});

function successResponses() {
return [
[
Expand Down Expand Up @@ -421,6 +392,91 @@ describe(replaceOptimisticMessage, () => {
});
});

describe('applyEmojiReactions', () => {
it('applies emoji reactions to messages correctly', async () => {
const roomId = 'room-id';
const messages = [
{ id: 'message-1', reactions: {} },
{ id: 'message-2', reactions: {} },
] as any;

const reactions = [
{ eventId: 'message-1', key: '😲' },
{ eventId: 'message-1', key: '❤️' },
{ eventId: 'message-2', key: '😂' },
{ eventId: 'message-2', key: '❤️' },
];

await expectSaga(applyEmojiReactions, roomId, messages)
.provide([[call(getMessageEmojiReactions, roomId), reactions]])
.run();

expect(messages).toEqual([
{ id: 'message-1', reactions: { '😲': 1, '❤️': 1 } },
{ id: 'message-2', reactions: { '😂': 1, '❤️': 1 } },
]);
});

it('does not modify messages without reactions', async () => {
const roomId = 'room-id';
const messages = [
{ id: 'message-1', reactions: {} },
{ id: 'message-2', reactions: {} },
] as any;

const reactions = [];

await expectSaga(applyEmojiReactions, roomId, messages)
.provide([[call(getMessageEmojiReactions, roomId), reactions]])
.run();

expect(messages).toEqual([
{ id: 'message-1', reactions: {} },
{ id: 'message-2', reactions: {} },
]);
});

it('accumulates reactions for the same key', async () => {
const roomId = 'room-id';
const messages = [
{ id: 'message-1', reactions: {} },
] as any;

const reactions = [
{ eventId: 'message-1', key: '❤️' },
{ eventId: 'message-1', key: '❤️' },
{ eventId: 'message-1', key: '😂' },
];

await expectSaga(applyEmojiReactions, roomId, messages)
.provide([[call(getMessageEmojiReactions, roomId), reactions]])
.run();

expect(messages).toEqual([
{ id: 'message-1', reactions: { '❤️': 2, '😂': 1 } },
]);
});

it('handles reactions when there are no matching messages', async () => {
const roomId = 'room-id';
const messages = [
{ id: 'message-1', reactions: {} },
] as any;

const reactions = [
{ eventId: 'message-2', key: '❤️' },
];

await expectSaga(applyEmojiReactions, roomId, messages)
.provide([[call(getMessageEmojiReactions, roomId), reactions]])
.run();

expect(messages).toEqual([
{ id: 'message-1', reactions: {} },
]);
});
});

describe('onMessageEmojiReactionChange', () => {
it('calls updateMessageEmojiReaction with the correct arguments', async () => {
const roomId = 'room-id';
Expand Down
35 changes: 25 additions & 10 deletions src/store/messages/saga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
MediaType,
MessageSendStatus,
MediaDownloadStatus,
Message,
} from '.';
import { receive as receiveMessage } from './';
import { ConversationStatus, MessagesFetchState, DefaultRoomLabels } from '../channels';
Expand Down Expand Up @@ -120,8 +121,6 @@ export function* getLocalZeroUsersMap() {
}

export function* mapMessagesAndPreview(messages, channelId) {
const reactions = yield call(getMessageEmojiReactions, channelId);

const zeroUsersMap = yield call(mapMessageSenders, messages, channelId);
yield call(mapAdminUserIdToZeroUserId, [{ messages }], zeroUsersMap);

Expand All @@ -134,14 +133,6 @@ export function* mapMessagesAndPreview(messages, channelId) {
if (preview) {
message.preview = preview;
}

const relatedReactions = reactions.filter((reaction) => reaction.eventId === message.id);
if (relatedReactions.length > 0) {
message.reactions = relatedReactions.reduce((acc, reaction) => {
acc[reaction.key] = (acc[reaction.key] || 0) + 1;
return acc;
}, message.reactions || {});
}
}

return messages;
Expand Down Expand Up @@ -175,6 +166,10 @@ export function* fetch(action) {
messages = [...messagesResponse.messages, ...existingMessages];
messages = uniqBy(messages, (m) => m.id ?? m);

if (yield select(_isActive(channelId))) {
yield call(applyEmojiReactions, channelId, messages);
}

yield call(receiveChannel, {
id: channelId,
messages,
Expand Down Expand Up @@ -706,3 +701,23 @@ export function* updateMessageEmojiReaction(roomId, { eventId, key }) {
yield call(receiveChannel, { id: roomId, messages: updatedMessages });
}
}

export function* applyEmojiReactions(roomId: string, messages: Message[]): Generator<any, void, any> {
const reactions = yield call(getMessageEmojiReactions, roomId);

messages.forEach((message) => {
const relatedReactions = reactions.filter((reaction) => {
const messageId = message?.id?.toString();
const eventId = reaction.eventId.toString();
return eventId === messageId;
});

if (relatedReactions.length > 0) {
message.reactions = relatedReactions.reduce((acc, reaction) => {
const key = reaction.key;
acc[key] = (acc[key] || 0) + 1;
return acc;
}, message.reactions || {});
}
});
}

0 comments on commit 6cac9b4

Please sign in to comment.