forked from microsoft/BotFramework-WebChat
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathTranscriptActivity.tsx
More file actions
116 lines (103 loc) · 4.86 KB
/
TranscriptActivity.tsx
File metadata and controls
116 lines (103 loc) · 4.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import { hooks } from 'botframework-webchat-api';
import { type WebChatActivity } from 'botframework-webchat-core';
import { validateProps } from 'botframework-webchat-react-valibot';
import React, { memo, useCallback, useMemo } from 'react';
import { custom, object, pipe, readonly, safeParse, type InferInput } from 'valibot';
import useFirstActivityInSenderGroup from '../Middleware/ActivityGrouping/ui/SenderGrouping/useFirstActivity';
import useLastActivityInSenderGroup from '../Middleware/ActivityGrouping/ui/SenderGrouping/useLastActivity';
import useFirstActivityInStatusGroup from '../Middleware/ActivityGrouping/ui/StatusGrouping/useFirstActivity';
import useLastActivityInStatusGroup from '../Middleware/ActivityGrouping/ui/StatusGrouping/useLastActivity';
import useActivityElementMapRef from '../providers/ChatHistoryDOM/useActivityElementRef';
import useGetRenderActivityCallback from '../providers/RenderingActivities/useGetRenderActivityCallback';
import isZeroOrPositive from '../Utils/isZeroOrPositive';
import ActivityRow from './ActivityRow';
const { useCreateActivityStatusRenderer, useCreateAvatarRenderer, useGetKeyByActivity, useStyleOptions } = hooks;
const transcriptActivityPropsSchema = pipe(
object({
activity: custom<WebChatActivity>(value => safeParse(object({}), value).success)
}),
readonly()
);
type TranscriptActivityProps = InferInput<typeof transcriptActivityPropsSchema>;
const TranscriptActivity = (props: TranscriptActivityProps) => {
const { activity } = validateProps(transcriptActivityPropsSchema, props);
const [{ bubbleFromUserNubOffset, bubbleNubOffset, groupTimestamp, showAvatarInGroup }] = useStyleOptions();
const [firstActivityInSenderGroup] = useFirstActivityInSenderGroup();
const [firstActivityInStatusGroup] = useFirstActivityInStatusGroup();
const [lastActivityInSenderGroup] = useLastActivityInSenderGroup();
const [lastActivityInStatusGroup] = useLastActivityInStatusGroup();
const activityElementMapRef = useActivityElementMapRef();
const createActivityStatusRenderer = useCreateActivityStatusRenderer();
const getKeyByActivity = useGetKeyByActivity();
const getRenderActivityCallback = useGetRenderActivityCallback();
const renderAvatar = useCreateAvatarRenderer();
const activityKey: string = useMemo(() => getKeyByActivity(activity), [activity, getKeyByActivity]);
const hideAllTimestamps = groupTimestamp === false;
const isFirstInSenderGroup =
firstActivityInSenderGroup === activity || typeof firstActivityInSenderGroup === 'undefined';
const isFirstInStatusGroup =
firstActivityInStatusGroup === activity || typeof firstActivityInStatusGroup === 'undefined';
const isLastInSenderGroup =
lastActivityInSenderGroup === activity || typeof lastActivityInSenderGroup === 'undefined';
const isLastInStatusGroup =
lastActivityInStatusGroup === activity || typeof lastActivityInStatusGroup === 'undefined';
const renderAvatarForSenderGroup = useMemo(
() => !!renderAvatar && renderAvatar({ activity }),
[activity, renderAvatar]
);
const isTopSideBotNub = isZeroOrPositive(bubbleNubOffset);
const isTopSideUserNub = isZeroOrPositive(bubbleFromUserNubOffset);
const renderActivityStatus = useMemo(
() =>
createActivityStatusRenderer({
activity,
nextVisibleActivity: undefined
}),
[activity, createActivityStatusRenderer]
);
const activityCallbackRef = useCallback(
(activityElement: HTMLElement) => {
activityElement
? activityElementMapRef.current.set(activityKey, activityElement)
: activityElementMapRef.current.delete(activityKey);
},
[activityElementMapRef, activityKey]
);
const hideTimestamp = hideAllTimestamps || !isLastInStatusGroup;
const isTopSideNub = activity.from?.role === 'user' ? isTopSideUserNub : isTopSideBotNub;
let showCallout: boolean;
// Depending on the "showAvatarInGroup" setting, the avatar will render in different positions.
if (showAvatarInGroup === 'sender') {
if (isTopSideNub) {
showCallout = isFirstInSenderGroup && isFirstInStatusGroup;
} else {
showCallout = isLastInSenderGroup && isLastInStatusGroup;
}
} else if (showAvatarInGroup === 'status') {
if (isTopSideNub) {
showCallout = isFirstInStatusGroup;
} else {
showCallout = isLastInStatusGroup;
}
} else {
showCallout = true;
}
const renderActivity = getRenderActivityCallback(activity);
const children = useMemo(
() =>
renderActivity({
hideTimestamp,
renderActivityStatus,
renderAvatar: renderAvatarForSenderGroup,
showCallout
}),
[hideTimestamp, renderActivity, renderActivityStatus, renderAvatarForSenderGroup, showCallout]
);
return (
<ActivityRow activity={activity} ref={activityCallbackRef}>
{children}
</ActivityRow>
);
};
export default memo(TranscriptActivity);
export { type TranscriptActivityProps };