fix: group message bugs

This commit is contained in:
kangfenmao 2025-01-22 16:15:56 +08:00
parent 084da9ebab
commit a6f086e3be
9 changed files with 53 additions and 14 deletions

View File

@ -256,9 +256,6 @@ body,
border: 1px solid var(--color-background-mute); border: 1px solid var(--color-background-mute);
} }
} }
.group-menu-bar {
background-color: var(--color-background);
}
code { code {
color: var(--color-text); color: var(--color-text);
} }

View File

@ -253,6 +253,10 @@
"message.style": "Message style", "message.style": "Message style",
"message.style.bubble": "Bubble", "message.style.bubble": "Bubble",
"message.style.plain": "Plain", "message.style.plain": "Plain",
"message.multi_model_style": "Multi-model answer style",
"message.multi_model_style.horizontal": "Horizontal",
"message.multi_model_style.vertical": "Vertical",
"message.multi_model_style.fold": "Fold",
"reset.confirm.content": "Are you sure you want to clear all data?", "reset.confirm.content": "Are you sure you want to clear all data?",
"reset.double.confirm.content": "All data will be lost, do you want to continue?", "reset.double.confirm.content": "All data will be lost, do you want to continue?",
"reset.double.confirm.title": "DATA LOST !!!", "reset.double.confirm.title": "DATA LOST !!!",

View File

@ -252,6 +252,10 @@
"message.style": "メッセージスタイル", "message.style": "メッセージスタイル",
"message.style.bubble": "バブル", "message.style.bubble": "バブル",
"message.style.plain": "プレーン", "message.style.plain": "プレーン",
"message.multi_model_style": "複数モデル回答スタイル",
"message.multi_model_style.horizontal": "水平",
"message.multi_model_style.vertical": "垂直",
"message.multi_model_style.fold": "折りたたむ",
"reset.confirm.content": "すべてのデータをリセットしてもよろしいですか?", "reset.confirm.content": "すべてのデータをリセットしてもよろしいですか?",
"reset.double.confirm.content": "すべてのデータが失われます。続行しますか?", "reset.double.confirm.content": "すべてのデータが失われます。続行しますか?",
"reset.double.confirm.title": "データが失われます!!!", "reset.double.confirm.title": "データが失われます!!!",

View File

@ -253,6 +253,10 @@
"message.style": "Стиль сообщения", "message.style": "Стиль сообщения",
"message.style.bubble": "Пузырь", "message.style.bubble": "Пузырь",
"message.style.plain": "Простой", "message.style.plain": "Простой",
"message.multi_model_style": "Стиль ответов от нескольких моделей",
"message.multi_model_style.horizontal": "Горизонтальный",
"message.multi_model_style.vertical": "Вертикальный",
"message.multi_model_style.fold": "Свернуть",
"reset.confirm.content": "Вы уверены, что хотите очистить все данные?", "reset.confirm.content": "Вы уверены, что хотите очистить все данные?",
"reset.double.confirm.content": "Все данные будут утеряны, хотите продолжить?", "reset.double.confirm.content": "Все данные будут утеряны, хотите продолжить?",
"reset.double.confirm.title": "ДАННЫЕ БУДУТ УТЕРЯНЫ !!!", "reset.double.confirm.title": "ДАННЫЕ БУДУТ УТЕРЯНЫ !!!",

View File

@ -253,6 +253,10 @@
"message.style": "消息樣式", "message.style": "消息樣式",
"message.style.bubble": "氣泡", "message.style.bubble": "氣泡",
"message.style.plain": "簡潔", "message.style.plain": "簡潔",
"message.multi_model_style": "多模型回答樣式",
"message.multi_model_style.horizontal": "水平",
"message.multi_model_style.vertical": "垂直",
"message.multi_model_style.fold": "折疊",
"reset.confirm.content": "確定要清除所有資料嗎?", "reset.confirm.content": "確定要清除所有資料嗎?",
"reset.double.confirm.content": "所有資料將會被清除,您確定要繼續嗎?", "reset.double.confirm.content": "所有資料將會被清除,您確定要繼續嗎?",
"reset.double.confirm.title": "資料將會丟失!!!", "reset.double.confirm.title": "資料將會丟失!!!",

