From 8ea73e14c9088418da813a42f6390cb0916570be Mon Sep 17 00:00:00 2001 From: kangfenmao Date: Fri, 1 Nov 2024 17:43:21 +0800 Subject: [PATCH] style(message): user message use black color --- .../src/pages/home/Messages/Message.tsx | 25 ++++++++--- .../pages/home/Messages/MessageContent.tsx | 2 + .../pages/home/Messages/MessageMenubar.tsx | 12 ++--- .../src/pages/home/Messages/MessageTokens.tsx | 8 +++- src/renderer/src/utils/index.ts | 8 ++-- src/renderer/src/utils/style.ts | 45 +++++++++++++++++++ 6 files changed, 83 insertions(+), 17 deletions(-) create mode 100644 src/renderer/src/utils/style.ts diff --git a/src/renderer/src/pages/home/Messages/Message.tsx b/src/renderer/src/pages/home/Messages/Message.tsx index 322b0302..b1a063f4 100644 --- a/src/renderer/src/pages/home/Messages/Message.tsx +++ b/src/renderer/src/pages/home/Messages/Message.tsx @@ -7,7 +7,7 @@ import { fetchChatCompletion } from '@renderer/services/ApiService' import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService' import { estimateMessageUsage } from '@renderer/services/TokenService' import { Message, Topic } from '@renderer/types' -import { runAsyncFunction } from '@renderer/utils' +import { classNames, runAsyncFunction } from '@renderer/utils' import { Divider } from 'antd' import { Dispatch, FC, memo, SetStateAction, useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' @@ -133,11 +133,13 @@ const MessageItem: FC = ({ return ( + style={{ alignItems: isAssistantMessage ? 'start' : 'end' }}> = (props) => { {message.role === 'user' && ( - + )} - + {!copied && } {copied && } {canRegenerate && ( - + )} {isAssistantMessage && ( - + @@ -127,14 +127,14 @@ const MessageMenubar: FC = (props) => { icon={} onConfirm={() => onDeleteMessage?.(message)}> - + {!isUserMessage && ( - + diff --git a/src/renderer/src/pages/home/Messages/MessageTokens.tsx b/src/renderer/src/pages/home/Messages/MessageTokens.tsx index ae63793e..2f265cd2 100644 --- a/src/renderer/src/pages/home/Messages/MessageTokens.tsx +++ b/src/renderer/src/pages/home/Messages/MessageTokens.tsx @@ -15,7 +15,11 @@ const MessgeTokens: React.FC<{ message: Message; isLastMessage: boolean }> = ({ } if (message.role === 'user') { - return Tokens: {message?.usage?.total_tokens} + return ( + + Tokens: {message?.usage?.total_tokens} + + ) } if (isLastMessage && generating) { @@ -24,7 +28,7 @@ const MessgeTokens: React.FC<{ message: Message; isLastMessage: boolean }> = ({ if (message.role === 'assistant') { return ( - + Tokens: {message?.usage?.total_tokens} | ↑{message?.usage?.prompt_tokens} | ↓{message?.usage?.completion_tokens} ) diff --git a/src/renderer/src/utils/index.ts b/src/renderer/src/utils/index.ts index 5c8931a2..9916ab26 100644 --- a/src/renderer/src/utils/index.ts +++ b/src/renderer/src/utils/index.ts @@ -4,6 +4,8 @@ import html2canvas from 'html2canvas' // @ts-ignore next-line` import { v4 as uuidv4 } from 'uuid' +import { classNames } from './style' + export const runAsyncFunction = async (fn: () => void) => { await fn() } @@ -330,10 +332,6 @@ export function formatFileSize(file: FileType) { return (size / 1024).toFixed(2) + ' KB' } -export function classNames(...classes: Array) { - return classes.filter(Boolean).join(' ') -} - export function sortByEnglishFirst(a: string, b: string) { const isAEnglish = /^[a-zA-Z]/.test(a) const isBEnglish = /^[a-zA-Z]/.test(b) @@ -341,3 +339,5 @@ export function sortByEnglishFirst(a: string, b: string) { if (!isAEnglish && isBEnglish) return 1 return a.localeCompare(b) } + +export { classNames } diff --git a/src/renderer/src/utils/style.ts b/src/renderer/src/utils/style.ts new file mode 100644 index 00000000..66e8e5c9 --- /dev/null +++ b/src/renderer/src/utils/style.ts @@ -0,0 +1,45 @@ +type ClassValue = string | number | boolean | undefined | null | ClassDictionary | ClassArray + +interface ClassDictionary { + [id: string]: any +} + +interface ClassArray extends Array {} + +// Example: +// classNames('foo', 'bar'); // => 'foo bar' +// classNames('foo', { bar: true }); // => 'foo bar' +// classNames({ foo: true, bar: false }); // => 'foo' +// classNames(['foo', 'bar']); // => 'foo bar' +// classNames('foo', null, 'bar'); // => 'foo bar' +// classNames({ message: true, 'message-assistant': true }); // => 'message message-assistant' + +/** + * 生成 class 字符串 + * @param args + * @returns + */ +export function classNames(...args: ClassValue[]): string { + const classes: string[] = [] + + args.forEach((arg) => { + if (!arg) return + + if (typeof arg === 'string' || typeof arg === 'number') { + classes.push(arg.toString()) + } else if (Array.isArray(arg)) { + const inner = classNames(...arg) + if (inner) { + classes.push(inner) + } + } else if (typeof arg === 'object') { + Object.entries(arg).forEach(([key, value]) => { + if (value) { + classes.push(key) + } + }) + } + }) + + return classes.filter(Boolean).join(' ') +}