refactor: enhance image block rendering and styling (#5567)

* refactor: enhance image block rendering and styling

* 更新 index.tsx

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>

* refactor: update key usage in MessageBlockRenderer for improved readability

---------

Co-authored-by: Chen Tao <70054568+eeee0717@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
This commit is contained in:
SuYao 2025-05-01 18:22:27 +08:00 committed by GitHub
parent f4debacbfc
commit 68e98f9a56
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 48 additions and 2 deletions

View File

@ -14,6 +14,7 @@ import type {
import { MessageBlockStatus, MessageBlockType } from '@renderer/types/newMessage' import { MessageBlockStatus, MessageBlockType } from '@renderer/types/newMessage'
import React from 'react' import React from 'react'
import { useSelector } from 'react-redux' import { useSelector } from 'react-redux'
import styled from 'styled-components'
import CitationBlock from './CitationBlock' import CitationBlock from './CitationBlock'
import ErrorBlock from './ErrorBlock' import ErrorBlock from './ErrorBlock'
@ -31,14 +32,42 @@ interface Props {
message: Message message: Message
} }
const filterImageBlockGroups = (blocks: MessageBlock[]): (MessageBlock[] | MessageBlock)[] => {
return blocks.reduce((acc: (MessageBlock[] | MessageBlock)[], currentBlock) => {
if (currentBlock.type === MessageBlockType.IMAGE) {
const prevGroup = acc[acc.length - 1]
if (Array.isArray(prevGroup) && prevGroup[0].type === MessageBlockType.IMAGE) {
prevGroup.push(currentBlock)
} else {
acc.push([currentBlock])
}
} else {
acc.push(currentBlock)
}
return acc
}, [])
}
const MessageBlockRenderer: React.FC<Props> = ({ blocks, message }) => { const MessageBlockRenderer: React.FC<Props> = ({ blocks, message }) => {
// 始终调用useSelector避免条件调用Hook // 始终调用useSelector避免条件调用Hook
const blockEntities = useSelector((state: RootState) => messageBlocksSelectors.selectEntities(state)) const blockEntities = useSelector((state: RootState) => messageBlocksSelectors.selectEntities(state))
// 根据blocks类型处理渲染数据 // 根据blocks类型处理渲染数据
const renderedBlocks = blocks.map((blockId) => blockEntities[blockId]).filter(Boolean) const renderedBlocks = blocks.map((blockId) => blockEntities[blockId]).filter(Boolean)
const groupedBlocks = filterImageBlockGroups(renderedBlocks)
return ( return (
<> <>
{renderedBlocks.map((block) => { {groupedBlocks.map((block) => {
if (Array.isArray(block)) {
return (
<ImageBlockGroup key={block.map((imageBlock) => imageBlock.id).join('-')}>
{block.map((imageBlock) => (
<ImageBlock key={imageBlock.id} block={imageBlock as ImageMessageBlock} />
))}
</ImageBlockGroup>
)
}
switch (block.type) { switch (block.type) {
case MessageBlockType.UNKNOWN: case MessageBlockType.UNKNOWN:
if (block.status === MessageBlockStatus.PROCESSING) { if (block.status === MessageBlockStatus.PROCESSING) {
@ -90,3 +119,18 @@ const MessageBlockRenderer: React.FC<Props> = ({ blocks, message }) => {
} }
export default React.memo(MessageBlockRenderer) export default React.memo(MessageBlockRenderer)
const ImageBlockGroup = styled.div`
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-items: center;
gap: 8px;
width: 100%;
margin: 8px 0;
> * {
flex: 0 0 auto;
min-width: 200px;
max-width: calc(33.33% - 8px);
}
`

View File

@ -99,7 +99,6 @@ const MessageImage: FC<Props> = ({ block }) => {
<Image <Image
src={image} src={image}
key={`image-${index}`} key={`image-${index}`}
width="33%"
preview={{ preview={{
toolbarRender: ( toolbarRender: (
_, _,
@ -131,9 +130,12 @@ const Container = styled.div`
flex-direction: row; flex-direction: row;
gap: 10px; gap: 10px;
margin-top: 8px; margin-top: 8px;
width: 100%;
` `
const Image = styled(AntdImage)` const Image = styled(AntdImage)`
border-radius: 10px; border-radius: 10px;
width: 100%;
height: auto;
` `
const ToobarWrapper = styled(Space)` const ToobarWrapper = styled(Space)`
padding: 0px 24px; padding: 0px 24px;