Skip to content

Commit 2424b98

Browse files
refactor ChatEntry
1 parent f1f684a commit 2424b98

File tree

2 files changed

+51
-49
lines changed

2 files changed

+51
-49
lines changed

components/app/chat-transcript.tsx

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,25 +56,31 @@ interface ChatTranscriptProps extends Omit<ChatEntryProps, 'entry'> {
5656
export function ChatTranscript({
5757
hidden = false,
5858
messages = [],
59-
hideName,
60-
hideTimestamp,
61-
messageFormatter,
6259
...props
6360
}: ChatTranscriptProps & Omit<HTMLMotionProps<'div'>, 'ref'>) {
6461
return (
6562
<AnimatePresence>
6663
{!hidden && (
6764
<MotionContainer {...CONTAINER_MOTION_PROPS} {...props}>
68-
{messages.map((message: ReceivedChatMessage) => (
69-
<MotionChatEntry
70-
key={message.id}
71-
entry={message}
72-
hideName={hideName}
73-
hideTimestamp={hideTimestamp}
74-
messageFormatter={messageFormatter}
75-
{...MESSAGE_MOTION_PROPS}
76-
/>
77-
))}
65+
{messages.map(({ id, timestamp, from, message, editTimestamp }: ReceivedChatMessage) => {
66+
const name = from?.name ?? from?.identity;
67+
const locale = navigator?.language ?? 'en-US';
68+
const messageOrigin = from?.isLocal ? 'local' : 'remote';
69+
const hasBeenEdited = !!editTimestamp;
70+
71+
return (
72+
<MotionChatEntry
73+
key={id}
74+
name={name}
75+
locale={locale}
76+
timestamp={timestamp}
77+
message={message}
78+
messageOrigin={messageOrigin}
79+
hasBeenEdited={hasBeenEdited}
80+
{...MESSAGE_MOTION_PROPS}
81+
/>
82+
);
83+
})}
7884
</MotionContainer>
7985
)}
8086
</AnimatePresence>

components/livekit/chat-entry.tsx

Lines changed: 32 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,58 @@
11
import * as React from 'react';
2-
import { useMemo } from 'react';
3-
import type { MessageFormatter, ReceivedChatMessage } from '@livekit/components-react';
42
import { cn } from '@/lib/utils';
53

64
export interface ChatEntryProps extends React.HTMLAttributes<HTMLLIElement> {
7-
/** The chat massage object to display. */
8-
entry: ReceivedChatMessage;
9-
/** Hide sender name. Useful when displaying multiple consecutive chat messages from the same person. */
10-
hideName?: boolean;
11-
/** Hide message timestamp. */
12-
hideTimestamp?: boolean;
13-
/** An optional formatter for the message body. */
14-
messageFormatter?: MessageFormatter;
5+
/** The locale to use for the timestamp. */
6+
locale: string;
7+
/** The timestamp of the message. */
8+
timestamp: number;
9+
/** The message to display. */
10+
message: string;
11+
/** The origin of the message. */
12+
messageOrigin: 'local' | 'remote';
13+
/** The sender's name. */
14+
name?: string;
15+
/** Whether the message has been edited. */
16+
hasBeenEdited?: boolean;
1517
}
1618

1719
export const ChatEntry = ({
18-
entry,
19-
hideName = false,
20-
hideTimestamp = false,
20+
name,
21+
locale,
22+
timestamp,
23+
message,
24+
messageOrigin,
25+
hasBeenEdited = false,
2126
className,
22-
messageFormatter,
2327
...props
2428
}: ChatEntryProps) => {
25-
const time = new Date(entry.timestamp);
26-
const hasBeenEdited = !!entry.editTimestamp;
27-
const name = entry.from?.name || entry.from?.identity;
28-
const locale = typeof navigator !== 'undefined' ? navigator.language : 'en-US';
29-
30-
const isUser = entry.from?.isLocal ?? false;
31-
const messageOrigin = isUser ? 'remote' : 'local';
32-
const showHeader = !hideTimestamp || !hideName || hasBeenEdited;
29+
const time = new Date(timestamp);
3330
const title = time.toLocaleTimeString(locale, { timeStyle: 'full' });
3431

35-
const formattedMessage = useMemo(() => {
36-
return messageFormatter ? messageFormatter(entry.message) : entry.message;
37-
}, [entry.message, messageFormatter]);
38-
3932
return (
4033
<li
4134
title={title}
4235
data-lk-message-origin={messageOrigin}
4336
className={cn('group flex w-full flex-col gap-0.5', className)}
4437
{...props}
4538
>
46-
{showHeader && (
39+
{name && (
4740
<header className="text-muted-foreground flex text-sm">
48-
{!hideName && <strong className="mt-2">{name}</strong>}
49-
{!hideTimestamp && (
50-
<span className="align-self-end ml-auto font-mono text-xs opacity-0 transition-opacity ease-linear group-hover:opacity-100">
51-
{hasBeenEdited && '*'}
52-
{time.toLocaleTimeString(locale, { timeStyle: 'short' })}
53-
</span>
54-
)}
41+
{name && <strong className="mt-2">{name}</strong>}
42+
<span className="align-self-end ml-auto font-mono text-xs opacity-0 transition-opacity ease-linear group-hover:opacity-100">
43+
{hasBeenEdited && '*'}
44+
{time.toLocaleTimeString(locale, { timeStyle: 'short' })}
45+
</span>
5546
</header>
5647
)}
5748

58-
<span className={cn('max-w-4/5 rounded-[20px]', isUser ? 'bg-muted ml-auto p-2' : 'mr-auto')}>
59-
{formattedMessage}
49+
<span
50+
className={cn(
51+
'max-w-4/5 rounded-[20px]',
52+
messageOrigin === 'local' ? 'bg-muted ml-auto p-2' : 'mr-auto'
53+
)}
54+
>
55+
{message}
6056
</span>
6157
</li>
6258
);

0 commit comments

Comments
 (0)