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

feat: emit message in messageUpdate output #468

Merged
merged 1 commit into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
9 changes: 8 additions & 1 deletion projects/stream-chat-angular/src/lib/channel.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1256,7 +1256,14 @@ describe('ChannelService', () => {
true
);

expect(latestMessage.status).toBe('sending');
expect(channel.state.addMessageSorted).toHaveBeenCalledWith(
jasmine.objectContaining({
status: 'received',
}),
true
);

expect(latestMessage.status).toBe('received');
});

it('should set message state while sending', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ describe('ChannelService - threads', () => {
service.activeChannel$.pipe(first()).subscribe((c) => (channel = c!));
const parentMessage = mockMessage();
parentMessage.id = 'parentId';
const replies = [mockMessage(), mockMessage()];
const replies = [mockMessage(1), mockMessage(2)];
replies.forEach((r) => (r.parent_id = parentMessage.id));
channel.state.threads[parentMessage.id] = replies;
spyOn(channel, 'getReplies').and.resolveTo({
Expand Down
65 changes: 45 additions & 20 deletions projects/stream-chat-angular/src/lib/channel.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
ReplaySubject,
Subscription,
} from 'rxjs';
import { first, map, shareReplay } from 'rxjs/operators';
import { first, map, shareReplay, take } from 'rxjs/operators';
import {
Attachment,
Channel,
Expand Down Expand Up @@ -677,7 +677,8 @@ export class ChannelService<
const channel = this.activeChannelSubject.getValue()!;
preview.readBy = [];
channel.state.addMessageSorted(preview, true);
await this.sendMessageRequest(preview, customData);
const response = await this.sendMessageRequest(preview, customData);
return response;
}

/**
Expand All @@ -704,9 +705,15 @@ export class ChannelService<
async updateMessage(message: StreamMessage<T>) {
const messageToUpdate = { ...message };
delete messageToUpdate.i18n;
await this.chatClientService.chatClient.updateMessage(
const response = await this.chatClientService.chatClient.updateMessage(
messageToUpdate as any as UpdatedMessage<T>
);

const channel = this.channelsSubject
.getValue()
?.find((c) => c.cid === message.cid);

return this.transformToStreamMessage(response.message, channel);
}

/**
Expand Down Expand Up @@ -879,20 +886,24 @@ export class ChannelService<
quoted_message_id: preview.quoted_message_id,
...customData,
} as Message<T>); // TODO: find out why we need typecast here
if (response?.message) {
channel.state.addMessageSorted(
{
...response.message,
status: 'received',
},
true
);
isThreadReply
? this.activeThreadMessagesSubject.next([
...channel.state.threads[preview.parent_id!],
])
: this.activeChannelMessagesSubject.next([...channel.state.messages]);
}
channel.state.addMessageSorted(
{
...response.message,
status: 'received',
},
true
);
isThreadReply
? this.activeThreadMessagesSubject.next([
...channel.state.threads[preview.parent_id!],
])
: this.activeChannelMessagesSubject.next([...channel.state.messages]);
let messages!: StreamMessage<T>[];
(isThreadReply ? this.activeThreadMessages$ : this.activeChannelMessages$)
.pipe(take(1))
.subscribe((m) => (messages = m));
const newMessage = messages[messages.length - 1]!;
return newMessage;
} catch (error) {
const stringError = JSON.stringify(error);
const parsedError: { status?: number } = stringError
Expand All @@ -912,6 +923,12 @@ export class ChannelService<
...channel.state.threads[preview.parent_id!],
])
: this.activeChannelMessagesSubject.next([...channel.state.messages]);
let messages!: StreamMessage<T>[];
(isThreadReply ? this.activeThreadMessages$ : this.activeChannelMessages$)
.pipe(take(1))
.subscribe((m) => (messages = m));
const newMessage = messages[messages.length - 1]!;
return newMessage;
}
}

Expand Down Expand Up @@ -1521,7 +1538,7 @@ export class ChannelService<

private transformToStreamMessage(
message: StreamMessage<T> | MessageResponse<T> | FormatMessageResponse<T>,
channel: Channel<T>
channel?: Channel<T>
) {
const isThreadMessage = !!message.parent_id;
if (
Expand Down Expand Up @@ -1555,7 +1572,11 @@ export class ChannelService<
if (this.isFormatMessageResponse(message)) {
return {
...message,
readBy: isThreadMessage ? [] : getReadBy(message, channel),
readBy: isThreadMessage
? []
: channel
? getReadBy(message, channel)
: [],
translation: getMessageTranslation(
message,
channel,
Expand All @@ -1566,7 +1587,11 @@ export class ChannelService<
const formatMessage = this.formatMessage(message);
return {
...formatMessage,
readBy: isThreadMessage ? [] : getReadBy(formatMessage, channel),
readBy: isThreadMessage
? []
: channel
? getReadBy(formatMessage, channel)
: [],
translation: getMessageTranslation(
message,
channel,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,12 @@ describe('MessageInputComponent', () => {
fixture.detectChanges();
const spy = jasmine.createSpy();
component.messageUpdate.subscribe(spy);
updateMessageSpy.and.resolveTo({ id: component.message.id });
await component.messageSent();

expect(spy).toHaveBeenCalledWith(undefined);
expect(spy).toHaveBeenCalledWith({
message: jasmine.objectContaining({ id: component.message.id }),
});
});

it('should send message if button is clicked', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ export class MessageInputComponent
/**
* Emits when a message was successfuly sent or updated
*/
@Output() readonly messageUpdate = new EventEmitter<void>();
@Output() readonly messageUpdate = new EventEmitter<{
message: StreamMessage;
}>();
@HostBinding() class = 'str-chat__message-input-angular-host';
isFileUploadAuthorized: boolean | undefined;
canSendLinks: boolean | undefined;
Expand Down Expand Up @@ -353,7 +355,7 @@ export class MessageInputComponent
this.textareaValue = '';
}
try {
await (this.isUpdate
const message = await (this.isUpdate
? this.channelService.updateMessage({
...this.message!,
text: text,
Expand All @@ -366,7 +368,7 @@ export class MessageInputComponent
this.parentMessageId,
this.quotedMessage?.id
));
this.messageUpdate.emit();
this.messageUpdate.emit({ message });
if (!this.isUpdate) {
this.attachmentService.resetAttachmentUploads();
}
Expand Down
44 changes: 28 additions & 16 deletions projects/stream-chat-angular/src/lib/mocks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ export const mockCurrentUser = () =>
image: 'link/to/photo',
} as UserResponse<DefaultStreamChatGenerics>);

export const mockMessage = () =>
export const mockMessage = (id?: number) =>
({
id: 'id',
id: id === undefined ? 'id' : `id${id}`,
text: 'Hello from Angular SDK',
user: mockCurrentUser(),
type: 'regular',
Expand Down Expand Up @@ -84,7 +84,10 @@ export const generateMockChannels = (length = 25) => {
},
watch: () => {},
stopWatching: () => {},
sendMessage: () => {},
sendMessage: (m: any) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
return Promise.resolve({ message: m });
},
sendImage: () => {},
sendFile: () => {},
sendAction: () => {},
Expand Down Expand Up @@ -113,22 +116,31 @@ export const generateMockChannels = (length = 25) => {
eddie: { user: { id: 'eddie' } },
},
addMessageSorted: function (response: MessageResponse) {
if (response.parent_id) {
if (
(this.threads as { [key: string]: StreamMessage[] })[
response.parent_id
]
) {
(this.threads as { [key: string]: StreamMessage[] })[
response.parent_id
].push(response as any as StreamMessage);
if (!response) {
return;
}
let array: StreamMessage[];
const message = response as any as StreamMessage;
const threads = this.threads as { [key: string]: StreamMessage[] };
if (message.parent_id) {
if (threads[message.parent_id]) {
array = threads[message.parent_id];
} else {
(this.threads as { [key: string]: StreamMessage[] })[
response.parent_id
] = [response as any as StreamMessage];
array = [];
threads[message.parent_id] = array;
}
} else {
this.messages.push(response as any as StreamMessage);
array = this.messages;
}
const existingMessageIndex = array.findIndex((m) =>
message.id
? m.id === message.id
: m.created_at === message.created_at
);
if (existingMessageIndex === -1) {
array.push(message);
} else {
array[existingMessageIndex] = message;
}
},
removeMessage: () => {},
Expand Down
Loading