Skip to content

Commit 7f00b79

Browse files
update UIKit version to v6.3.8
1 parent c2e493d commit 7f00b79

44 files changed

Lines changed: 827 additions & 149 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@cometchat/chat-uikit-react",
3-
"version": "6.3.7",
3+
"version": "6.3.8",
44
"description": "Ready-to-use Chat UI Components for React(Javascript/Web)",
55
"author": "CometChat",
66
"exports": {

sample-app/CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
## [6.2.5] - 19-01-2026
2+
## New
3+
- None
4+
5+
## Enhancements
6+
- Added a selected users preview in the `CometChatUsers` component, allowing users to review selected members before adding them to a group.
7+
8+
## Fixes
9+
- Fixed an issue where the unban success toast was not displayed when a member was unbanned from a group.
10+
- Fixed an issue where users were unblocked even when clicking outside the **Unblock User** confirmation button.
11+
112
## [6.2.4] - 15-10-2025
213

314
## New

sample-app/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
{
22
"name": "sample-app",
3-
"version": "6.2.4",
3+
"version": "6.2.5",
44
"description": "React App made using CometChat React v6 UI Kit.",
55
"author": "CometChat",
66
"private": true,
77
"dependencies": {
8-
"@cometchat/calls-sdk-javascript": "^4.1.0",
9-
"@cometchat/chat-sdk-javascript": "^4.1.3",
10-
"@cometchat/chat-uikit-react": "~6.3.3",
8+
"@cometchat/calls-sdk-javascript": "^4.2.2",
9+
"@cometchat/chat-sdk-javascript": "^4.1.6",
10+
"@cometchat/chat-uikit-react": "~6.3.8",
1111
"react": "18.2.0",
1212
"react-dom": "18.2.0",
1313
"react-router-dom": "6.14.2",

sample-app/src/components/CometChatAddMembers/CometChatAddMembers.tsx

Lines changed: 67 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -219,15 +219,17 @@ export function CometChatAddMembers(props: IAddMembersProps) {
219219
const membersToAddRef = useRef<CometChat.GroupMember[]>([]);
220220
const selectionModeRef = useRef(selectionMode);
221221
const loggedInUserRef = useRef<CometChat.User | null>(null);
222-
const onSelectPropRef = useRefSync(onSelect);
223222
const groupPropRef = useRefSync(group);
224223
const onBackPropRef = useRefSync(onBack);
225224
const onAddMembersButtonClickPropRef = useRefSync(onAddMembersButtonClick);
226225
const errorHandler = useCometChatErrorHandler(onError!);
227226
const [isLoading, setIsLoading] = useState(false);
228227
const [isDisabled, setIsDisabled] = useState(true);
229228
const [isError, setIsError] = useState(false);
230-
/**
229+
const [membersCount, setMembersCount] = useState(0);
230+
// Track selected users internally
231+
const selectedUsersMapRef = useRef<Map<string, CometChat.User>>(new Map());
232+
231233
/**
232234
* Creates a `CometChat.GroupMember` instance from the provided `user`
233235
*/
@@ -241,48 +243,28 @@ export function CometChatAddMembers(props: IAddMembersProps) {
241243
}, [groupPropRef]);
242244

243245
/**
244-
* Updates `membersToAddRef`
245-
*
246-
* @remarks
247-
* This function makes sure `membersToAddRef` is in sync with the UI
246+
* Handles individual user selection changes from CometChatUsers
247+
* Tracks selected users internally and updates state accordingly
248248
*/
249-
const onSelectWrapper = useCallback((user: CometChat.User, selected: boolean): void => {
250-
251-
if (onSelectPropRef.current) {
252-
return onSelectPropRef.current(user, selected);
253-
}
254-
if (selectionModeRef.current === SelectionMode.single) {
255-
membersToAddRef.current = [createGroupMemberFromUser(user)];
256-
}
257-
else if (selectionModeRef.current === SelectionMode.multiple) {
258-
updateAddMembersList(user);
259-
}
260-
if (membersToAddRef.current.length == 0) {
261-
setIsDisabled(true)
262-
}
263-
else {
264-
setIsDisabled(false);
249+
const handleSelect = useCallback((user: CometChat.User, selected: boolean): void => {
250+
if (selected) {
251+
selectedUsersMapRef.current.set(user.getUid(), user);
252+
} else {
253+
selectedUsersMapRef.current.delete(user.getUid());
265254
}
266-
}, [createGroupMemberFromUser, onSelectPropRef]);
267-
268-
const updateAddMembersList = (user: CometChat.User) => {
269-
const targetUid = user.getUid();
270-
const tmpMembersToAddList: CometChat.GroupMember[] = [];
271-
let updated = false;
272-
for (let i = 0; i < membersToAddRef.current.length; i++) {
273-
const curMember = membersToAddRef.current[i];
274-
if (targetUid === curMember.getUid()) {
275-
updated = true;
276-
}
277-
else {
278-
tmpMembersToAddList.push(curMember);
279-
}
280-
}
281-
if (!updated) {
282-
tmpMembersToAddList.push(createGroupMemberFromUser(user));
283-
}
284-
membersToAddRef.current = tmpMembersToAddList;
285-
}
255+
256+
// Convert selected users to group members
257+
const selectedUsersList = Array.from(selectedUsersMapRef.current.values());
258+
membersToAddRef.current = selectedUsersList.map(u => createGroupMemberFromUser(u));
259+
260+
// Update button disabled state and count based on selection
261+
const count = selectedUsersList.length;
262+
setMembersCount(count);
263+
setIsDisabled(count === 0);
264+
265+
// Call the original onSelect prop if provided
266+
onSelect?.(user, selected);
267+
}, [createGroupMemberFromUser, onSelect]);
286268

287269
/**
288270
* Creates a `CometChat.Action` instance
@@ -322,6 +304,7 @@ export function CometChatAddMembers(props: IAddMembersProps) {
322304
if (onAddBtnClick) {
323305
onAddBtnClick(group.getGuid(), membersToAddRef.current);
324306
membersToAddRef.current = [];
307+
setMembersCount(0);
325308
return;
326309
}
327310
const UIDsToRemove: Set<string> = new Set();
@@ -353,6 +336,7 @@ export function CometChatAddMembers(props: IAddMembersProps) {
353336
});
354337
}
355338
membersToAddRef.current = [];
339+
setMembersCount(0);
356340
onBackPropRef.current?.();
357341
}
358342
catch (error) {
@@ -379,31 +363,59 @@ export function CometChatAddMembers(props: IAddMembersProps) {
379363
);
380364
}
381365

366+
/**
367+
* Gets the localized button text based on member count
368+
*/
369+
function getButtonText(): string {
370+
if (buttonText && buttonText !== getLocalizedString("add_members")) {
371+
return buttonText;
372+
}
373+
if (membersCount === 0) {
374+
return getLocalizedString("add_members");
375+
}
376+
if (membersCount === 1) {
377+
// Prefer dedicated singular key for better localization
378+
const singular = getLocalizedString("add_member");
379+
if (singular && singular !== "") {
380+
return singular;
381+
}
382+
// Fallback to plural template with n = 1, if available
383+
const nSingular = getLocalizedString("add_n_members");
384+
if (nSingular && nSingular !== "") {
385+
return nSingular.replace("{n}", "1");
386+
}
387+
// Final English fallback
388+
const generic = getLocalizedString("add_members");
389+
return generic && generic !== "" ? generic : "";
390+
}
391+
const n = getLocalizedString("add_n_members");
392+
// Fallback if localization key is missing
393+
if (!n || n === "") {
394+
// Use localized fallback instead of hardcoded English string
395+
const generic = getLocalizedString("add_members");
396+
return generic && generic !== "" ? generic : "";
397+
}
398+
const text = n.replace("{n}", membersCount.toString());
399+
return text;
400+
}
401+
382402
/**
383403
* Creates add members button view
384404
*/
385405
function getAddMembersBtnView() {
406+
const buttonTextValue = getButtonText();
386407
return (
387408
<div className={`cometchat-add-members__add-btn-wrapper ${isDisabled ? "cometchat-add-members__add-btn-wrapper-disabled" : ""}`}>
388409
<CometChatButton
410+
key={`add-btn-${membersCount}`}
389411
isLoading={isLoading}
390-
text={buttonText}
412+
text={buttonTextValue}
391413
onClick={onAddBtnClickWrapper}
392414
/>
393415
</div>
394416
);
395417
}
396418

397-
const onUsersSelected = (user: CometChat.User) => {
398-
updateAddMembersList(user);
399-
if (membersToAddRef.current.length == 0) {
400-
setIsDisabled(true)
401-
}
402-
else {
403-
setIsDisabled(false);
404-
}
405-
}
406-
407419
useCometChatAddMembers({
408420
loggedInUserRef,
409421
errorHandler,
@@ -427,14 +439,13 @@ export function CometChatAddMembers(props: IAddMembersProps) {
427439
onError={onError}
428440
options={options}
429441
selectionMode={selectionMode}
430-
onSelect={onSelectWrapper}
442+
onSelect={handleSelect}
431443
usersRequestBuilder={usersRequestBuilder}
432444
searchRequestBuilder={searchRequestBuilder}
433445
itemView={listItemView}
434446
subtitleView={subtitleView}
435-
onItemClick={onUsersSelected}
436447
activeUser={undefined}
437-
448+
showSelectedUsersPreview={true}
438449
/>
439450
{isError ? <div className="cometchat-add-members_error-view">
440451
{getLocalizedString("member_error_subtitle")}

sample-app/src/components/CometChatDetails/CometChatThreadedMessages.tsx

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -56,29 +56,42 @@ export const CometChatThreadedMessages = (props: ThreadProps) => {
5656
user={(selectedItem as CometChat.Conversation)?.getConversationType?.() === "user" ? (selectedItem as CometChat.Conversation)?.getConversationWith() as CometChat.User : (selectedItem as CometChat.User).getUid?.() ? selectedItem as CometChat.User : undefined}
5757
group={(selectedItem as CometChat.Conversation)?.getConversationType?.() === "group" ? (selectedItem as CometChat.Conversation)?.getConversationWith() as CometChat.Group : (selectedItem as CometChat.Group).getGuid?.() ? selectedItem as CometChat.Group : undefined}
5858
/>
59-
</div> : <div className="message-composer-blocked" onClick={()=>{
60-
let user: CometChat.User | null = null;
59+
</div> :
60+
(
61+
<div className="message-composer-blocked">
62+
<div className="message-composer-blocked__text">
63+
{getLocalizedString("cannot_send_to_blocked_user")}{" "}
64+
<a
65+
onClick={() => {
66+
let user: CometChat.User | null = null;
6167

62-
if (selectedItem instanceof CometChat.User) {
63-
user = selectedItem;
64-
} else if (
65-
selectedItem instanceof CometChat.Conversation &&
66-
selectedItem.getConversationType() === CometChat.RECEIVER_TYPE.USER &&
67-
selectedItem.getConversationWith() instanceof CometChat.User
68-
) {
69-
user = selectedItem.getConversationWith() as CometChat.User;
70-
}
71-
if (user) {
72-
CometChat.unblockUsers([user.getUid()]).then(() => {
73-
user?.setBlockedByMe(false);
74-
CometChatUserEvents.ccUserUnblocked.next(user as CometChat.User);
75-
});
76-
}
77-
}}>
78-
<div className="message-composer-blocked__text">
79-
{getLocalizedString("cannot_send_to_blocked_user")} <a> {getLocalizedString("click_to_unblock")}</a>
80-
</div>
81-
</div>}
68+
if (selectedItem instanceof CometChat.User) {
69+
user = selectedItem;
70+
} else if (
71+
selectedItem instanceof CometChat.Conversation &&
72+
selectedItem.getConversationType() ===
73+
CometChat.RECEIVER_TYPE.USER &&
74+
selectedItem.getConversationWith() instanceof
75+
CometChat.User
76+
) {
77+
user =
78+
selectedItem.getConversationWith() as CometChat.User;
79+
}
80+
if (user) {
81+
CometChat.unblockUsers([user.getUid()]).then(() => {
82+
user?.setBlockedByMe(false);
83+
CometChatUserEvents.ccUserUnblocked.next(
84+
user as CometChat.User
85+
);
86+
});
87+
}
88+
}}
89+
>
90+
{getLocalizedString("click_to_unblock")}
91+
</a>
92+
</div>
93+
</div>
94+
)}
8295
</>}
8396
</div>
8497
);

sample-app/src/components/CometChatHome/CometChatHome.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ function CometChatHome(props: { theme?: string }) {
127127
toastTextRef.current = getLocalizedString("member_banned");
128128
setShowToast(true)
129129
})
130+
let ccGroupMemberUnbanned = CometChatGroupEvents.ccGroupMemberUnbanned.subscribe(() => {
131+
toastTextRef.current = getLocalizedString("member_unbanned");
132+
setShowToast(true)
133+
})
130134
let ccGroupMemberKicked = CometChatGroupEvents.ccGroupMemberKicked.subscribe(() => {
131135
toastTextRef.current = getLocalizedString("member_removed");
132136
setShowToast(true)
@@ -136,6 +140,7 @@ function CometChatHome(props: { theme?: string }) {
136140
ccGroupMemberScopeChanged?.unsubscribe();
137141
ccGroupMemberAdded?.unsubscribe();
138142
ccGroupMemberBanned?.unsubscribe();
143+
ccGroupMemberUnbanned?.unsubscribe();
139144
ccGroupMemberKicked?.unsubscribe();
140145
}
141146

sample-app/src/components/CometChatMessages/CometChatMessages.tsx

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -80,23 +80,28 @@ export const CometChatMessages = (props: MessagesViewProps) => {
8080
onThreadRepliesClick={(message: CometChat.BaseMessage) => onThreadRepliesClick(message)}
8181
goToMessageId={goToMessageId}
8282
textFormatters={searchKeyword && searchKeyword.trim() !== "" ? getFormatters() : undefined}
83+
startFromUnreadMessages={true}
84+
showMarkAsUnreadOption={true}
8385
/>
8486
</div>
8587
{showComposerState ? <div className="cometchat-composer-wrapper">
8688
<CometChatMessageComposer
8789
user={user}
8890
group={group}
8991
/>
90-
</div> : <div className="message-composer-blocked" onClick={() => {
91-
if (user) {
92-
CometChat.unblockUsers([user?.getUid()]).then(() => {
93-
user.setBlockedByMe(false);
94-
CometChatUserEvents.ccUserUnblocked.next(user);
95-
})
96-
}
97-
}}>
92+
</div> : <div className="message-composer-blocked">
9893
<div className="message-composer-blocked__text">
99-
{getLocalizedString("cannot_send_to_blocked_user")} <a> {getLocalizedString("click_to_unblock")}</a>
94+
{getLocalizedString("cannot_send_to_blocked_user")}
95+
<a onClick={() => {
96+
if (user) {
97+
CometChat.unblockUsers([user?.getUid()]).then(() => {
98+
user.setBlockedByMe(false);
99+
CometChatUserEvents.ccUserUnblocked.next(user);
100+
})
101+
}
102+
}}>
103+
{getLocalizedString("click_to_unblock")}
104+
</a>
100105
</div>
101106
</div>}
102107
</div>

sample-app/src/locales/de/de.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,12 @@
2626
"ownership_transferred_successfully": "Gruppenbesitz erfolgreich übertragen.",
2727
"permissions_updated_successfully": "Berechtigungen erfolgreich aktualisiert.",
2828
"member_added": "Mitglied zur Gruppe hinzugefügt.",
29+
"member_unbanned": "Das Mitglied wurde in der Gruppe wieder entsperrt.",
2930
"member_banned": "Mitglied wurde aus der Gruppe verbannt.",
3031
"member_removed": "Mitglied wurde aus der Gruppe entfernt.",
3132
"add_members": "Mitglieder hinzufügen",
33+
"add_member": "Mitglied hinzufügen",
34+
"add_n_members": "{n} Mitglieder hinzufügen",
3235
"leave": "Verlassen",
3336
"delete_and_exit": "Löschen und verlassen",
3437
"ownership_transfer": "Besitzübertragung",

sample-app/src/locales/en-GB/en-GB.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@
2727
"permissions_updated_successfully": "Permissions updated successfully.",
2828
"member_added": "Member added to the group.",
2929
"member_banned": "Member has been banned from the group.",
30+
"member_unbanned": "Member has been unbanned from the group.",
3031
"member_removed": "Member has been removed from the group.",
3132
"add_members": "Add Members",
33+
"add_member": "Add Member",
34+
"add_n_members": "Add {n} Members",
3235
"leave": "Leave",
3336
"delete_and_exit": "Delete and Exit",
3437
"ownership_transfer": "Ownership Transfer",

sample-app/src/locales/en-US/en-US.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@
2727
"permissions_updated_successfully": "Permissions updated successfully.",
2828
"member_added": "Member added to the group.",
2929
"member_banned": "Member has been banned from the group.",
30+
"member_unbanned": "Member has been unbanned from the group.",
3031
"member_removed": "Member has been removed from the group.",
3132
"add_members": "Add Members",
33+
"add_member": "Add Member",
34+
"add_n_members": "Add {n} Members",
3235
"leave": "Leave",
3336
"delete_and_exit": "Delete and Exit",
3437
"ownership_transfer": "Ownership Transfer",

0 commit comments

Comments
 (0)