Skip to content

Commit 7c0e616

Browse files
JamesBurnsidecarocao-msft
authored andcommitted
Fix unread chat messages badge on the CallWithChatComposite being cleared when the call goes on hold (#3332)
1 parent 1dc3fd9 commit 7c0e616

5 files changed

Lines changed: 70 additions & 39 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "Fix unread chat messages badge on the CallWithChatComposite being cleared when the call goes on hold",
4+
"packageName": "@azure/communication-react",
5+
"email": "2684369+JamesBurnside@users.noreply.github.com",
6+
"dependentChangeType": "patch"
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "Fix unread chat messages badge on the CallWithChatComposite being cleared when the call goes on hold",
4+
"packageName": "@azure/communication-react",
5+
"email": "2684369+JamesBurnside@users.noreply.github.com",
6+
"dependentChangeType": "patch"
7+
}

packages/react-composites/src/composites/CallWithChatComposite/CallWithChatComposite.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import { isDisabled } from '../CallComposite/utils';
4141
import { CustomCallControlButtonCallback } from '../common/ControlBar/CustomButton';
4242
import { SidePaneHeader } from '../common/SidePaneHeader';
4343
import { _CallControlOptions } from '../CallComposite/types/CallControlOptions';
44+
import { useUnreadMessagesTracker } from './ChatButton/useUnreadMessagesTracker';
4445

4546
/**
4647
* Props required for the {@link CallWithChatComposite}
@@ -283,32 +284,36 @@ const CallWithChatScreen = (props: CallWithChatScreenProps): JSX.Element => {
283284
[chatButtonDisabled, mobileView, toggleChat, showChatButton]
284285
);
285286

287+
const unreadChatMessagesCount = useUnreadMessagesTracker(chatProps.adapter, isChatOpen);
288+
286289
const customChatButton: CustomCallControlButtonCallback = useCallback(
287290
(args: CustomCallControlButtonCallbackArgs) => ({
288291
placement: mobileView ? 'primary' : 'secondary',
289292
onRenderButton: () => (
290293
<ChatButtonWithUnreadMessagesBadge
291-
chatAdapter={chatProps.adapter}
292-
isChatPaneVisible={isChatOpen}
293294
checked={isChatOpen}
294295
showLabel={args.displayType !== 'compact'}
295296
onClick={toggleChat}
296297
disabled={chatButtonDisabled}
297298
strings={chatButtonStrings}
298299
styles={commonButtonStyles}
299300
newMessageLabel={callWithChatStrings.chatButtonNewMessageNotificationLabel}
301+
unreadChatMessagesCount={unreadChatMessagesCount}
302+
// As chat is disabled when on hold, we don't want to show the unread badge when on hold
303+
hideUnreadChatMessagesBadge={isOnHold}
300304
/>
301305
)
302306
}),
303307
[
304308
callWithChatStrings.chatButtonNewMessageNotificationLabel,
305309
chatButtonStrings,
306-
chatProps.adapter,
307310
commonButtonStyles,
308311
isChatOpen,
309312
chatButtonDisabled,
310313
mobileView,
311-
toggleChat
314+
toggleChat,
315+
unreadChatMessagesCount,
316+
isOnHold
312317
]
313318
);
314319

packages/react-composites/src/composites/CallWithChatComposite/ChatButton/ChatButtonWithUnreadMessagesBadge.tsx

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT license.
33

4-
import { ChatMessage } from '@azure/communication-chat';
54
import { IStackStyles, Stack } from '@fluentui/react';
65
import { _formatString } from '@internal/acs-ui-common';
76
import { ControlBarButtonProps } from '@internal/react-components';
8-
import React, { useCallback, useMemo, useState } from 'react';
9-
import { useEffect } from 'react';
10-
import { ChatAdapter } from '../../ChatComposite';
7+
import React, { useCallback, useMemo } from 'react';
118
import { CallWithChatCompositeIcon } from '../../common/icons';
129
import { ChatButton } from './ChatButton';
1310
import { useCallWithChatCompositeStrings } from '../hooks/useCallWithChatCompositeStrings';
@@ -17,27 +14,19 @@ import { NotificationIcon } from './NotificationIcon';
1714
* @private
1815
*/
1916
export interface ChatButtonWithUnreadMessagesBadgeProps extends ControlBarButtonProps {
20-
chatAdapter: ChatAdapter;
21-
isChatPaneVisible: boolean;
22-
newMessageLabel?: string;
17+
unreadChatMessagesCount: number;
18+
hideUnreadChatMessagesBadge?: boolean;
19+
newMessageLabel: string;
2320
}
2421

