Skip to content

Commit 079b654

Browse files
committed
feat(chat): add basic message reaction implementation
1 parent 005d57e commit 079b654

File tree

9 files changed

+264
-235
lines changed

9 files changed

+264
-235
lines changed

src/components/chat/chat-message-list.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,6 @@ export default class IgcChatMessageListComponent extends LitElement {
7676
}));
7777
}
7878

79-
private handleReaction(e: CustomEvent) {
80-
const { messageId, emoji } = e.detail;
81-
82-
this.dispatchEvent(
83-
new CustomEvent('add-reaction', {
84-
detail: { messageId, emoji },
85-
bubbles: true,
86-
composed: true,
87-
})
88-
);
89-
}
90-
9179
private scrollToBottom() {
9280
requestAnimationFrame(() => {
9381
const container = this.shadowRoot?.host as HTMLElement;
@@ -127,7 +115,6 @@ export default class IgcChatMessageListComponent extends LitElement {
127115
.message=${message}
128116
.user=${this.user}
129117
.enableReactions=${this.enableReactions}
130-
@add-reaction=${this.handleReaction}
131118
></igc-chat-message>
132119
`
133120
)}

src/components/chat/chat-message.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ export default class IgcChatMessageComponent extends LitElement {
5858
}
5959

6060
private handleAddReaction(e: CustomEvent) {
61-
const emoji = e.detail.emoji;
61+
const { emojiId, emoji } = e.detail;
6262

6363
this.dispatchEvent(
6464
new CustomEvent('add-reaction', {
65-
detail: { messageId: this.message?.id, emoji },
65+
detail: { messageId: this.message?.id, emojiId, emoji },
6666
bubbles: true,
6767
composed: true,
6868
})

src/components/chat/chat.ts

Lines changed: 45 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import IgcChatHeaderComponent from './chat-header.js';
77
import IgcChatInputComponent from './chat-input.js';
88
import IgcChatMessageListComponent from './chat-message-list.js';
99
import { styles } from './themes/chat.base.css.js';
10-
import type { IgcMessage, IgcUser } from './types.js';
10+
import type { IgcMessage, IgcMessageReaction, IgcUser } from './types.js';
1111

1212
export interface IgcChatComponentEventMap {
1313
igcMessageEntered: CustomEvent<IgcMessage>;
@@ -106,73 +106,61 @@ export default class IgcChatComponent extends EventEmitterMixin<
106106
}
107107

108108
private handleAddReaction(e: CustomEvent) {
109-
const { messageId, emoji } = e.detail;
109+
const { messageId, emojiId, emoji } = e.detail;
110110

111-
this.messages.map((message) => {
111+
if (!messageId) return;
112+
113+
this.messages = this.messages.map((message) => {
112114
if (message.id === messageId) {
113-
const existingReaction = message.reactions?.find(
114-
(r) => r.emoji === emoji
115+
const userReaction = message.reactions?.find(
116+
(r) => this.user && r.users.includes(this.user.id)
115117
);
116118

117-
if (existingReaction && this.user) {
118-
// Toggle reaction for current user
119-
const userId = this.user.id;
120-
const hasReacted = existingReaction.users.includes(userId);
121-
122-
if (hasReacted) {
123-
// Remove reaction
124-
const updatedReactions =
125-
message.reactions
126-
?.map((r) => {
127-
if (r.emoji === emoji) {
128-
return {
129-
...r,
130-
count: r.count - 1,
131-
users: r.users.filter((id) => id !== userId),
132-
};
133-
}
134-
return r;
135-
})
136-
.filter((r) => r.count > 0) || [];
137-
138-
return {
139-
...message,
140-
reactions: updatedReactions,
141-
};
142-
}
119+
if (userReaction) {
120+
// Remove reaction
121+
message.reactions?.forEach((r) => {
122+
if (r.id === userReaction.id) {
123+
r.count -= 1;
124+
r.users = (r.users ?? []).filter((id) => id !== this.user?.id);
125+
}
126+
});
127+
128+
message.reactions =
129+
message.reactions?.filter((r) => r.count > 0) || [];
130+
}
131+
132+
const existingReaction = message.reactions?.find(
133+
(r) => r.id === emojiId
134+
);
143135

136+
if (existingReaction) {
144137
// Add reaction
145-
const updatedReactions =
146-
message.reactions?.map((r) => {
147-
if (r.emoji === emoji) {
148-
return {
149-
...r,
150-
count: r.count + 1,
151-
users: [...r.users, userId],
152-
};
138+
message.reactions?.forEach((r) => {
139+
if (r.id === emojiId) {
140+
r.count += 1;
141+
if (this.user) {
142+
r.users.push(this.user.id);
153143
}
154-
return r;
155-
}) || [];
144+
}
145+
});
156146

157-
return {
158-
...message,
159-
reactions: updatedReactions,
160-
};
147+
message.reactions = message.reactions ?? [];
161148
}
162149

163-
// Create new reaction
164-
const newReaction = {
165-
emoji,
166-
count: 1,
167-
users: [this.user?.id],
168-
};
169-
170-
return {
171-
...message,
172-
reactions: [...(message.reactions || []), newReaction],
173-
};
150+
if (!existingReaction && userReaction?.id !== emojiId) {
151+
// Create new reaction
152+
const newReaction: IgcMessageReaction = {
153+
id: emojiId,
154+
emoji,
155+
count: 1,
156+
users: this.user ? [this.user.id] : [],
157+
};
158+
159+
message.reactions = [...(message.reactions || []), newReaction];
160+
}
174161
}
175-
return message;
162+
163+
return { ...message };
176164
});
177165
}
178166

0 commit comments

Comments
 (0)