Skip to content

Commit fcfe671

Browse files
authored
Refactor captions component, move the announcer to an internal component (#5901)
* Update * Change files
1 parent e67722d commit fcfe671

4 files changed

Lines changed: 108 additions & 49 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"type": "patch",
3+
"area": "improvement",
4+
"workstream": "RTTCaptions",
5+
"comment": "Refactor captions component, put the announcer to one single private component",
6+
"packageName": "@azure/communication-react",
7+
"email": "96077406+carocao-msft@users.noreply.github.com",
8+
"dependentChangeType": "patch"
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"type": "patch",
3+
"area": "improvement",
4+
"workstream": "RTTCaptions",
5+
"comment": "Refactor captions component, put the announcer to one single private component",
6+
"packageName": "@azure/communication-react",
7+
"email": "96077406+carocao-msft@users.noreply.github.com",
8+
"dependentChangeType": "patch"
9+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
import React, { useEffect, useState } from 'react';
4+
import { hiddenAnnouncementClassName } from './styles/Captions.style';
5+
import { CaptionsInformation, RealTimeTextInformation } from './CaptionsBanner';
6+
7+
/** @internal */
8+
export type _CaptionsAndRTTAnnouncerProps = {
9+
/**
10+
* Array of captions to be displayed
11+
*/
12+
captions: CaptionsInformation[];
13+
/**
14+
* Array of finalized and partial real time text messages
15+
*/
16+
realTimeTexts?: {
17+
completedMessages?: RealTimeTextInformation[];
18+
currentInProgress?: RealTimeTextInformation[];
19+
myInProgress?: RealTimeTextInformation;
20+
};
21+
/**
22+
* Title for the real time text messages
23+
*/
24+
realTimeTextTitle: string;
25+
/**
26+
* Title for the captions
27+
*/
28+
captionsTitle: string;
29+
};
30+
31+
/** @internal */
32+
export const _CaptionsAndRTTAnnouncer = (props: _CaptionsAndRTTAnnouncerProps): JSX.Element => {
33+
const { captions, realTimeTexts, realTimeTextTitle, captionsTitle } = props;
34+
const [announcedRTT, setAnnouncedRTT] = useState<number[]>([]);
35+
const [announcedCaption, setAnnouncedCaption] = useState<string[]>([]);
36+
const [captionAnnouncementText, setCaptionAnnouncementText] = useState<CaptionsInformation[]>([]);
37+
const [rttAnnouncementText, setRTTAnnouncementText] = useState<RealTimeTextInformation[]>([]);
38+
39+
useEffect(() => {
40+
if (realTimeTexts?.completedMessages) {
41+
//filter out the messages that have already been announced
42+
const rTTMessagesToAnnounce = realTimeTexts.completedMessages.filter(
43+
(message) => !announcedRTT.includes(message.id)
44+
);
45+
if (rTTMessagesToAnnounce.length > 0) {
46+
setRTTAnnouncementText(rTTMessagesToAnnounce);
47+
setAnnouncedRTT((prev) => [...prev, ...rTTMessagesToAnnounce.map((message) => message.id)]);
48+
}
49+
}
50+
if (captions.length > 0) {
51+
// filter out the captions that have already been announced
52+
const captionsToAnnounce = captions.filter(
53+
(caption) => !announcedCaption.includes(caption.id) && caption.isFinalized
54+
);
55+
if (captionsToAnnounce.length > 0) {
56+
setCaptionAnnouncementText(captionsToAnnounce);
57+
setAnnouncedCaption((prev) => [...prev, ...captionsToAnnounce.map((caption) => caption.id)]);
58+
}
59+
}
60+
}, [captions, realTimeTexts?.completedMessages, announcedRTT, announcedCaption]);
61+
return (
62+
<>
63+
{(rttAnnouncementText.length > 0 || captionAnnouncementText?.length > 0) && (
64+
<div aria-live="assertive" role="alert" aria-atomic="true" className={hiddenAnnouncementClassName}>
65+
<span>
66+
{rttAnnouncementText.map((text) => (
67+
<span>
68+
{realTimeTextTitle} {text.displayName}: {text.message}
69+
</span>
70+
))}
71+
</span>
72+
<span>
73+
{captionAnnouncementText.map((text) => (
74+
<span>
75+
{captionsTitle} {text.displayName}: {text.captionText}
76+
</span>
77+
))}
78+
</span>
79+
</div>
80+
)}
81+
</>
82+
);
83+
};

packages/react-components/src/components/CaptionsBanner.tsx

Lines changed: 7 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
captionsBannerClassName,
1111
captionsBannerFullHeightClassName,
1212
captionsContainerClassName,
13-
hiddenAnnouncementClassName,
1413
loadingBannerFullHeightStyles,
1514
loadingBannerStyles
1615
} from './styles/Captions.style';
@@ -27,7 +26,7 @@ import {
2726
} from './styles/Captions.style';
2827
import { titleClassName } from './styles/CaptionsSettingsModal.styles';
2928
import { Text, IconButton } from '@fluentui/react';
30-
29+
import { _CaptionsAndRTTAnnouncer } from './CaptionsAndRTTAnnouncer';
3130
/**
3231
* @public
3332
* information required for each line of caption
@@ -243,10 +242,6 @@ export const CaptionsBanner = (props: CaptionsBannerProps): JSX.Element => {
243242
const theme = useTheme();
244243

245244
const [expandBannerHeight, setExpandBannerHeight] = useState<boolean>(false);
246-
const [announcedRTT, setAnnouncedRTT] = useState<number[]>([]);
247-
const [announcedCaption, setAnnouncedCaption] = useState<string[]>([]);
248-
const [captionAnnouncementText, setCaptionAnnouncementText] = useState<CaptionsInformation[]>([]);
249-
const [rttAnnouncementText, setRTTAnnouncementText] = useState<RealTimeTextInformation[]>([]);
250245

251246
const getTitle = (): string => {
252247
if (isCaptionsOn && isRealTimeTextOn) {
@@ -314,29 +309,6 @@ export const CaptionsBanner = (props: CaptionsBannerProps): JSX.Element => {
314309
}
315310
}, [latestLocalRealTimeText]);
316311

317-
useEffect(() => {
318-
if (realTimeTexts?.completedMessages) {
319-
//filter out the messages that have already been announced
320-
const rTTMessagesToAnnounce = realTimeTexts.completedMessages.filter(
321-
(message) => !announcedRTT.includes(message.id)
322-
);
323-
if (rTTMessagesToAnnounce.length > 0) {
324-
setRTTAnnouncementText(rTTMessagesToAnnounce);
325-
setAnnouncedRTT((prev) => [...prev, ...rTTMessagesToAnnounce.map((message) => message.id)]);
326-
}
327-
}
328-
if (captions.length > 0) {
329-
// filter out the captions that have already been announced
330-
const captionsToAnnounce = captions.filter(
331-
(caption) => !announcedCaption.includes(caption.id) && caption.isFinalized
332-
);
333-
if (captionsToAnnounce.length > 0) {
334-
setCaptionAnnouncementText(captionsToAnnounce);
335-
setAnnouncedCaption((prev) => [...prev, ...captionsToAnnounce.map((caption) => caption.id)]);
336-
}
337-
}
338-
}, [captions, realTimeTexts?.completedMessages, announcedRTT, announcedCaption]);
339-
340312
const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>): void => {
341313
if (event.key === 'Enter') {
342314
event.preventDefault();
@@ -384,26 +356,12 @@ export const CaptionsBanner = (props: CaptionsBannerProps): JSX.Element => {
384356
<>
385357
{(startCaptionsInProgress || isCaptionsOn || isRealTimeTextOn) && (
386358
<FocusZone shouldFocusOnMount className={captionsContainerClassName} data-ui-id="captions-banner">
387-
{/* ARIA live region */}
388-
{(rttAnnouncementText.length > 0 || captionAnnouncementText?.length > 0) && (
389-
<div aria-live="assertive" role="alert" aria-atomic="true" className={hiddenAnnouncementClassName}>
390-
<span>
391-
{rttAnnouncementText.map((text) => (
392-
<span>
393-
{strings.realTimeTextBannerTitle} {text.displayName}: {text.message}
394-
</span>
395-
))}
396-
</span>
397-
<span>
398-
{captionAnnouncementText.map((text) => (
399-
<span>
400-
{strings.captionsOnlyContainerTitle} {text.displayName}: {text.captionText}
401-
</span>
402-
))}
403-
</span>
404-
</div>
405-
)}
406-
359+
<_CaptionsAndRTTAnnouncer
360+
captions={captions}
361+
realTimeTexts={realTimeTexts}
362+
realTimeTextTitle={strings.realTimeTextBannerTitle ?? ''}
363+
captionsTitle={strings.captionsOnlyContainerTitle ?? ''}
364+
/>
407365
{(isCaptionsOn || isRealTimeTextOn) && formFactor === 'compact' && (
408366
<Stack
409367
horizontal

0 commit comments

Comments
 (0)