25-
/**
26-
* Helper function to determine if the message in the event is a valid one from a user.
27-
* Display name is used since system messages will not have one.
28-
*/
29-
const validNewChatMessage = (message): boolean =>
30-
!!message.senderDisplayName && (message.type === 'text' || message.type === 'html');
31-
3222
const filledIcon = <CallWithChatCompositeIcon iconName={'ControlBarChatButtonActive'} />;
3323
const regularIcon = <CallWithChatCompositeIcon iconName={'ControlBarChatButtonInactive'} />;
3424

3525
/**
3626
* @private
3727
*/
3828
export const ChatButtonWithUnreadMessagesBadge = (props: ChatButtonWithUnreadMessagesBadgeProps): JSX.Element => {
39-
const { chatAdapter, isChatPaneVisible, newMessageLabel } = props;
40-
const [unreadChatMessagesCount, setUnreadChatMessagesCount] = useState<number>(0);
29+
const { newMessageLabel, unreadChatMessagesCount, hideUnreadChatMessagesBadge } = props;
4130

4231
const baseIcon = props.showLabel ? regularIcon : filledIcon;
4332
const callWithChatStrings = useCallWithChatCompositeStrings();
@@ -61,30 +50,13 @@ export const ChatButtonWithUnreadMessagesBadge = (props: ChatButtonWithUnreadMes
6150
const notificationOnIcon = useCallback((): JSX.Element => {
6251
return (
6352
<Stack styles={chatNotificationContainerStyles}>
64-
{unreadChatMessagesCount > 0 && (
53+
{unreadChatMessagesCount > 0 && !hideUnreadChatMessagesBadge && (
6554
<NotificationIcon chatMessagesCount={unreadChatMessagesCount} label={newMessageLabel} />
6655
)}
6756
{baseIcon}
6857
</Stack>
6958
);
70-
}, [unreadChatMessagesCount, newMessageLabel, baseIcon]);
71-
72-
useEffect(() => {
73-
if (isChatPaneVisible) {
74-
setUnreadChatMessagesCount(0);
75-
return;
76-
}
77-
const incrementUnreadChatMessagesCount = (event: { message: ChatMessage }): void => {
78-
if (!isChatPaneVisible && validNewChatMessage(event.message)) {
79-
setUnreadChatMessagesCount(unreadChatMessagesCount + 1);
80-
}
81-
};
82-
chatAdapter.on('messageReceived', incrementUnreadChatMessagesCount);
83-
84-
return () => {
85-
chatAdapter.off('messageReceived', incrementUnreadChatMessagesCount);
86-
};
87-
}, [chatAdapter, setUnreadChatMessagesCount, isChatPaneVisible, unreadChatMessagesCount]);
59+
}, [unreadChatMessagesCount, newMessageLabel, baseIcon, hideUnreadChatMessagesBadge]);
8860

8961
return (
9062
<ChatButton
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
4+
import { useEffect, useState } from 'react';
5+
import { ChatAdapter } from '../../ChatComposite/adapter/ChatAdapter';
6+
import { ChatMessage } from '@azure/communication-chat';
7+
8+
/**
9+
* Used by the CallWithChatComposite to track unread messages for showing as a badge on the Chat Button.
10+
* @private
11+
*/
12+
export const useUnreadMessagesTracker = (chatAdapter: ChatAdapter, isChatPaneVisible: boolean): number => {
13+
const [unreadChatMessagesCount, setUnreadChatMessagesCount] = useState<number>(0);
14+
15+
useEffect(() => {
16+
if (isChatPaneVisible) {
17+
setUnreadChatMessagesCount(0);
18+
return;
19+
}
20+
const incrementUnreadChatMessagesCount = (event: { message: ChatMessage }): void => {
21+
if (!isChatPaneVisible && validNewChatMessage(event.message)) {
22+
setUnreadChatMessagesCount(unreadChatMessagesCount + 1);
23+
}
24+
};
25+
chatAdapter.on('messageReceived', incrementUnreadChatMessagesCount);
26+
27+
return () => {
28+
chatAdapter.off('messageReceived', incrementUnreadChatMessagesCount);
29+
};
30+
}, [chatAdapter, setUnreadChatMessagesCount, isChatPaneVisible, unreadChatMessagesCount]);
31+
32+
return unreadChatMessagesCount;
33+
};
34+
35+
/**
36+
* Helper function to determine if the message in the event is a valid one from a user.
37+
* Display name is used since system messages will not have one.
38+
*/
39+
const validNewChatMessage = (message): boolean =>
40+
!!message.senderDisplayName && (message.type === 'text' || message.type === 'html');

0 commit comments

Comments
 (0)