Skip to content

Commit 26e9a2d

Browse files
committed
refactor: extract useActivityKeysOfSendStatus hook to eliminate duplication
Both SendFailed and LongSend shared the same useMemo pattern for filtering activities by send status and isPresentational. Extracted into a shared hook useActivityKeysOfSendStatus(status).
1 parent 5fc301c commit 26e9a2d

3 files changed

Lines changed: 37 additions & 35 deletions

File tree

packages/component/src/Transcript/LiveRegion/LongSend.tsx

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { hooks } from 'botframework-webchat-api';
2-
import { memo, useEffect, useMemo, useRef, useState } from 'react';
2+
import { memo, useEffect, useRef, useState } from 'react';
33

44
import { useLiveRegion } from '../../providers/LiveRegionTwin';
55
import { SENDING } from '../../types/internal/SendStatus';
6-
import isPresentational from './isPresentational';
6+
import useActivityKeysOfSendStatus from './useActivityKeysOfSendStatus';
77

8-
const { useGetActivityByKey, useLocalizer, usePonyfill, useSendStatusByActivityKey } = hooks;
8+
const { useLocalizer, usePonyfill } = hooks;
99

1010
const SENDING_ANNOUNCEMENT_DELAY = 3000;
1111

@@ -19,8 +19,6 @@ const SENDING_ANNOUNCEMENT_DELAY = 3000;
1919
* Presentational activities (e.g. `event` or `typing`) are excluded to reduce noise.
2020
*/
2121
const LiveRegionLongSend = () => {
22-
const [sendStatusByActivityKey] = useSendStatusByActivityKey();
23-
const getActivityByKey = useGetActivityByKey();
2422
const localize = useLocalizer();
2523
const [{ clearTimeout, setTimeout }] = usePonyfill();
2624

@@ -33,21 +31,7 @@ const LiveRegionLongSend = () => {
3331
const [tick, setTick] = useState(0);
3432

3533
/** Keys of outgoing non-presentational activities that are currently in the sending state. */
36-
const sendingKeys = useMemo<Set<string>>(() => {
37-
const keys = new Set<string>();
38-
39-
for (const [key, sendStatus] of sendStatusByActivityKey) {
40-
if (sendStatus !== SENDING) {
41-
continue;
42-
}
43-
44-
if (!isPresentational(getActivityByKey(key))) {
45-
keys.add(key);
46-
}
47-
}
48-
49-
return keys;
50-
}, [getActivityByKey, sendStatusByActivityKey]);
34+
const sendingKeys = useActivityKeysOfSendStatus(SENDING);
5135

5236
/**
5337
* Arm a per-key timer when a key newly enters `sendingKeys`.

packages/component/src/Transcript/LiveRegion/SendFailed.tsx

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import { memo, useMemo } from 'react';
44
import usePrevious from '../../hooks/internal/usePrevious';
55
import { useLiveRegion } from '../../providers/LiveRegionTwin';
66
import { SEND_FAILED } from '../../types/internal/SendStatus';
7-
import isPresentational from './isPresentational';
7+
import useActivityKeysOfSendStatus from './useActivityKeysOfSendStatus';
88

9-
const { useGetActivityByKey, useLocalizer, useSendStatusByActivityKey } = hooks;
9+
const { useLocalizer } = hooks;
1010

1111
/**
1212
* React component to on-demand narrate "Failed to send message" at the end of the live region.
@@ -19,8 +19,6 @@ const { useGetActivityByKey, useLocalizer, useSendStatusByActivityKey } = hooks;
1919
* Thus, we need to use a live region "footnote" to indicate the message was failed to send.
2020
*/
2121
const LiveRegionSendFailed = () => {
22-
const [sendStatusByActivityKey] = useSendStatusByActivityKey();
23-
const getActivityByKey = useGetActivityByKey();
2422
const localize = useLocalizer();
2523

2624
/**
@@ -29,17 +27,7 @@ const LiveRegionSendFailed = () => {
2927
* Activities which are presentational, such as `event` or `typing`, are ignored to reduce confusions.
3028
* "Failed to send message" should not be narrated for presentational activities.
3129
*/
32-
const activityKeysOfSendFailed = useMemo<Set<string>>(
33-
() =>
34-
Array.from(sendStatusByActivityKey).reduce(
35-
(activityKeysOfSendFailed, [key, sendStatus]) =>
36-
sendStatus === SEND_FAILED && !isPresentational(getActivityByKey(key))
37-
? activityKeysOfSendFailed.add(key)
38-
: activityKeysOfSendFailed,
39-
new Set<string>()
40-
),
41-
[getActivityByKey, sendStatusByActivityKey]
42-
);
30+
const activityKeysOfSendFailed = useActivityKeysOfSendStatus(SEND_FAILED);
4331

4432
/** Returns localized "Failed to send message." */
4533
const liveRegionSendFailedAlt = localize('TRANSCRIPT_LIVE_REGION_SEND_FAILED_ALT');
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { hooks } from 'botframework-webchat-api';
2+
import { useMemo } from 'react';
3+
4+
import type { SendStatus } from '../../types/internal/SendStatus';
5+
import isPresentational from './isPresentational';
6+
7+
const { useGetActivityByKey, useSendStatusByActivityKey } = hooks;
8+
9+
/**
10+
* Returns the set of keys of outgoing non-presentational activities that currently
11+
* have the given send status.
12+
*
13+
* Presentational activities (e.g. `event` or `typing`) are excluded to reduce noise.
14+
*/
15+
export default function useActivityKeysOfSendStatus(status: SendStatus): Set<string> {
16+
const [sendStatusByActivityKey] = useSendStatusByActivityKey();
17+
const getActivityByKey = useGetActivityByKey();
18+
19+
return useMemo<Set<string>>(() => {
20+
const keys = new Set<string>();
21+
22+
for (const [key, sendStatus] of sendStatusByActivityKey) {
23+
if (sendStatus === status && !isPresentational(getActivityByKey(key))) {
24+
keys.add(key);
25+
}
26+
}
27+
28+
return keys;
29+
}, [getActivityByKey, sendStatusByActivityKey, status]);
30+
}

0 commit comments

Comments
 (0)