View File

@ -27,6 +27,7 @@ interface Props {
total?: number total?: number
hidePresetMessages?: boolean hidePresetMessages?: boolean
style?: React.CSSProperties style?: React.CSSProperties
isGrouped?: boolean
onGetMessages?: () => Message[] onGetMessages?: () => Message[]
onSetMessages?: Dispatch<SetStateAction<Message[]>> onSetMessages?: Dispatch<SetStateAction<Message[]>>
onDeleteMessage?: (message: Message) => Promise<void> onDeleteMessage?: (message: Message) => Promise<void>
@ -45,6 +46,7 @@ const MessageItem: FC<Props> = ({
topic, topic,
index, index,
hidePresetMessages, hidePresetMessages,
isGrouped,
style, style,
onDeleteMessage, onDeleteMessage,
onSetMessages, onSetMessages,
@ -187,6 +189,7 @@ const MessageItem: FC<Props> = ({
index={index} index={index}
isLastMessage={isLastMessage} isLastMessage={isLastMessage}
isAssistantMessage={isAssistantMessage} isAssistantMessage={isAssistantMessage}
isGrouped={isGrouped}
setModel={setModel} setModel={setModel}
onEditMessage={onEditMessage} onEditMessage={onEditMessage}
onDeleteMessage={onDeleteMessage} onDeleteMessage={onDeleteMessage}

View File

@ -6,7 +6,7 @@ import { useSettings } from '@renderer/hooks/useSettings'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService' import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
import { MultiModelMessageStyle } from '@renderer/store/settings' import { MultiModelMessageStyle } from '@renderer/store/settings'
import { Message, Model, Topic } from '@renderer/types' import { Message, Model, Topic } from '@renderer/types'
import { Button, Segmented } from 'antd' import { Button, Segmented as AntdSegmented } from 'antd'
import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react' import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react'
import styled, { css } from 'styled-components' import styled, { css } from 'styled-components'
@ -63,6 +63,7 @@ const MessageGroup: FC<Props> = ({
key={message.id} key={message.id}
className={message.role === 'assistant' && isHorizontal && isGrouped ? 'group-message-wrapper' : ''}> className={message.role === 'assistant' && isHorizontal && isGrouped ? 'group-message-wrapper' : ''}>
<MessageItem <MessageItem
isGrouped={isGrouped}
message={message} message={message}
topic={topic} topic={topic}
index={message.index} index={message.index}
@ -76,10 +77,10 @@ const MessageGroup: FC<Props> = ({
))} ))}
</GridContainer> </GridContainer>
{isGrouped && ( {isGrouped && (
<GroupMenuBar className="group-menu-bar"> <GroupMenuBar className="group-menu-bar" $layout={multiModelMessageStyle}>
<HStack style={{ alignItems: 'center', flex: 1, overflow: 'hidden' }}> <HStack style={{ alignItems: 'center', flex: 1, overflow: 'hidden' }}>
<LayoutContainer> <LayoutContainer>
{['fold', 'horizontal', 'vertical'].map((layout) => ( {['fold', 'vertical', 'horizontal'].map((layout) => (
<LayoutOption <LayoutOption
key={layout} key={layout}
active={multiModelMessageStyle === layout} active={multiModelMessageStyle === layout}
@ -180,17 +181,20 @@ const MessageWrapper = styled(Scrollbar)<MessageWrapperProps>`
}} }}
` `
const GroupMenuBar = styled.div` const GroupMenuBar = styled.div<{ $layout: MultiModelMessageStyle }>`
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
gap: 10px; gap: 10px;
background-color: var(--color-background-soft);
padding: 6px 10px; padding: 6px 10px;
border-radius: 6px; border-radius: 6px;
margin-top: 10px; margin-top: 10px;
justify-content: space-between; justify-content: space-between;
overflow: hidden; overflow: hidden;
border: 0.5px solid var(--color-border);
height: 40px;
margin-left: ${({ $layout }) => ($layout === 'horizontal' ? '0' : '40px')};
transition: all 0.3s ease;
` `
const LayoutContainer = styled.div` const LayoutContainer = styled.div`
@ -203,11 +207,10 @@ const LayoutOption = styled.div<{ active: boolean }>`
cursor: pointer; cursor: pointer;
padding: 2px 10px; padding: 2px 10px;
border-radius: 4px; border-radius: 4px;
background-color: ${({ active }) => (active ? 'var(--color-primary)' : 'transparent')}; background-color: ${({ active }) => (active ? 'var(--color-background-soft)' : 'transparent')};
color: ${({ active }) => (active ? 'var(--color-white)' : 'inherit')};
&:hover { &:hover {
background-color: ${({ active }) => (active ? 'var(--color-primary)' : 'var(--color-hover)')}; background-color: ${({ active }) => (active ? 'var(--color-background-soft)' : 'var(--color-hover)')};
} }
` `
@ -220,6 +223,22 @@ const ModelsContainer = styled(Scrollbar)`
} }
` `
const Segmented = styled(AntdSegmented)`
.ant-segmented-item {
background-color: transparent !important;
transition: none !important;
&:hover {
background: transparent !important;
}
}
.ant-segmented-thumb,
.ant-segmented-item-selected {
background-color: transparent !important;
border: 0.5px solid var(--color-border);
transition: none !important;
}
`
const SegmentedLabel = styled.div` const SegmentedLabel = styled.div`
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -30,6 +30,7 @@ interface Props {
assistantModel?: Model assistantModel?: Model
model?: Model model?: Model
index?: number index?: number
isGrouped?: boolean
isLastMessage: boolean isLastMessage: boolean
isAssistantMessage: boolean isAssistantMessage: boolean
setModel: (model: Model) => void setModel: (model: Model) => void
@ -42,6 +43,7 @@ const MessageMenubar: FC<Props> = (props) => {
const { const {
message, message,
index, index,
isGrouped,
model, model,
isLastMessage, isLastMessage,
isAssistantMessage, isAssistantMessage,
@ -252,14 +254,16 @@ const MessageMenubar: FC<Props> = (props) => {
</ActionButton> </ActionButton>
</Tooltip> </Tooltip>
)} )}
<Popconfirm <Popconfirm
disabled={isGrouped}
title={t('message.message.delete.content')} title={t('message.message.delete.content')}
okButtonProps={{ danger: true }} okButtonProps={{ danger: true }}
icon={<QuestionCircleOutlined style={{ color: 'red' }} />} icon={<QuestionCircleOutlined style={{ color: 'red' }} />}
onConfirm={() => onDeleteMessage?.(message)}> onConfirm={() => onDeleteMessage?.(message)}>
<Tooltip title={t('common.delete')} mouseEnterDelay={1}> <Tooltip title={t('common.delete')} mouseEnterDelay={1}>
<ActionButton className="message-action-button"> <ActionButton
className="message-action-button"
onClick={isGrouped ? () => onDeleteMessage?.(message) : undefined}>
<DeleteOutlined /> <DeleteOutlined />
</ActionButton> </ActionButton>
</Tooltip> </Tooltip>

View File

@ -265,8 +265,8 @@ const SettingsTab: FC<Props> = (props) => {
onChange={(value) => dispatch(setMultiModelMessageStyle(value))} onChange={(value) => dispatch(setMultiModelMessageStyle(value))}
style={{ width: 135 }}> style={{ width: 135 }}>
<Select.Option value="fold">{t('message.message.multi_model_style.fold')}</Select.Option> <Select.Option value="fold">{t('message.message.multi_model_style.fold')}</Select.Option>
<Select.Option value="horizontal">{t('message.message.multi_model_style.horizontal')}</Select.Option>
<Select.Option value="vertical">{t('message.message.multi_model_style.vertical')}</Select.Option> <Select.Option value="vertical">{t('message.message.multi_model_style.vertical')}</Select.Option>
<Select.Option value="horizontal">{t('message.message.multi_model_style.horizontal')}</Select.Option>
</Select> </Select>
</SettingRow> </SettingRow>
<SettingDivider /> <SettingDivider />