Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hotfix 1174.1 #1176

Merged
merged 18 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ export const onSubmitMessage = async (
account: Account,
selectedContact: ContactPreview,
) => {
// Message can't be empty if no files are selected & its not DELETE msg.
if (
messageView.actionType !== MessageActionType.DELETE &&
!props.filesSelected.length &&
(!props.message || props.message.trim() === '')
) {
return;
}
if (messageView.actionType === MessageActionType.REPLY) {
const referenceMessageHash =
messageView.messageData?.envelop.metadata?.encryptedMessageHash;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,24 +71,26 @@ export class ReceiptDispatcher {
contactAliasName: string,
messageModel: MessageModel,
) {
//We only want to acknowledge messages from type NEW. Every other message type can be neglected for now
const msgIsNew = messageModel.envelop.message.metadata.type === 'NEW';
//We only want to acknowledge messages from type NEW or REPLY. Every other message type can be neglected for now
const shouldAcknowledgeMessage =
messageModel.envelop.message.metadata.type === 'NEW' ||
messageModel.envelop.message.metadata.type === 'REPLY';
//Check if the selected contact is the sender of the message.
// If that is the case we've to acknowledge the message and send a READ_OPENED acknowledgement to the sender
const selectedContactIsSender =
selectedContact?.contactDetails.account.ensName ===
contactAliasName;

//We acknowledge that we've received the message by sending a READ_RECEIVED acknowledgement to the sender
if (msgIsNew) {
if (shouldAcknowledgeMessage) {
await this.sendReceivedReceipte(contactAliasName, messageModel);
console.log('sent received receipt to ', contactAliasName);
}

if (msgIsNew && selectedContactIsSender) {
if (shouldAcknowledgeMessage && selectedContactIsSender) {
// if contact is selected then send READ_OPENED acknowledgement to sender for new message received
await this.sendOpendReceipt(contactAliasName, messageModel);
console.log('sent opend receipt to ', contactAliasName);
console.log('sent opened receipt to ', contactAliasName);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { MessageModel } from '../../useMessage';

export const renderEdit = (messages: MessageModel[]) => {
export const renderEdit = (_messages: MessageModel[]) => {
//Copy messages object to not mutate the original object
const messages: MessageModel[] = [..._messages];
//Before processing the messages have to be sorted ASC by timestamp
messages.sort(
(a, b) =>
a.envelop.message.metadata.timestamp -
b.envelop.message.metadata.timestamp,
);
//To apply insertions we have to find every message that is an edit and find the original message
//A message can be edited multiple times so we always have to find the original message
//A path for a simple edit looks like [NEW, EDIT]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,19 @@ export const renderMessage = (messages: MessageModel[]) => {
const withDeletes = renderDelete(withReadOpened);
const withReactions = renderReactions(withDeletes);
const withReply = renderReply(withReactions);
const withReplyC = renderReply(withReactions);

//Its desirable to have all messages in a conversation sorted by their timestamp. However edited messages are an
//exception to this rule, since they should be displayed in the order they were edited.
// Therefore we sort the messages by their timestamp and then we eventually replace messages that have been edited
//Messages are sorted DESC, so the pagination adds old messages at the end of the array
withReply.sort(
(a, b) =>
b.envelop.message.metadata.timestamp -
a.envelop.message.metadata.timestamp,
);
const withoutEdited = renderEdit(withReply);
//Sort the messages by timestamp DESC to show them in the right order
// withoutEdited.sort(
// (a, b) =>
// b.envelop.message.metadata.timestamp -
// a.envelop.message.metadata.timestamp,
// );

//There a several ways a message can added to the client. I.e via Websocket, multiple DS or from the storage.
//This leads occasionally to duplicates we don't want to display.
const withoutDuplicates = renderDuplicates(withoutEdited);
return withoutDuplicates;
//We reverse the array to display the messages in the right order
return withoutDuplicates.reverse();
};
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ export const handleMessagesFromWebSocket = async (
// Resolve TLD to alias
const contact = contactPreview?.contactDetails.account.ensName!;

console.log('contactPreview MSGWS', contactPreview);

const messageState =
selectedContact?.contactDetails.account.ensName === contact
? MessageState.Read
Expand Down
126 changes: 0 additions & 126 deletions packages/messenger-widget/src/hooks/messages/useMessage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,132 +92,6 @@ describe('useMessage hook test cases', () => {
});
const config: DM3Configuration = configurationContext.dm3Configuration!;

it('should not add empty message', async () => {
const storageContext = getMockedStorageContext({
editMessageBatchAsync: jest.fn(),
storeMessageBatch: jest.fn(),
storeMessage: jest.fn(),
});
const conversationContext = getMockedConversationContext({
selectedContact: getEmptyContact(
'max.eth',
undefined,
false,
0,
[],
),
});
const deliveryServiceContext = getMockedDeliveryServiceContext({
//Add websocket mock
onNewMessage: (cb: Function) => {
console.log('on new message');
},
removeOnNewMessageListener: jest.fn(),
});
const authContext = getMockedAuthContext({});
const tldContext = getMockedTldContext({});

const wrapper = ({ children }: { children: any }) => (
<>
<AuthContext.Provider value={authContext}>
<TLDContext.Provider value={tldContext}>
<StorageContext.Provider value={storageContext}>
<ConversationContext.Provider
value={conversationContext}
>
<DeliveryServiceContext.Provider
value={deliveryServiceContext}
>
{children}
</DeliveryServiceContext.Provider>
</ConversationContext.Provider>
</StorageContext.Provider>
</TLDContext.Provider>
</AuthContext.Provider>
</>
);

const { result } = renderHook(() => useMessage(), {
wrapper,
});
await waitFor(() =>
expect(result.current.contactIsLoading('max.eth')).toBe(false),
);

const messageFactory = MockMessageFactory(sender, receiver, ds1);
const message = await messageFactory.createMessage('');
const addMessageResult = await waitFor(() =>
result.current.addMessage('max.eth', message),
);

expect(addMessageResult).toEqual({
isSuccess: false,
error: 'Message is empty',
});
});
it('should trim message', async () => {
const storageContext = getMockedStorageContext({
editMessageBatchAsync: jest.fn(),
storeMessageBatch: jest.fn(),
storeMessage: jest.fn(),
});
const conversationContext = getMockedConversationContext({
selectedContact: getEmptyContact(
'max.eth',
undefined,
false,
0,
[],
),
});
const deliveryServiceContext = getMockedDeliveryServiceContext({
//Add websocket mock
onNewMessage: (cb: Function) => {
console.log('on new message');
},
removeOnNewMessageListener: jest.fn(),
});
const authContext = getMockedAuthContext({});
const tldContext = getMockedTldContext({});

const wrapper = ({ children }: { children: any }) => (
<>
<AuthContext.Provider value={authContext}>
<TLDContext.Provider value={tldContext}>
<StorageContext.Provider value={storageContext}>
<ConversationContext.Provider
value={conversationContext}
>
<DeliveryServiceContext.Provider
value={deliveryServiceContext}
>
{children}
</DeliveryServiceContext.Provider>
</ConversationContext.Provider>
</StorageContext.Provider>
</TLDContext.Provider>
</AuthContext.Provider>
</>
);

const { result } = renderHook(() => useMessage(), {
wrapper,
});
await waitFor(() =>
expect(result.current.contactIsLoading('max.eth')).toBe(false),
);

const messageFactory = MockMessageFactory(sender, receiver, ds1);
const message = await messageFactory.createMessage(' ');
const addMessageResult = await waitFor(() =>
result.current.addMessage('max.eth', message),
);

expect(addMessageResult).toEqual({
isSuccess: false,
error: 'Message is empty',
});
});
it('should add message', async () => {
Bhupesh-mfsi marked this conversation as resolved.
Show resolved Hide resolved
const storageContext = getMockedStorageContext({
editMessageBatchAsync: jest.fn(),
Expand Down
6 changes: 0 additions & 6 deletions packages/messenger-widget/src/hooks/messages/useMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -276,12 +276,6 @@ export const useMessage = () => {
message: Message,
): Promise<{ isSuccess: boolean; error?: string }> => {
const contact = normalizeEnsName(_contactName);
//If a message is empty it should not be added

if (!message.message || message.message.trim() === '') {
return { isSuccess: false, error: 'Message is empty' };
}

//Find the recipient of the message in the contact list
const recipient = contacts.find(
(c) => c.contactDetails.account.ensName === contact,
Expand Down
Loading