@@ -6,8 +6,10 @@ import { useSettings } from '@renderer/hooks/useSettings'
66import { useAppDispatch } from '@renderer/store'
77import { setFoldDisplayMode } from '@renderer/store/settings'
88import type { Model } from '@renderer/types'
9- import type { Message } from '@renderer/types/newMessage'
9+ import { AssistantMessageStatus , type Message } from '@renderer/types/newMessage'
10+ import { lightbulbSoftVariants } from '@renderer/utils/motionVariants'
1011import { Avatar , Segmented as AntdSegmented , Tooltip } from 'antd'
12+ import { motion } from 'motion/react'
1113import { FC , memo , useCallback } from 'react'
1214import { useTranslation } from 'react-i18next'
1315import styled from 'styled-components'
@@ -26,50 +28,62 @@ const MessageGroupModelList: FC<MessageGroupModelListProps> = ({ messages, selec
2628 const { foldDisplayMode } = useSettings ( )
2729 const isCompact = foldDisplayMode === 'compact'
2830
31+ const isMessageProcessing = useCallback ( ( message : Message ) => {
32+ return [
33+ AssistantMessageStatus . PENDING ,
34+ AssistantMessageStatus . PROCESSING ,
35+ AssistantMessageStatus . SEARCHING
36+ ] . includes ( message . status as AssistantMessageStatus )
37+ } , [ ] )
38+
2939 const renderLabel = useCallback (
3040 ( message : Message ) => {
3141 const modelTip = message . model ?. name
42+ const isProcessing = isMessageProcessing ( message )
3243
3344 if ( isCompact ) {
3445 return (
35- < Tooltip key = { message . id } title = { modelTip } mouseEnterDelay = { 0.5 } >
46+ < Tooltip key = { message . id } title = { modelTip } mouseEnterDelay = { 0.5 } mouseLeaveDelay = { 0 } >
3647 < AvatarWrapper
3748 className = "avatar-wrapper"
3849 $isSelected = { message . id === selectMessageId }
3950 onClick = { ( ) => {
4051 setSelectedMessage ( message )
4152 } } >
42- < ModelAvatar model = { message . model as Model } size = { 22 } />
53+ < motion . span variants = { lightbulbSoftVariants } animate = { isProcessing ? 'active' : 'idle' } initial = "idle" >
54+ < ModelAvatar model = { message . model as Model } size = { 22 } />
55+ </ motion . span >
4356 </ AvatarWrapper >
4457 </ Tooltip >
4558 )
4659 }
4760 return (
4861 < SegmentedLabel >
49- < ModelAvatar model = { message . model as Model } size = { 20 } />
62+ < ModelAvatar className = { isProcessing ? 'animation-pulse' : '' } model = { message . model as Model } size = { 20 } />
5063 < ModelName > { message . model ?. name } </ ModelName >
5164 </ SegmentedLabel >
5265 )
5366 } ,
54- [ isCompact , selectMessageId , setSelectedMessage ]
67+ [ isCompact , isMessageProcessing , selectMessageId , setSelectedMessage ]
5568 )
5669
5770 return (
5871 < Container >
59- < DisplayModeToggle
60- displayMode = { foldDisplayMode }
61- onClick = { ( ) => dispatch ( setFoldDisplayMode ( isCompact ? 'expanded' : 'compact' ) ) } >
62- < Tooltip
63- title = {
64- isCompact
65- ? t ( `message.message.multi_model_style.fold.expand` )
66- : t ( 'message.message.multi_model_style.fold.compress' )
67- }
68- placement = "top" >
72+ < Tooltip
73+ title = {
74+ isCompact
75+ ? t ( `message.message.multi_model_style.fold.expand` )
76+ : t ( 'message.message.multi_model_style.fold.compress' )
77+ }
78+ placement = "top"
79+ mouseEnterDelay = { 0.5 }
80+ mouseLeaveDelay = { 0 } >
81+ < DisplayModeToggle
82+ displayMode = { foldDisplayMode }
83+ onClick = { ( ) => dispatch ( setFoldDisplayMode ( isCompact ? 'expanded' : 'compact' ) ) } >
6984 { isCompact ? < ArrowsAltOutlined /> : < ShrinkOutlined /> }
70- </ Tooltip >
71- </ DisplayModeToggle >
72-
85+ </ DisplayModeToggle >
86+ </ Tooltip >
7387 < ModelsContainer $displayMode = { foldDisplayMode } >
7488 { isCompact ? (
7589 /* Compact style display */
0 commit comments