This commit is contained in:
07akioni
2026-07-31 19:20:12 +08:00
parent 94a600eddd
commit 57d6d9ee1c

View File

@@ -142,41 +142,52 @@ function projectUserText(text: string): ReactNode {
return <>{parts}</> return <>{parts}</>
} }
/** Right-aligned bubble shared by user and steering rows (steering has no actions). */
function UserStyleBubble({
content, actions, t,
}: {
content: readonly unknown[]
/** Optional IconActions (or similar) below the bubble; receives the joined text. */
actions?: (text: string) => ReactNode
t: ChatViewSlotProps['t']
}): ReactNode {
const { text, rest } = contentText(content)
const truncated = (total: number): string => t('json.truncated', { total })
return (
<div className={css.userRow}>
<div className={css.bubble}>
{projectUserText(text)}
{rest.map((block, i) => <JsonBlock key={i} label={t('message.extraBlock')} payload={block} truncatedLabel={truncated} />)}
</div>
{actions?.(text)}
</div>
)
}
export const MessageItem = memo(function MessageItem({ export const MessageItem = memo(function MessageItem({
node, retryActive = false, onFork, t, node, retryActive = false, onFork, t,
}: MessageItemProps) { }: MessageItemProps) {
const truncated = (total: number): string => t('json.truncated', { total }) const truncated = (total: number): string => t('json.truncated', { total })
switch (node.kind) { switch (node.kind) {
case 'user': { case 'user':
const { text, rest } = contentText(node.content)
return ( return (
<div className={css.userRow}> <UserStyleBubble
<div className={css.bubble}> content={node.content}
{projectUserText(text)} t={t}
{rest.map((block, i) => <JsonBlock key={i} label={t('message.extraBlock')} payload={block} truncatedLabel={truncated} />)} actions={text => (
</div> <MessageIconActions
<MessageIconActions text={text}
text={text} time={node.time}
time={node.time} clock="start"
clock="start" onBranch={onFork === undefined ? undefined : () => { onFork(node.seq) }}
onBranch={onFork === undefined ? undefined : () => { onFork(node.seq) }} className={css.actions}
className={css.actions} t={t}
t={t} />
/> )}
</div> />
) )
} case 'steering':
case 'steering': { return <UserStyleBubble content={node.content} t={t} />
const { text, rest } = contentText(node.content)
return (
<div className={css.userRow}>
<div className={css.bubble}>
{projectUserText(text)}
{rest.map((block, i) => <JsonBlock key={i} label={t('message.extraBlock')} payload={block} truncatedLabel={truncated} />)}
</div>
</div>
)
}
case 'context': case 'context':
return ( return (
<ContextInjectionRow content={node.content} source={node.source} t={t} /> <ContextInjectionRow content={node.content} source={node.source} t={t} />