mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-26 20:12:38 +08:00
refactor(ThinkingEffect): optimize thinking effect (#8232)
* refactor(ThinkingEffect): optimize message rendering and adjust styles - Removed unnecessary motion components and simplified message rendering logic. - Updated line height and container dimensions for better layout consistency. - Adjusted padding and width in styled components for improved visual appearance. * fix(ThinkingBlock): remove margin-top from snapshot for consistent styling * refactor(Message): remove unnecessary padding adjustments for assistant messages
This commit is contained in:
parent
fe91d4b56a
commit
e85ea1ff28
@ -1,7 +1,7 @@
|
||||
import { lightbulbVariants } from '@renderer/utils/motionVariants'
|
||||
import { isEqual } from 'lodash'
|
||||
import { ChevronRight, Lightbulb } from 'lucide-react'
|
||||
import { AnimatePresence, motion } from 'motion/react'
|
||||
import { motion } from 'motion/react'
|
||||
import React, { useEffect, useMemo, useState } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
@ -25,15 +25,15 @@ const ThinkingEffect: React.FC<Props> = ({ isThinking, thinkingTimeText, content
|
||||
}
|
||||
}, [content, isThinking, messages])
|
||||
|
||||
const lineHeight = 16
|
||||
const LINE_HEIGHT = 14
|
||||
const containerHeight = useMemo(() => {
|
||||
if (expanded) return lineHeight * 3
|
||||
return Math.min(80, Math.max(messages.length + 2, 3) * lineHeight)
|
||||
if (expanded || messages.length < 2) return 38
|
||||
return Math.min(68, Math.max(messages.length + 1, 2) * LINE_HEIGHT + 10)
|
||||
}, [expanded, messages.length])
|
||||
|
||||
return (
|
||||
<ThinkingContainer style={{ height: containerHeight }} className={expanded ? 'expanded' : ''}>
|
||||
<LoadingContainer className={expanded || !messages.length ? 'expanded' : ''}>
|
||||
<LoadingContainer>
|
||||
<motion.div variants={lightbulbVariants} animate={isThinking ? 'active' : 'idle'} initial="idle">
|
||||
<Lightbulb size={expanded || !messages.length ? 20 : 30} style={{ transition: 'width,height, 150ms' }} />
|
||||
</motion.div>
|
||||
@ -44,31 +44,26 @@ const ThinkingEffect: React.FC<Props> = ({ isThinking, thinkingTimeText, content
|
||||
|
||||
{!expanded && (
|
||||
<Content>
|
||||
<AnimatePresence>
|
||||
<Messages
|
||||
style={{
|
||||
height: messages.length * LINE_HEIGHT
|
||||
}}
|
||||
initial={{
|
||||
y: -2
|
||||
}}
|
||||
animate={{
|
||||
y: -messages.length * LINE_HEIGHT - 2
|
||||
}}
|
||||
transition={{
|
||||
duration: 0.15,
|
||||
ease: 'linear'
|
||||
}}>
|
||||
{messages.map((message, index) => {
|
||||
const finalY = containerHeight - (messages.length - index) * lineHeight - 4
|
||||
|
||||
if (index < messages.length - 5) return null
|
||||
|
||||
return (
|
||||
<ContentLineMotion
|
||||
key={index}
|
||||
initial={{
|
||||
y: index === messages.length - 1 ? containerHeight : finalY + lineHeight,
|
||||
height: lineHeight
|
||||
}}
|
||||
animate={{
|
||||
y: finalY
|
||||
}}
|
||||
transition={{
|
||||
duration: 0.15,
|
||||
ease: 'linear'
|
||||
}}>
|
||||
{message}
|
||||
</ContentLineMotion>
|
||||
)
|
||||
return <Message key={index}>{message}</Message>
|
||||
})}
|
||||
</AnimatePresence>
|
||||
</Messages>
|
||||
</Content>
|
||||
)}
|
||||
</TextContainer>
|
||||
@ -99,17 +94,18 @@ const Title = styled.div`
|
||||
position: absolute;
|
||||
inset: 0 0 auto 0;
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
font-weight: 500;
|
||||
padding: 4px 0 30px;
|
||||
padding: 6px 0;
|
||||
z-index: 99;
|
||||
transition: padding-top 150ms;
|
||||
&.expanded {
|
||||
padding-top: 14px;
|
||||
padding-top: 12px;
|
||||
}
|
||||
`
|
||||
|
||||
const LoadingContainer = styled.div`
|
||||
width: 60px;
|
||||
width: 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@ -123,9 +119,6 @@ const LoadingContainer = styled.div`
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
&.expanded {
|
||||
width: 40px;
|
||||
}
|
||||
`
|
||||
|
||||
const TextContainer = styled.div`
|
||||
@ -135,7 +128,7 @@ const TextContainer = styled.div`
|
||||
position: relative;
|
||||
`
|
||||
|
||||
const Content = styled(motion.div)`
|
||||
const Content = styled.div`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
mask: linear-gradient(
|
||||
@ -146,17 +139,26 @@ const Content = styled(motion.div)`
|
||||
rgb(0 0 0 / 100%) 90%,
|
||||
rgb(0 0 0 / 100%) 100%
|
||||
);
|
||||
position: relative;
|
||||
`
|
||||
|
||||
const ContentLineMotion = styled(motion.div)`
|
||||
const Messages = styled(motion.div)`
|
||||
width: 100%;
|
||||
line-height: 16px;
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
`
|
||||
|
||||
const Message = styled.div`
|
||||
width: 100%;
|
||||
line-height: 14px;
|
||||
font-size: 11px;
|
||||
color: var(--color-text-2);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
position: absolute;
|
||||
`
|
||||
|
||||
const ArrowContainer = styled.div`
|
||||
|
||||
@ -136,7 +136,6 @@ const ThinkingTimeSeconds = memo(
|
||||
)
|
||||
|
||||
const CollapseContainer = styled(Collapse)`
|
||||
margin-top: 15px;
|
||||
margin-bottom: 15px;
|
||||
.ant-collapse-header {
|
||||
padding: 0 !important;
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
exports[`ThinkingBlock > basic rendering > should match snapshot 1`] = `
|
||||
.c0 {
|
||||
margin-top: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ import MessageContent from '@renderer/pages/home/Messages/MessageContent'
|
||||
import MessageErrorBoundary from '@renderer/pages/home/Messages/MessageErrorBoundary'
|
||||
// import { LegacyMessage } from '@renderer/types'
|
||||
import type { Message } from '@renderer/types/newMessage'
|
||||
import { classNames } from '@renderer/utils'
|
||||
import { FC, memo, useRef } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
@ -21,7 +22,6 @@ const MessageItem: FC<Props> = ({ message, index, total, route }) => {
|
||||
// const [message, setMessage] = useState(_message)
|
||||
// const [bl, setTextBlock] = useState<MainTextMessageBlock | null>(null)
|
||||
// const model = useModel(getMessageModelId(message))
|
||||
const isBubbleStyle = true
|
||||
const { messageFont, fontSize } = useSettings()
|
||||
const messageContainerRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
@ -39,14 +39,18 @@ const MessageItem: FC<Props> = ({ message, index, total, route }) => {
|
||||
<MessageContainer
|
||||
key={message.id}
|
||||
ref={messageContainerRef}
|
||||
style={{ ...(isBubbleStyle ? { alignItems: isAssistantMessage ? 'start' : 'end' } : {}), maxWidth }}>
|
||||
className={classNames({
|
||||
message: true,
|
||||
'message-assistant': isAssistantMessage,
|
||||
'message-user': !isAssistantMessage
|
||||
})}
|
||||
style={{ maxWidth }}>
|
||||
<MessageContentContainer
|
||||
className="message-content-container"
|
||||
style={{
|
||||
fontFamily: messageFont === 'serif' ? 'var(--font-family-serif)' : 'var(--font-family)',
|
||||
fontSize,
|
||||
background: messageBackground,
|
||||
...(isAssistantMessage ? { paddingLeft: 5, paddingRight: 5 } : {})
|
||||
background: messageBackground
|
||||
}}>
|
||||
<MessageErrorBoundary>
|
||||
<MessageContent message={message} />
|
||||
|
||||
Loading…
Reference in New Issue
Block a user