mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-03 02:59:07 +08:00
feat: add functionality to insert messages at a specific index in the… (#6299)
* feat: add functionality to insert messages at a specific index in the Redux store - Introduced a new interface for inserting messages at a specified index. - Implemented the insertMessageAtIndex reducer to handle message insertion. - Updated saveMessageAndBlocksToDB to support message insertion logic. - Modified appendAssistantResponseThunk to utilize the new insertion functionality. * feat: integrate multi-select mode handling in MessageGroup component - Added useChatContext hook to access multi-select mode state. - Updated isGrouped logic to account for multi-select mode, ensuring proper message grouping behavior. - Enhanced MessageWrapper styles for better layout management in different modes. --------- Co-authored-by: kangfenmao <kangfenmao@qq.com>
This commit is contained in:
parent
c000203ac1
commit
46ca79ef5c
@ -1,5 +1,6 @@
|
|||||||
import Scrollbar from '@renderer/components/Scrollbar'
|
import Scrollbar from '@renderer/components/Scrollbar'
|
||||||
import { MessageEditingProvider } from '@renderer/context/MessageEditingContext'
|
import { MessageEditingProvider } from '@renderer/context/MessageEditingContext'
|
||||||
|
import { useChatContext } from '@renderer/hooks/useChatContext'
|
||||||
import { useMessageOperations } from '@renderer/hooks/useMessageOperations'
|
import { useMessageOperations } from '@renderer/hooks/useMessageOperations'
|
||||||
import { useSettings } from '@renderer/hooks/useSettings'
|
import { useSettings } from '@renderer/hooks/useSettings'
|
||||||
import { MultiModelMessageStyle } from '@renderer/store/settings'
|
import { MultiModelMessageStyle } from '@renderer/store/settings'
|
||||||
@ -24,6 +25,7 @@ interface Props {
|
|||||||
const MessageGroup = ({ messages, topic, hidePresetMessages, registerMessageElement }: Props) => {
|
const MessageGroup = ({ messages, topic, hidePresetMessages, registerMessageElement }: Props) => {
|
||||||
const { editMessage } = useMessageOperations(topic)
|
const { editMessage } = useMessageOperations(topic)
|
||||||
const { multiModelMessageStyle: multiModelMessageStyleSetting, gridColumns, gridPopoverTrigger } = useSettings()
|
const { multiModelMessageStyle: multiModelMessageStyleSetting, gridColumns, gridPopoverTrigger } = useSettings()
|
||||||
|
const { isMultiSelectMode } = useChatContext(topic)
|
||||||
|
|
||||||
const [multiModelMessageStyle, setMultiModelMessageStyle] = useState<MultiModelMessageStyle>(
|
const [multiModelMessageStyle, setMultiModelMessageStyle] = useState<MultiModelMessageStyle>(
|
||||||
messages[0].multiModelMessageStyle || multiModelMessageStyleSetting
|
messages[0].multiModelMessageStyle || multiModelMessageStyleSetting
|
||||||
@ -59,7 +61,7 @@ const MessageGroup = ({ messages, topic, hidePresetMessages, registerMessageElem
|
|||||||
[editMessage, selectedMessageId]
|
[editMessage, selectedMessageId]
|
||||||
)
|
)
|
||||||
|
|
||||||
const isGrouped = messageLength > 1 && messages.every((m) => m.role === 'assistant')
|
const isGrouped = isMultiSelectMode ? false : messageLength > 1 && messages.every((m) => m.role === 'assistant')
|
||||||
const isHorizontal = multiModelMessageStyle === 'horizontal'
|
const isHorizontal = multiModelMessageStyle === 'horizontal'
|
||||||
const isGrid = multiModelMessageStyle === 'grid'
|
const isGrid = multiModelMessageStyle === 'grid'
|
||||||
|
|
||||||
@ -298,6 +300,19 @@ interface MessageWrapperProps {
|
|||||||
const MessageWrapper = styled(Scrollbar)<MessageWrapperProps>`
|
const MessageWrapper = styled(Scrollbar)<MessageWrapperProps>`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
&.horizontal {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
&.grid {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
&.fold {
|
||||||
|
display: none;
|
||||||
|
&.selected {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
${({ $layout, $isGrouped }) => {
|
${({ $layout, $isGrouped }) => {
|
||||||
if ($layout === 'horizontal' && $isGrouped) {
|
if ($layout === 'horizontal' && $isGrouped) {
|
||||||
return css`
|
return css`
|
||||||
|
|||||||
@ -59,6 +59,13 @@ interface RemoveMessagesPayload {
|
|||||||
messageIds: string[]
|
messageIds: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Payload for inserting a message at a specific index
|
||||||
|
interface InsertMessageAtIndexPayload {
|
||||||
|
topicId: string
|
||||||
|
message: Message
|
||||||
|
index: number
|
||||||
|
}
|
||||||
|
|
||||||
// 4. Create the Slice with Refactored Reducers
|
// 4. Create the Slice with Refactored Reducers
|
||||||
const messagesSlice = createSlice({
|
const messagesSlice = createSlice({
|
||||||
name: 'newMessages',
|
name: 'newMessages',
|
||||||
@ -95,6 +102,20 @@ const messagesSlice = createSlice({
|
|||||||
state.loadingByTopic[topicId] = false
|
state.loadingByTopic[topicId] = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
insertMessageAtIndex(state, action: PayloadAction<InsertMessageAtIndexPayload>) {
|
||||||
|
const { topicId, message, index } = action.payload
|
||||||
|
messagesAdapter.addOne(state, message) // Add message to entities
|
||||||
|
if (!state.messageIdsByTopic[topicId]) {
|
||||||
|
state.messageIdsByTopic[topicId] = []
|
||||||
|
}
|
||||||
|
// Ensure index is within bounds
|
||||||
|
const safeIndex = Math.max(0, Math.min(index, state.messageIdsByTopic[topicId].length))
|
||||||
|
state.messageIdsByTopic[topicId].splice(safeIndex, 0, message.id) // Insert ID at specified index
|
||||||
|
|
||||||
|
if (!(topicId in state.loadingByTopic)) {
|
||||||
|
state.loadingByTopic[topicId] = false
|
||||||
|
}
|
||||||
|
},
|
||||||
updateMessage(
|
updateMessage(
|
||||||
state,
|
state,
|
||||||
action: PayloadAction<{
|
action: PayloadAction<{
|
||||||
|
|||||||
@ -49,20 +49,24 @@ const handleChangeLoadingOfTopic = async (topicId: string) => {
|
|||||||
store.dispatch(newMessagesActions.setTopicLoading({ topicId, loading: false }))
|
store.dispatch(newMessagesActions.setTopicLoading({ topicId, loading: false }))
|
||||||
}
|
}
|
||||||
// TODO: 后续可以将db操作移到Listener Middleware中
|
// TODO: 后续可以将db操作移到Listener Middleware中
|
||||||
export const saveMessageAndBlocksToDB = async (message: Message, blocks: MessageBlock[]) => {
|
export const saveMessageAndBlocksToDB = async (message: Message, blocks: MessageBlock[], messageIndex: number = -1) => {
|
||||||
try {
|
try {
|
||||||
if (blocks.length > 0) {
|
if (blocks.length > 0) {
|
||||||
await db.message_blocks.bulkPut(blocks)
|
await db.message_blocks.bulkPut(blocks)
|
||||||
}
|
}
|
||||||
const topic = await db.topics.get(message.topicId)
|
const topic = await db.topics.get(message.topicId)
|
||||||
if (topic) {
|
if (topic) {
|
||||||
const messageIndex = topic.messages.findIndex((m) => m.id === message.id)
|
const _messageIndex = topic.messages.findIndex((m) => m.id === message.id)
|
||||||
const updatedMessages = [...topic.messages]
|
const updatedMessages = [...topic.messages]
|
||||||
|
|
||||||
if (messageIndex !== -1) {
|
if (_messageIndex !== -1) {
|
||||||
updatedMessages[messageIndex] = message
|
updatedMessages[_messageIndex] = message
|
||||||
} else {
|
} else {
|
||||||
updatedMessages.push(message)
|
if (messageIndex !== -1) {
|
||||||
|
updatedMessages.splice(messageIndex, 0, message)
|
||||||
|
} else {
|
||||||
|
updatedMessages.push(message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await db.topics.update(message.topicId, { messages: updatedMessages })
|
await db.topics.update(message.topicId, { messages: updatedMessages })
|
||||||
} else {
|
} else {
|
||||||
@ -1244,10 +1248,14 @@ export const appendAssistantResponseThunk =
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 3. Update Redux Store
|
// 3. Update Redux Store
|
||||||
dispatch(newMessagesActions.addMessage({ topicId, message: newAssistantStub }))
|
const currentTopicMessageIds = getState().messages.messageIdsByTopic[topicId] || []
|
||||||
|
const existingMessageIndex = currentTopicMessageIds.findIndex((id) => id === existingAssistantMessageId)
|
||||||
|
const insertAtIndex = existingMessageIndex !== -1 ? existingMessageIndex + 1 : currentTopicMessageIds.length
|
||||||
|
|
||||||
|
dispatch(newMessagesActions.insertMessageAtIndex({ topicId, message: newAssistantStub, index: insertAtIndex }))
|
||||||
|
|
||||||
// 4. Update Database (Save the stub to the topic's message list)
|
// 4. Update Database (Save the stub to the topic's message list)
|
||||||
await saveMessageAndBlocksToDB(newAssistantStub, [])
|
await saveMessageAndBlocksToDB(newAssistantStub, [], insertAtIndex)
|
||||||
|
|
||||||
// 5. Prepare and queue the processing task
|
// 5. Prepare and queue the processing task
|
||||||
const assistantConfigForThisCall = {
|
const assistantConfigForThisCall = {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user