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