mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-19 14:41:24 +08:00
refactor: align lucide icons in antd button, use more lucide icons (#8805)
* refactor: align lucide icons in antd button * refactor(AssistantsTab): use lucide icon and typography in add assistant button * refactor: use lucide icons for assistant item dropdown * refactor: use lucide icons in topic item dropdown * refactor: use lucide icon in InfoTooltip, align ApiOptionsSettings expand icon * refactor: use lucide icons in TokenCount * refactor: use brush in assistant item dropdown * test: update snapshot * test: mock tooltip * fix: token count alignment * refactor: update icons in MessageMenubar, bump antd * refactor: use lucide icons in MessageTools, make colors consistent * refactor: use lucide icons in ProviderSetting * test: simplify test with mocks * refactor: use lucide icons in knowledge base dropdown * refactor: export all custom icons, use EditIcon for lucide pen * refactor: use lucide copy for CopyIcon, update tests * refactor: use lucide icons in MessageMenubar * refactor: improve pause and send button style * refactor: export SvgSpinners180Ring as LoadingIcon * refactor: use lucide icons in Agents, use DeleteIcon * refactor: use Pencil as EditIcon * fix: i18n key missing * refactor: use lucide icons in Files * refactor: use lucide icons in KnowledgeBase items * refactor: use lucide icons in assistant settings * refactor: use lucide icons in memory settings, add UserSelector * chore: remove duplicate memory component * refactor: use lucide icons in ProviderList * refactor: use lucide icons in QuickPhraseSettings * refactor: use lucide icons in McpSettings * refactor: use lucide icons in DataSettings * refactor: use lucide icons in DefaultAssistantSettings * refactor: add icon to save * refactor: add lucide-custom * fix: icon position in ModelEditContent * refactor: use ListMinus in ManageModelsList * refactor: improve TokenCount alignment * fix: topic pin/unpin i18n * fix: self review * fix: simplify knowledge base dropdown * fix: remove plus icon color * refactor: add ResetIcon and RefreshIcon
This commit is contained in:
parent
41e8a445ca
commit
0e1df2460e
@ -1,5 +1,5 @@
|
||||
diff --git a/es/dropdown/dropdown.js b/es/dropdown/dropdown.js
|
||||
index 986877a762b9ad0aca596a8552732cd12d2eaabb..1f18aa2ea745e68950e4cee16d4d655f5c835fd5 100644
|
||||
index 2e45574398ff68450022a0078e213cc81fe7454e..58ba7789939b7805a89f92b93d222f8fb1168bdf 100644
|
||||
--- a/es/dropdown/dropdown.js
|
||||
+++ b/es/dropdown/dropdown.js
|
||||
@@ -2,7 +2,7 @@
|
||||
@ -11,7 +11,7 @@ index 986877a762b9ad0aca596a8552732cd12d2eaabb..1f18aa2ea745e68950e4cee16d4d655f
|
||||
import classNames from 'classnames';
|
||||
import RcDropdown from 'rc-dropdown';
|
||||
import useEvent from "rc-util/es/hooks/useEvent";
|
||||
@@ -158,8 +158,10 @@ const Dropdown = props => {
|
||||
@@ -160,8 +160,10 @@ const Dropdown = props => {
|
||||
className: `${prefixCls}-menu-submenu-arrow`
|
||||
}, direction === 'rtl' ? (/*#__PURE__*/React.createElement(LeftOutlined, {
|
||||
className: `${prefixCls}-menu-submenu-arrow-icon`
|
||||
@ -24,22 +24,8 @@ index 986877a762b9ad0aca596a8552732cd12d2eaabb..1f18aa2ea745e68950e4cee16d4d655f
|
||||
}))),
|
||||
mode: "vertical",
|
||||
selectable: false,
|
||||
diff --git a/es/dropdown/style/index.js b/es/dropdown/style/index.js
|
||||
index 768c01783002c6901c85a73061ff6b3e776a60ce..39b1b95a56cdc9fb586a193c3adad5141f5cf213 100644
|
||||
--- a/es/dropdown/style/index.js
|
||||
+++ b/es/dropdown/style/index.js
|
||||
@@ -240,7 +240,8 @@ const genBaseStyle = token => {
|
||||
marginInlineEnd: '0 !important',
|
||||
color: token.colorTextDescription,
|
||||
fontSize: fontSizeIcon,
|
||||
- fontStyle: 'normal'
|
||||
+ fontStyle: 'normal',
|
||||
+ marginTop: 3,
|
||||
}
|
||||
}
|
||||
}),
|
||||
diff --git a/es/select/useIcons.js b/es/select/useIcons.js
|
||||
index 959115be936ef8901548af2658c5dcfdc5852723..c812edd52123eb0faf4638b1154fcfa1b05b513b 100644
|
||||
index 572aaaa0899f429cbf8a7181f2eeada545f76dcb..4e175c8d7713dd6422f8bcdc74ee671a835de6ce 100644
|
||||
--- a/es/select/useIcons.js
|
||||
+++ b/es/select/useIcons.js
|
||||
@@ -4,10 +4,10 @@ import * as React from 'react';
|
||||
@ -51,10 +37,10 @@ index 959115be936ef8901548af2658c5dcfdc5852723..c812edd52123eb0faf4638b1154fcfa1
|
||||
import SearchOutlined from "@ant-design/icons/es/icons/SearchOutlined";
|
||||
import { devUseWarning } from '../_util/warning';
|
||||
+import { ChevronDown } from 'lucide-react';
|
||||
export default function useIcons(_ref) {
|
||||
let {
|
||||
suffixIcon,
|
||||
@@ -56,8 +56,10 @@ export default function useIcons(_ref) {
|
||||
export default function useIcons({
|
||||
suffixIcon,
|
||||
clearIcon,
|
||||
@@ -54,8 +54,10 @@ export default function useIcons({
|
||||
className: iconCls
|
||||
}));
|
||||
}
|
||||
@ -162,7 +162,7 @@
|
||||
"@viz-js/lang-dot": "^1.0.5",
|
||||
"@viz-js/viz": "^3.14.0",
|
||||
"@xyflow/react": "^12.4.4",
|
||||
"antd": "patch:antd@npm%3A5.24.7#~/.yarn/patches/antd-npm-5.24.7-356a553ae5.patch",
|
||||
"antd": "patch:antd@npm%3A5.26.7#~/.yarn/patches/antd-npm-5.26.7-029c5c381a.patch",
|
||||
"archiver": "^7.0.1",
|
||||
"async-mutex": "^0.5.0",
|
||||
"axios": "^1.7.3",
|
||||
|
||||
@ -12,6 +12,13 @@
|
||||
outline: none;
|
||||
}
|
||||
|
||||
// Align lucide icon in Button
|
||||
.ant-btn .ant-btn-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ant-tabs-tabpane:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
@ -84,6 +91,14 @@
|
||||
max-height: 50vh;
|
||||
overflow-y: auto;
|
||||
border: 0.5px solid var(--color-border);
|
||||
|
||||
// Align lucide icon in dropdown menu item extra
|
||||
.ant-dropdown-menu-submenu-expand-icon,
|
||||
.ant-dropdown-menu-item-extra {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
.ant-dropdown-arrow + .ant-dropdown-menu {
|
||||
border: none;
|
||||
@ -96,6 +111,10 @@
|
||||
background-color: var(--ant-color-bg-elevated);
|
||||
overflow: hidden;
|
||||
border-radius: var(--ant-border-radius-lg);
|
||||
|
||||
.ant-dropdown-menu-submenu-title {
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-popover {
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
--color-border: #ffffff19;
|
||||
--color-border-soft: #ffffff10;
|
||||
--color-border-mute: #ffffff05;
|
||||
--color-error: #f44336;
|
||||
--color-error: #ff4d50;
|
||||
--color-link: #338cff;
|
||||
--color-code-background: #323232;
|
||||
--color-hover: rgba(40, 40, 40, 1);
|
||||
@ -73,8 +73,8 @@
|
||||
|
||||
--list-item-border-radius: 10px;
|
||||
|
||||
--color-status-success: #52c41a;
|
||||
--color-status-error: #ff4d4f;
|
||||
--color-status-success: green;
|
||||
--color-status-error: var(--color-error);
|
||||
--color-status-warning: #faad14;
|
||||
}
|
||||
|
||||
@ -112,7 +112,7 @@
|
||||
--color-border: #00000019;
|
||||
--color-border-soft: #00000010;
|
||||
--color-border-mute: #00000005;
|
||||
--color-error: #f44336;
|
||||
--color-error: #ff4d50;
|
||||
--color-link: #1677ff;
|
||||
--color-code-background: #e3e3e3;
|
||||
--color-hover: var(--color-white-mute);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { usePreviewToolHandlers, usePreviewTools } from '@renderer/components/CodeToolbar'
|
||||
import SvgSpinners180Ring from '@renderer/components/Icons/SvgSpinners180Ring'
|
||||
import { LoadingIcon } from '@renderer/components/Icons'
|
||||
import { AsyncInitializer } from '@renderer/utils/asyncInitializer'
|
||||
import { Flex, Spin } from 'antd'
|
||||
import { debounce } from 'lodash'
|
||||
@ -86,7 +86,7 @@ const GraphvizPreview: React.FC<BasicPreviewProps> = ({ children, setTools }) =>
|
||||
}, [children, debouncedRender])
|
||||
|
||||
return (
|
||||
<Spin spinning={isLoading} indicator={<SvgSpinners180Ring color="var(--color-text-2)" />}>
|
||||
<Spin spinning={isLoading} indicator={<LoadingIcon color="var(--color-text-2)" />}>
|
||||
<Flex vertical style={{ minHeight: isLoading ? '2rem' : 'auto' }}>
|
||||
{error && <PreviewError>{error}</PreviewError>}
|
||||
<StyledGraphviz ref={graphvizRef} className="graphviz special-preview" />
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { nanoid } from '@reduxjs/toolkit'
|
||||
import { usePreviewToolHandlers, usePreviewTools } from '@renderer/components/CodeToolbar'
|
||||
import SvgSpinners180Ring from '@renderer/components/Icons/SvgSpinners180Ring'
|
||||
import { LoadingIcon } from '@renderer/components/Icons'
|
||||
import { useMermaid } from '@renderer/hooks/useMermaid'
|
||||
import { Flex, Spin } from 'antd'
|
||||
import { debounce } from 'lodash'
|
||||
@ -139,7 +139,7 @@ const MermaidPreview: React.FC<BasicPreviewProps> = ({ children, setTools }) =>
|
||||
const isLoading = isLoadingMermaid || isRendering
|
||||
|
||||
return (
|
||||
<Spin spinning={isLoading} indicator={<SvgSpinners180Ring color="var(--color-text-2)" />}>
|
||||
<Spin spinning={isLoading} indicator={<LoadingIcon color="var(--color-text-2)" />}>
|
||||
<Flex vertical style={{ minHeight: isLoading ? '2rem' : 'auto' }}>
|
||||
{(mermaidError || error) && <PreviewError>{mermaidError || error}</PreviewError>}
|
||||
<StyledMermaid ref={mermaidRef} className="mermaid special-preview" />
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { LoadingOutlined } from '@ant-design/icons'
|
||||
import { loggerService } from '@logger'
|
||||
import CodeEditor from '@renderer/components/CodeEditor'
|
||||
import { CodeTool, CodeToolbar, TOOL_SPECS, useCodeTool } from '@renderer/components/CodeToolbar'
|
||||
import { LoadingIcon } from '@renderer/components/Icons'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { pyodideService } from '@renderer/services/PyodideService'
|
||||
import { extractTitle } from '@renderer/utils/formats'
|
||||
@ -173,7 +173,7 @@ export const CodeBlockView: React.FC<Props> = memo(({ children, language, onSave
|
||||
|
||||
registerTool({
|
||||
...TOOL_SPECS.run,
|
||||
icon: isRunning ? <LoadingOutlined /> : <CirclePlay className="icon" />,
|
||||
icon: isRunning ? <LoadingIcon /> : <CirclePlay className="icon" />,
|
||||
tooltip: t('code_block.run'),
|
||||
onClick: () => !isRunning && handleRunScript()
|
||||
})
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
import { FC } from 'react'
|
||||
import { Copy } from 'lucide-react'
|
||||
|
||||
const CopyIcon: FC<React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>> = (props) => {
|
||||
return <i {...props} className={`iconfont icon-copy ${props.className}`} />
|
||||
}
|
||||
const CopyIcon = (props: React.ComponentProps<typeof Copy>) => <Copy size="1rem" {...props} />
|
||||
|
||||
export default CopyIcon
|
||||
|
||||
5
src/renderer/src/components/Icons/DeleteIcon.tsx
Normal file
5
src/renderer/src/components/Icons/DeleteIcon.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
import { Trash } from 'lucide-react'
|
||||
|
||||
const DeleteIcon = (props: React.ComponentProps<typeof Trash>) => <Trash size="1rem" {...props} />
|
||||
|
||||
export default DeleteIcon
|
||||
5
src/renderer/src/components/Icons/EditIcon.tsx
Normal file
5
src/renderer/src/components/Icons/EditIcon.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
import { Pencil } from 'lucide-react'
|
||||
|
||||
const EditIcon = (props: React.ComponentProps<typeof Pencil>) => <Pencil size="1rem" {...props} />
|
||||
|
||||
export default EditIcon
|
||||
5
src/renderer/src/components/Icons/RefreshIcon.tsx
Normal file
5
src/renderer/src/components/Icons/RefreshIcon.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
import { RefreshCw } from 'lucide-react'
|
||||
|
||||
const RefreshIcon = (props: React.ComponentProps<typeof RefreshCw>) => <RefreshCw size="1rem" {...props} />
|
||||
|
||||
export default RefreshIcon
|
||||
5
src/renderer/src/components/Icons/ResetIcon.tsx
Normal file
5
src/renderer/src/components/Icons/ResetIcon.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
import { RotateCcw } from 'lucide-react'
|
||||
|
||||
const ResetIcon = (props: React.ComponentProps<typeof RotateCcw>) => <RotateCcw size="1rem" {...props} />
|
||||
|
||||
export default ResetIcon
|
||||
@ -1,6 +1,7 @@
|
||||
import { SVGProps } from 'react'
|
||||
|
||||
export function SvgSpinners180Ring(props: SVGProps<SVGSVGElement>) {
|
||||
export function SvgSpinners180Ring(props: SVGProps<SVGSVGElement> & { size?: number | string }) {
|
||||
const { size = '1em', ...svgProps } = props
|
||||
// 避免与全局样式冲突
|
||||
const animationClassName = 'svg-spinner-anim-180-ring'
|
||||
|
||||
@ -25,11 +26,11 @@ export function SvgSpinners180Ring(props: SVGProps<SVGSVGElement>) {
|
||||
</style>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox="0 0 24 24"
|
||||
{...props}
|
||||
className={`${animationClassName} ${props.className || ''}`.trim()}>
|
||||
{...svgProps}
|
||||
className={`${animationClassName} ${svgProps.className || ''}`.trim()}>
|
||||
{/* Icon from SVG Spinners by Utkarsh Verma - https://github.com/n3r4zzurr0/svg-spinners/blob/main/LICENSE */}
|
||||
<path
|
||||
fill="currentColor"
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
import { render } from '@testing-library/react'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import CopyIcon from '../CopyIcon'
|
||||
|
||||
describe('CopyIcon', () => {
|
||||
it('should match snapshot with props and className', () => {
|
||||
const onClick = vi.fn()
|
||||
const { container } = render(
|
||||
<CopyIcon className="custom-class" onClick={onClick} title="Copy to clipboard" data-testid="copy-icon" />
|
||||
)
|
||||
|
||||
expect(container.firstChild).toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
@ -1,9 +0,0 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`CopyIcon > should match snapshot with props and className 1`] = `
|
||||
<i
|
||||
class="iconfont icon-copy custom-class"
|
||||
data-testid="copy-icon"
|
||||
title="Copy to clipboard"
|
||||
/>
|
||||
`;
|
||||
19
src/renderer/src/components/Icons/index.ts
Normal file
19
src/renderer/src/components/Icons/index.ts
Normal file
@ -0,0 +1,19 @@
|
||||
export { default as CopyIcon } from './CopyIcon'
|
||||
export { default as DeleteIcon } from './DeleteIcon'
|
||||
export * from './DownloadIcons'
|
||||
export { default as EditIcon } from './EditIcon'
|
||||
export { default as FallbackFavicon } from './FallbackFavicon'
|
||||
export { default as MinAppIcon } from './MinAppIcon'
|
||||
export * from './NutstoreIcons'
|
||||
export { default as OcrIcon } from './OcrIcon'
|
||||
export { default as ReasoningIcon } from './ReasoningIcon'
|
||||
export { default as RefreshIcon } from './RefreshIcon'
|
||||
export { default as ResetIcon } from './ResetIcon'
|
||||
export * from './SVGIcon'
|
||||
export { default as LoadingIcon } from './SvgSpinners180Ring'
|
||||
export { default as ToolIcon } from './ToolIcon'
|
||||
export { default as ToolsCallingIcon } from './ToolsCallingIcon'
|
||||
export { default as UnWrapIcon } from './UnWrapIcon'
|
||||
export { default as VisionIcon } from './VisionIcon'
|
||||
export { default as WebSearchIcon } from './WebSearchIcon'
|
||||
export { default as WrapIcon } from './WrapIcon'
|
||||
@ -1,17 +1,18 @@
|
||||
import { InfoCircleOutlined } from '@ant-design/icons'
|
||||
import { Tooltip, TooltipProps } from 'antd'
|
||||
import { Info } from 'lucide-react'
|
||||
|
||||
type InheritedTooltipProps = Omit<TooltipProps, 'children'>
|
||||
|
||||
interface InfoTooltipProps extends InheritedTooltipProps {
|
||||
iconColor?: string
|
||||
iconSize?: string | number
|
||||
iconStyle?: React.CSSProperties
|
||||
}
|
||||
|
||||
const InfoTooltip = ({ iconColor = 'var(--color-text-3)', iconStyle, ...rest }: InfoTooltipProps) => {
|
||||
const InfoTooltip = ({ iconColor = 'var(--color-text-3)', iconSize = 14, iconStyle, ...rest }: InfoTooltipProps) => {
|
||||
return (
|
||||
<Tooltip {...rest}>
|
||||
<InfoCircleOutlined style={{ color: iconColor, ...iconStyle }} role="img" aria-label="Information" />
|
||||
<Info size={iconSize} color={iconColor} style={{ ...iconStyle }} role="img" aria-label="Information" />
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { loggerService } from '@logger'
|
||||
import AiProvider from '@renderer/aiCore'
|
||||
import { RefreshIcon } from '@renderer/components/Icons'
|
||||
import { useProvider } from '@renderer/hooks/useProvider'
|
||||
import { Model } from '@renderer/types'
|
||||
import { getErrorMessage } from '@renderer/utils'
|
||||
import { Button, InputNumber, Space, Tooltip } from 'antd'
|
||||
import { RefreshCw } from 'lucide-react'
|
||||
import { memo, useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@ -77,7 +77,7 @@ const InputEmbeddingDimension = ({
|
||||
<Button
|
||||
role="button"
|
||||
aria-label="Get embedding dimension"
|
||||
icon={<RefreshCw size={16} />}
|
||||
icon={<RefreshIcon size={16} />}
|
||||
loading={loading}
|
||||
disabled={disabled}
|
||||
onClick={handleFetchDimension}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { loggerService } from '@logger'
|
||||
import SvgSpinners180Ring from '@renderer/components/Icons/SvgSpinners180Ring'
|
||||
import { LoadingIcon } from '@renderer/components/Icons'
|
||||
import NewApiAddModelPopup from '@renderer/components/ModelList/NewApiAddModelPopup'
|
||||
import NewApiBatchAddModelPopup from '@renderer/components/ModelList/NewApiBatchAddModelPopup'
|
||||
import { TopView } from '@renderer/components/TopView'
|
||||
@ -22,7 +22,7 @@ import { Button, Empty, Flex, Modal, Spin, Tabs, Tooltip } from 'antd'
|
||||
import Input from 'antd/es/input/Input'
|
||||
import { groupBy, isEmpty, uniqBy } from 'lodash'
|
||||
import { debounce } from 'lodash'
|
||||
import { Eraser, ListPlus, RefreshCcw, Search } from 'lucide-react'
|
||||
import { ListMinus, ListPlus, RefreshCcw, Search } from 'lucide-react'
|
||||
import { useCallback, useEffect, useMemo, useOptimistic, useRef, useState, useTransition } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -251,7 +251,7 @@ const PopupContainer: React.FC<Props> = ({ providerId, resolve }) => {
|
||||
mouseLeaveDelay={0}>
|
||||
<Button
|
||||
type="default"
|
||||
icon={isAllFilteredInProvider ? <Eraser size={18} /> : <ListPlus size={18} />}
|
||||
icon={isAllFilteredInProvider ? <ListMinus size={18} /> : <ListPlus size={18} />}
|
||||
size="large"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
@ -331,7 +331,7 @@ const PopupContainer: React.FC<Props> = ({ providerId, resolve }) => {
|
||||
</SearchContainer>
|
||||
<Spin
|
||||
spinning={isLoading}
|
||||
indicator={<SvgSpinners180Ring color="var(--color-text-2)" style={{ opacity: loadingModels ? 1 : 0 }} />}>
|
||||
indicator={<LoadingIcon color="var(--color-text-2)" style={{ opacity: loadingModels ? 1 : 0 }} />}>
|
||||
<ListContainer>
|
||||
{loadingModels || isEmpty(list) ? (
|
||||
<Empty
|
||||
|
||||
@ -13,7 +13,7 @@ import { Model, ModelCapability, ModelType, Provider } from '@renderer/types'
|
||||
import { getDefaultGroupName, getDifference, getUnion, uniqueObjectArray } from '@renderer/utils'
|
||||
import { Button, Checkbox, Divider, Flex, Form, Input, InputNumber, message, Modal, Select, Switch } from 'antd'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { ChevronDown, ChevronUp } from 'lucide-react'
|
||||
import { ChevronDown, ChevronUp, SaveIcon } from 'lucide-react'
|
||||
import { FC, useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -167,8 +167,9 @@ const ModelEditContent: FC<ModelEditContentProps> = ({ provider, model, onUpdate
|
||||
const val = form.getFieldValue('name')
|
||||
navigator.clipboard.writeText((val.id || model.id) as string)
|
||||
message.success(t('message.copied'))
|
||||
}}>
|
||||
<CopyIcon /> {t('chat.topics.copy.title')}
|
||||
}}
|
||||
icon={<CopyIcon size={16} />}>
|
||||
{t('chat.topics.copy.title')}
|
||||
</Button>
|
||||
</Flex>
|
||||
</Form.Item>
|
||||
@ -210,7 +211,7 @@ const ModelEditContent: FC<ModelEditContentProps> = ({ provider, model, onUpdate
|
||||
style={{ color: 'var(--color-text-3)' }}>
|
||||
{t('settings.moresetting.label')}
|
||||
</Button>
|
||||
<Button type="primary" htmlType="submit" size="middle">
|
||||
<Button type="primary" htmlType="submit" icon={<SaveIcon size={16} />}>
|
||||
{t('common.save')}
|
||||
</Button>
|
||||
</Flex>
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import CollapsibleSearchBar from '@renderer/components/CollapsibleSearchBar'
|
||||
import CustomTag from '@renderer/components/CustomTag'
|
||||
import { StreamlineGoodHealthAndWellBeing } from '@renderer/components/Icons/SVGIcon'
|
||||
import SvgSpinners180Ring from '@renderer/components/Icons/SvgSpinners180Ring'
|
||||
import { LoadingIcon, StreamlineGoodHealthAndWellBeing } from '@renderer/components/Icons'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import AddModelPopup from '@renderer/components/ModelList/AddModelPopup'
|
||||
import EditModelPopup from '@renderer/components/ModelList/EditModelPopup'
|
||||
@ -160,7 +159,7 @@ const ModelList: React.FC<ModelListProps> = ({ providerId }) => {
|
||||
</HStack>
|
||||
</HStack>
|
||||
</SettingSubtitle>
|
||||
<Spin spinning={isLoading} indicator={<SvgSpinners180Ring color="var(--color-text-2)" />}>
|
||||
<Spin spinning={isLoading} indicator={<LoadingIcon color="var(--color-text-2)" />}>
|
||||
{displayedModelGroups && !isEmpty(displayedModelGroups) ? (
|
||||
<Flex gap={12} vertical>
|
||||
{Object.keys(displayedModelGroups).map((group, i) => (
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { type HealthResult, HealthStatusIndicator } from '@renderer/components/HealthStatusIndicator'
|
||||
import { EditIcon } from '@renderer/components/Icons'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import ModelIdWithTags from '@renderer/components/ModelIdWithTags'
|
||||
import { getModelLogo } from '@renderer/config/models'
|
||||
@ -6,7 +7,7 @@ import { Model } from '@renderer/types'
|
||||
import { ModelWithStatus } from '@renderer/types/healthCheck'
|
||||
import { maskApiKey } from '@renderer/utils/api'
|
||||
import { Avatar, Button, Tooltip } from 'antd'
|
||||
import { Minus, Pen } from 'lucide-react'
|
||||
import { Minus } from 'lucide-react'
|
||||
import React, { memo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -51,7 +52,7 @@ const ModelListItem: React.FC<ModelListItemProps> = ({ ref, model, modelStatus,
|
||||
<HealthStatusIndicator results={healthResults} loading={isChecking} showLatency />
|
||||
<HStack alignItems="center" gap={0}>
|
||||
<Tooltip title={t('models.edit')} mouseLeaveDelay={0}>
|
||||
<Button type="text" onClick={() => onEdit(model)} disabled={disabled} icon={<Pen size={14} />} />
|
||||
<Button type="text" onClick={() => onEdit(model)} disabled={disabled} icon={<EditIcon size={14} />} />
|
||||
</Tooltip>
|
||||
<Tooltip title={t('settings.models.manage.remove_model')} mouseLeaveDelay={0}>
|
||||
<Button type="text" onClick={() => onRemove(model)} disabled={disabled} icon={<Minus size={14} />} />
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { type HealthResult, HealthStatusIndicator } from '@renderer/components/HealthStatusIndicator'
|
||||
import { EditIcon } from '@renderer/components/Icons'
|
||||
import { StreamlineGoodHealthAndWellBeing } from '@renderer/components/Icons/SVGIcon'
|
||||
import { ApiKeyWithStatus } from '@renderer/types/healthCheck'
|
||||
import { maskApiKey } from '@renderer/utils/api'
|
||||
import { Button, Flex, Input, InputRef, List, Popconfirm, Tooltip, Typography } from 'antd'
|
||||
import { Check, Minus, Pen, X } from 'lucide-react'
|
||||
import { Check, Minus, X } from 'lucide-react'
|
||||
import { FC, memo, useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -148,7 +149,7 @@ const ApiKeyItem: FC<ApiKeyItemProps> = ({
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip title={t('common.edit')} mouseLeaveDelay={0}>
|
||||
<Button type="text" icon={<Pen size={16} />} onClick={handleEdit} disabled={disabled} />
|
||||
<Button type="text" icon={<EditIcon size={16} />} onClick={handleEdit} disabled={disabled} />
|
||||
</Tooltip>
|
||||
<Popconfirm
|
||||
title={t('common.delete_confirm')}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { PlusOutlined } from '@ant-design/icons'
|
||||
import { DeleteIcon } from '@renderer/components/Icons'
|
||||
import { StreamlineGoodHealthAndWellBeing } from '@renderer/components/Icons/SVGIcon'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import { usePreprocessProvider } from '@renderer/hooks/usePreprocess'
|
||||
@ -8,7 +8,7 @@ import { SettingHelpText } from '@renderer/pages/settings'
|
||||
import { isProviderSupportAuth } from '@renderer/services/ProviderService'
|
||||
import { ApiKeyWithStatus, HealthStatus } from '@renderer/types/healthCheck'
|
||||
import { Button, Card, Flex, List, Popconfirm, Space, Tooltip, Typography } from 'antd'
|
||||
import { Trash } from 'lucide-react'
|
||||
import { Plus } from 'lucide-react'
|
||||
import { FC, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -140,7 +140,12 @@ export const ApiKeyList: FC<ApiKeyListProps> = ({ provider, updateProvider, prov
|
||||
cancelText={t('common.cancel')}
|
||||
okButtonProps={{ danger: true }}>
|
||||
<Tooltip title={t('settings.provider.remove_invalid_keys')} placement="top" mouseLeaveDelay={0}>
|
||||
<Button type="text" icon={<Trash size={16} />} disabled={isChecking || !!pendingNewKey} danger />
|
||||
<Button
|
||||
type="text"
|
||||
icon={<DeleteIcon size={16} className="lucide-custom" />}
|
||||
disabled={isChecking || !!pendingNewKey}
|
||||
danger
|
||||
/>
|
||||
</Tooltip>
|
||||
</Popconfirm>
|
||||
|
||||
@ -161,7 +166,7 @@ export const ApiKeyList: FC<ApiKeyListProps> = ({ provider, updateProvider, prov
|
||||
key="add"
|
||||
type="primary"
|
||||
onClick={handleAddNew}
|
||||
icon={<PlusOutlined />}
|
||||
icon={<Plus size={16} />}
|
||||
autoFocus={shouldAutoFocus()}
|
||||
disabled={isChecking || !!pendingNewKey}>
|
||||
{t('common.add')}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { CopyIcon, DeleteIcon } from '@renderer/components/Icons'
|
||||
import { useChatContext } from '@renderer/hooks/useChatContext'
|
||||
import { Topic } from '@renderer/types'
|
||||
import { Button, Tooltip } from 'antd'
|
||||
import { Copy, Save, Trash, X } from 'lucide-react'
|
||||
import { Save, X } from 'lucide-react'
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -49,7 +50,7 @@ const MultiSelectActionPopup: FC<Props> = ({ topic }) => {
|
||||
shape="circle"
|
||||
color="default"
|
||||
variant="text"
|
||||
icon={<Copy size={16} />}
|
||||
icon={<CopyIcon size={16} />}
|
||||
disabled={isActionDisabled}
|
||||
onClick={() => handleAction('copy')}
|
||||
/>
|
||||
@ -60,7 +61,7 @@ const MultiSelectActionPopup: FC<Props> = ({ topic }) => {
|
||||
color="danger"
|
||||
variant="text"
|
||||
danger
|
||||
icon={<Trash size={16} />}
|
||||
icon={<DeleteIcon size={16} className="lucide-custom" />}
|
||||
onClick={() => handleAction('delete')}
|
||||
/>
|
||||
</Tooltip>
|
||||
|
||||
@ -1,9 +1,25 @@
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import InfoTooltip from '../InfoTooltip'
|
||||
|
||||
vi.mock('antd', () => ({
|
||||
Tooltip: ({ children, title }: { children: React.ReactNode; title: string }) => (
|
||||
<div>
|
||||
{children}
|
||||
{title && <div>{title}</div>}
|
||||
</div>
|
||||
)
|
||||
}))
|
||||
|
||||
vi.mock('lucide-react', () => ({
|
||||
Info: ({ ref, ...props }) => (
|
||||
<div {...props} ref={ref} role="img" aria-label="Information">
|
||||
Info
|
||||
</div>
|
||||
)
|
||||
}))
|
||||
|
||||
describe('InfoTooltip', () => {
|
||||
it('should match snapshot', () => {
|
||||
const { container } = render(
|
||||
@ -12,13 +28,11 @@ describe('InfoTooltip', () => {
|
||||
expect(container.firstChild).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('should show tooltip on hover', async () => {
|
||||
it('should pass title prop to the underlying Tooltip component', () => {
|
||||
const tooltipText = 'This is helpful information'
|
||||
render(<InfoTooltip title={tooltipText} />)
|
||||
|
||||
const icon = screen.getByRole('img', { name: 'Information' })
|
||||
await userEvent.hover(icon)
|
||||
|
||||
expect(await screen.findByText(tooltipText)).toBeInTheDocument()
|
||||
expect(screen.getByRole('img', { name: 'Information' })).toBeInTheDocument()
|
||||
expect(screen.getByText(tooltipText)).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,27 +1,71 @@
|
||||
import { render, screen, waitFor } from '@testing-library/react'
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import React from 'react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import InputEmbeddingDimension from '../InputEmbeddingDimension'
|
||||
|
||||
const mocks = vi.hoisted(() => {
|
||||
return {
|
||||
aiCore: {
|
||||
getEmbeddingDimensions: vi.fn()
|
||||
},
|
||||
i18n: {
|
||||
t: (k: string) => {
|
||||
const translations: Record<string, string> = {
|
||||
'knowledge.embedding_model_required': '请选择嵌入模型',
|
||||
'knowledge.provider_not_found': '找不到提供商',
|
||||
'message.error.get_embedding_dimensions': '获取嵌入维度失败',
|
||||
'knowledge.dimensions_size_placeholder': '请输入维度大小',
|
||||
'knowledge.dimensions_auto_set': '自动设置维度'
|
||||
}
|
||||
return translations[k] || k
|
||||
const mocks = vi.hoisted(() => ({
|
||||
aiCore: {
|
||||
getEmbeddingDimensions: vi.fn()
|
||||
},
|
||||
i18n: {
|
||||
t: (k: string) => {
|
||||
const translations: Record<string, string> = {
|
||||
'knowledge.embedding_model_required': '请选择嵌入模型',
|
||||
'knowledge.provider_not_found': '找不到提供商',
|
||||
'message.error.get_embedding_dimensions': '获取嵌入维度失败',
|
||||
'knowledge.dimensions_size_placeholder': '请输入维度大小',
|
||||
'knowledge.dimensions_auto_set': '自动设置维度'
|
||||
}
|
||||
return translations[k] || k
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
// Mock antd components to prevent flaky snapshot tests
|
||||
vi.mock('antd', () => {
|
||||
const MockSpaceCompact: React.FC<React.PropsWithChildren<{ style?: React.CSSProperties }>> = ({
|
||||
children,
|
||||
style
|
||||
}) => (
|
||||
<div data-testid="space-compact" style={style}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
||||
const MockInputNumber = ({ ref, value, onChange, placeholder, disabled, style }: any) => (
|
||||
<input
|
||||
ref={ref}
|
||||
type="number"
|
||||
data-testid="input-number"
|
||||
placeholder={placeholder}
|
||||
value={value ?? ''}
|
||||
onChange={(e) => onChange(e.target.valueAsNumber)}
|
||||
disabled={disabled}
|
||||
style={style}
|
||||
/>
|
||||
)
|
||||
|
||||
const MockButton: React.FC<any> = ({ children, onClick, loading, disabled, icon, ...rest }) => (
|
||||
<button type="button" onClick={onClick} disabled={disabled || loading} {...rest}>
|
||||
{loading ? 'Loading...' : icon}
|
||||
{children}
|
||||
</button>
|
||||
)
|
||||
|
||||
const MockTooltip: React.FC<React.PropsWithChildren<{ title: string }>> = ({ children, title }) => (
|
||||
<div data-testid="tooltip" data-title={title}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
||||
return {
|
||||
Button: MockButton,
|
||||
InputNumber: MockInputNumber,
|
||||
Space: { Compact: MockSpaceCompact },
|
||||
Tooltip: MockTooltip
|
||||
}
|
||||
})
|
||||
|
||||
// Mock dependencies
|
||||
@ -46,20 +90,10 @@ vi.mock('react-i18next', () => ({
|
||||
}
|
||||
}))
|
||||
|
||||
// Mock logger
|
||||
vi.mock('@logger', () => ({
|
||||
loggerService: {
|
||||
withContext: () => ({
|
||||
warn: vi.fn(),
|
||||
error: vi.fn()
|
||||
})
|
||||
}
|
||||
}))
|
||||
|
||||
vi.mock('lucide-react', () => ({
|
||||
RefreshCw: (props: React.SVGProps<SVGSVGElement>) => (
|
||||
vi.mock('@renderer/components/Icons', () => ({
|
||||
RefreshIcon: (props: React.SVGProps<SVGSVGElement>) => (
|
||||
<svg data-testid="refresh-icon" aria-label="refresh" role="img" {...props}>
|
||||
RefreshCw
|
||||
RefreshIcon
|
||||
</svg>
|
||||
)
|
||||
}))
|
||||
@ -119,13 +153,11 @@ describe('InputEmbeddingDimension', () => {
|
||||
describe('functionality', () => {
|
||||
it('should call onChange when input value changes', async () => {
|
||||
const handleChange = vi.fn()
|
||||
const user = userEvent.setup()
|
||||
|
||||
render(<InputEmbeddingDimension model={mockModel} onChange={handleChange} />)
|
||||
|
||||
const input = screen.getByPlaceholderText('请输入维度大小')
|
||||
await user.clear(input)
|
||||
await user.type(input, '2048')
|
||||
fireEvent.change(input, { target: { value: '2048' } })
|
||||
|
||||
expect(handleChange).toHaveBeenCalledWith(2048)
|
||||
})
|
||||
@ -182,7 +214,6 @@ describe('InputEmbeddingDimension', () => {
|
||||
|
||||
it('should handle null value correctly', async () => {
|
||||
const handleChange = vi.fn()
|
||||
const user = userEvent.setup()
|
||||
|
||||
render(<InputEmbeddingDimension model={mockModel} value={null} onChange={handleChange} />)
|
||||
|
||||
@ -190,7 +221,7 @@ describe('InputEmbeddingDimension', () => {
|
||||
expect(input.value).toBe('')
|
||||
|
||||
// Should allow typing new value
|
||||
await user.type(input, '1024')
|
||||
fireEvent.change(input, { target: { value: '1024' } })
|
||||
expect(handleChange).toHaveBeenCalledWith(1024)
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,28 +1,18 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`InfoTooltip > should match snapshot 1`] = `
|
||||
<span
|
||||
aria-describedby="test-id"
|
||||
aria-label="Information"
|
||||
class="anticon anticon-info-circle"
|
||||
role="img"
|
||||
style="color: rgb(24, 144, 255); font-size: 16px;"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="info-circle"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
<div>
|
||||
<div
|
||||
aria-label="Information"
|
||||
color="#1890ff"
|
||||
role="img"
|
||||
size="14"
|
||||
style="font-size: 16px;"
|
||||
>
|
||||
<path
|
||||
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"
|
||||
/>
|
||||
<path
|
||||
d="M464 336a48 48 0 1096 0 48 48 0 10-96 0zm72 112h-48c-4.4 0-8 3.6-8 8v272c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V456c0-4.4-3.6-8-8-8z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
Info
|
||||
</div>
|
||||
<div>
|
||||
Test tooltip
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@ -2,95 +2,24 @@
|
||||
|
||||
exports[`InputEmbeddingDimension > basic rendering > should match snapshot with all props 1`] = `
|
||||
<div
|
||||
class="ant-space-compact css-dev-only-do-not-override-1261szd"
|
||||
data-testid="space-compact"
|
||||
style="width: 100%;"
|
||||
>
|
||||
<div
|
||||
class="ant-input-number css-dev-only-do-not-override-1261szd ant-input-number-outlined ant-input-number-compact-item ant-input-number-compact-first-item"
|
||||
<input
|
||||
data-testid="input-number"
|
||||
placeholder="请输入维度大小"
|
||||
style="flex: 1;"
|
||||
type="number"
|
||||
value="1536"
|
||||
/>
|
||||
<div
|
||||
data-testid="tooltip"
|
||||
data-title="自动设置维度"
|
||||
>
|
||||
<div
|
||||
class="ant-input-number-handler-wrap"
|
||||
>
|
||||
<span
|
||||
aria-disabled="false"
|
||||
aria-label="Increase Value"
|
||||
class="ant-input-number-handler ant-input-number-handler-up"
|
||||
role="button"
|
||||
unselectable="on"
|
||||
>
|
||||
<span
|
||||
aria-label="up"
|
||||
class="anticon anticon-up ant-input-number-handler-up-inner"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="up"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M890.5 755.3L537.9 269.2c-12.8-17.6-39-17.6-51.7 0L133.5 755.3A8 8 0 00140 768h75c5.1 0 9.9-2.5 12.9-6.6L512 369.8l284.1 391.6c3 4.1 7.8 6.6 12.9 6.6h75c6.5 0 10.3-7.4 6.5-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
aria-disabled="false"
|
||||
aria-label="Decrease Value"
|
||||
class="ant-input-number-handler ant-input-number-handler-down"
|
||||
role="button"
|
||||
unselectable="on"
|
||||
>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down ant-input-number-handler-down-inner"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-input-number-input-wrap"
|
||||
>
|
||||
<input
|
||||
aria-valuemin="1"
|
||||
aria-valuenow="1536"
|
||||
autocomplete="off"
|
||||
class="ant-input-number-input"
|
||||
placeholder="请输入维度大小"
|
||||
role="spinbutton"
|
||||
step="1"
|
||||
value="1536"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
aria-describedby="test-id"
|
||||
aria-label="Get embedding dimension"
|
||||
class="ant-btn css-dev-only-do-not-override-1261szd ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-icon-only ant-btn-compact-item ant-btn-compact-last-item"
|
||||
role="button"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-btn-icon"
|
||||
<button
|
||||
aria-label="Get embedding dimension"
|
||||
role="button"
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-label="refresh"
|
||||
@ -98,124 +27,37 @@ exports[`InputEmbeddingDimension > basic rendering > should match snapshot with
|
||||
role="img"
|
||||
size="16"
|
||||
>
|
||||
RefreshCw
|
||||
RefreshIcon
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`InputEmbeddingDimension > basic rendering > should match snapshot with loading state 1`] = `
|
||||
<div
|
||||
class="ant-space-compact css-dev-only-do-not-override-1261szd"
|
||||
data-testid="space-compact"
|
||||
style="width: 100%;"
|
||||
>
|
||||
<div
|
||||
class="ant-input-number css-dev-only-do-not-override-1261szd ant-input-number-outlined ant-input-number-compact-item ant-input-number-compact-first-item"
|
||||
<input
|
||||
data-testid="input-number"
|
||||
placeholder="请输入维度大小"
|
||||
style="flex: 1;"
|
||||
type="number"
|
||||
value=""
|
||||
/>
|
||||
<div
|
||||
data-testid="tooltip"
|
||||
data-title="自动设置维度"
|
||||
>
|
||||
<div
|
||||
class="ant-input-number-handler-wrap"
|
||||
<button
|
||||
aria-label="Get embedding dimension"
|
||||
disabled=""
|
||||
role="button"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-disabled="false"
|
||||
aria-label="Increase Value"
|
||||
class="ant-input-number-handler ant-input-number-handler-up"
|
||||
role="button"
|
||||
unselectable="on"
|
||||
>
|
||||
<span
|
||||
aria-label="up"
|
||||
class="anticon anticon-up ant-input-number-handler-up-inner"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="up"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M890.5 755.3L537.9 269.2c-12.8-17.6-39-17.6-51.7 0L133.5 755.3A8 8 0 00140 768h75c5.1 0 9.9-2.5 12.9-6.6L512 369.8l284.1 391.6c3 4.1 7.8 6.6 12.9 6.6h75c6.5 0 10.3-7.4 6.5-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
aria-disabled="false"
|
||||
aria-label="Decrease Value"
|
||||
class="ant-input-number-handler ant-input-number-handler-down"
|
||||
role="button"
|
||||
unselectable="on"
|
||||
>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down ant-input-number-handler-down-inner"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-input-number-input-wrap"
|
||||
>
|
||||
<input
|
||||
aria-valuemin="1"
|
||||
autocomplete="off"
|
||||
class="ant-input-number-input"
|
||||
placeholder="请输入维度大小"
|
||||
role="spinbutton"
|
||||
step="1"
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
Loading...
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
aria-describedby="test-id"
|
||||
aria-label="Get embedding dimension"
|
||||
class="ant-btn css-dev-only-do-not-override-1261szd ant-btn-default ant-btn-color-default ant-btn-variant-outlined ant-btn-icon-only ant-btn-loading ant-btn-compact-item ant-btn-compact-last-item"
|
||||
role="button"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="ant-btn-icon ant-btn-loading-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="loading"
|
||||
class="anticon anticon-loading anticon-spin"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="loading"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="0 0 1024 1024"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@ -596,7 +596,7 @@
|
||||
"list": "Topic List",
|
||||
"move_to": "Move to",
|
||||
"new": "New Topic",
|
||||
"pinned": "Pinned Topics",
|
||||
"pin": "Pin Topic",
|
||||
"prompt": {
|
||||
"edit": {
|
||||
"title": "Edit Topic Prompts"
|
||||
@ -605,7 +605,7 @@
|
||||
"tips": "Topic Prompts: Additional supplementary prompts provided for the current topic"
|
||||
},
|
||||
"title": "Topics",
|
||||
"unpinned": "Unpinned Topics"
|
||||
"unpin": "Unpin Topic"
|
||||
},
|
||||
"translate": "Translate"
|
||||
},
|
||||
@ -1552,6 +1552,7 @@
|
||||
"mode": {
|
||||
"edit": "Edit",
|
||||
"generate": "Draw",
|
||||
"merge": "Merge",
|
||||
"remix": "Remix",
|
||||
"upscale": "Upscale"
|
||||
},
|
||||
|
||||
@ -596,7 +596,7 @@
|
||||
"list": "トピックリスト",
|
||||
"move_to": "移動先",
|
||||
"new": "新しいトピック",
|
||||
"pinned": "トピックを固定",
|
||||
"pin": "トピックを固定",
|
||||
"prompt": {
|
||||
"edit": {
|
||||
"title": "トピック提示語を編集する"
|
||||
@ -605,7 +605,7 @@
|
||||
"tips": "トピック提示語:現在のトピックに対して追加の補足提示語を提供"
|
||||
},
|
||||
"title": "トピック",
|
||||
"unpinned": "固定解除"
|
||||
"unpin": "固定解除"
|
||||
},
|
||||
"translate": "翻訳"
|
||||
},
|
||||
@ -1552,6 +1552,7 @@
|
||||
"mode": {
|
||||
"edit": "部分編集",
|
||||
"generate": "画像生成",
|
||||
"merge": "マージ",
|
||||
"remix": "混合",
|
||||
"upscale": "拡大"
|
||||
},
|
||||
|
||||
@ -596,7 +596,7 @@
|
||||
"list": "Список топиков",
|
||||
"move_to": "Переместить в",
|
||||
"new": "Новый топик",
|
||||
"pinned": "Закрепленные темы",
|
||||
"pin": "Закрепленные темы",
|
||||
"prompt": {
|
||||
"edit": {
|
||||
"title": "Редактировать подсказки темы"
|
||||
@ -605,7 +605,7 @@
|
||||
"tips": "Тематические подсказки: Дополнительные подсказки, предоставленные для текущей темы"
|
||||
},
|
||||
"title": "Топики",
|
||||
"unpinned": "Открепленные темы"
|
||||
"unpin": "Открепленные темы"
|
||||
},
|
||||
"translate": "Перевести"
|
||||
},
|
||||
@ -1552,6 +1552,7 @@
|
||||
"mode": {
|
||||
"edit": "Редактирование",
|
||||
"generate": "Рисование",
|
||||
"merge": "Слияние",
|
||||
"remix": "Смешивание",
|
||||
"upscale": "Увеличение"
|
||||
},
|
||||
|
||||
@ -596,7 +596,7 @@
|
||||
"list": "话题列表",
|
||||
"move_to": "移动到",
|
||||
"new": "开始新对话",
|
||||
"pinned": "固定话题",
|
||||
"pin": "固定话题",
|
||||
"prompt": {
|
||||
"edit": {
|
||||
"title": "编辑话题提示词"
|
||||
@ -605,7 +605,7 @@
|
||||
"tips": "话题提示词:针对当前话题提供额外的补充提示词"
|
||||
},
|
||||
"title": "话题",
|
||||
"unpinned": "取消固定"
|
||||
"unpin": "取消固定"
|
||||
},
|
||||
"translate": "翻译"
|
||||
},
|
||||
@ -1552,6 +1552,7 @@
|
||||
"mode": {
|
||||
"edit": "编辑",
|
||||
"generate": "绘图",
|
||||
"merge": "合并",
|
||||
"remix": "混合",
|
||||
"upscale": "高清增强"
|
||||
},
|
||||
|
||||
@ -596,7 +596,7 @@
|
||||
"list": "話題列表",
|
||||
"move_to": "移動到",
|
||||
"new": "開始新對話",
|
||||
"pinned": "固定話題",
|
||||
"pin": "固定話題",
|
||||
"prompt": {
|
||||
"edit": {
|
||||
"title": "編輯話題提示詞"
|
||||
@ -605,7 +605,7 @@
|
||||
"tips": "話題提示詞:針對目前話題提供額外的補充提示詞"
|
||||
},
|
||||
"title": "話題",
|
||||
"unpinned": "取消固定"
|
||||
"unpin": "取消固定"
|
||||
},
|
||||
"translate": "翻譯"
|
||||
},
|
||||
@ -1552,6 +1552,7 @@
|
||||
"mode": {
|
||||
"edit": "編輯",
|
||||
"generate": "繪圖",
|
||||
"merge": "合併",
|
||||
"remix": "混合",
|
||||
"upscale": "放大"
|
||||
},
|
||||
|
||||
@ -596,7 +596,7 @@
|
||||
"list": "Λίστα θεμάτων",
|
||||
"move_to": "Μετακίνηση στο",
|
||||
"new": "Ξεκινήστε νέα συζήτηση",
|
||||
"pinned": "Σταθερά θέματα",
|
||||
"pin": "Σταθερά θέματα",
|
||||
"prompt": {
|
||||
"edit": {
|
||||
"title": "Επεξεργασία προσδοκώμενων όριων"
|
||||
@ -605,7 +605,7 @@
|
||||
"tips": "Προσδοκώμενα όρια: προσθέτει επιπλέον επιστημονικές προσθήκες για το παρόν θέμα"
|
||||
},
|
||||
"title": "Θέματα",
|
||||
"unpinned": "Αποστέλλω"
|
||||
"unpin": "Ξεκαρφίτσωμα"
|
||||
},
|
||||
"translate": "Μετάφραση"
|
||||
},
|
||||
|
||||
@ -596,7 +596,7 @@
|
||||
"list": "Lista de temas",
|
||||
"move_to": "Mover a",
|
||||
"new": "Iniciar nueva conversación",
|
||||
"pinned": "Fijar tema",
|
||||
"pin": "Fijar tema",
|
||||
"prompt": {
|
||||
"edit": {
|
||||
"title": "Editar palabras clave del tema"
|
||||
@ -605,7 +605,7 @@
|
||||
"tips": "Palabras clave del tema: proporcionar indicaciones adicionales para el tema actual"
|
||||
},
|
||||
"title": "Tema",
|
||||
"unpinned": "Quitar fijación"
|
||||
"unpin": "Quitar fijación"
|
||||
},
|
||||
"translate": "Traducir"
|
||||
},
|
||||
|
||||
@ -596,7 +596,7 @@
|
||||
"list": "Liste des sujets",
|
||||
"move_to": "Déplacer vers",
|
||||
"new": "Commencer une nouvelle conversation",
|
||||
"pinned": "Fixer le sujet",
|
||||
"pin": "Fixer le sujet",
|
||||
"prompt": {
|
||||
"edit": {
|
||||
"title": "Modifier les indicateurs de sujet"
|
||||
@ -605,7 +605,7 @@
|
||||
"tips": "Indicateurs de sujet : fournir des indications supplémentaires pour le sujet actuel"
|
||||
},
|
||||
"title": "Sujet",
|
||||
"unpinned": "Annuler le fixage"
|
||||
"unpin": "Annuler le fixage"
|
||||
},
|
||||
"translate": "Traduire"
|
||||
},
|
||||
|
||||
@ -596,7 +596,7 @@
|
||||
"list": "Lista de tópicos",
|
||||
"move_to": "Mover para",
|
||||
"new": "Começar nova conversa",
|
||||
"pinned": "Fixar tópico",
|
||||
"pin": "Fixar tópico",
|
||||
"prompt": {
|
||||
"edit": {
|
||||
"title": "Editar prompt do tópico"
|
||||
@ -605,7 +605,7 @@
|
||||
"tips": "Prompt do tópico: fornecer prompts adicionais para o tópico atual"
|
||||
},
|
||||
"title": "Tópicos",
|
||||
"unpinned": "Desfixar"
|
||||
"unpin": "Desfixar"
|
||||
},
|
||||
"translate": "Traduzir"
|
||||
},
|
||||
|
||||
@ -1,12 +1,5 @@
|
||||
import {
|
||||
DeleteOutlined,
|
||||
EditOutlined,
|
||||
EllipsisOutlined,
|
||||
ExportOutlined,
|
||||
PlusOutlined,
|
||||
SortAscendingOutlined
|
||||
} from '@ant-design/icons'
|
||||
import CustomTag from '@renderer/components/CustomTag'
|
||||
import { DeleteIcon, EditIcon } from '@renderer/components/Icons'
|
||||
import { useAgents } from '@renderer/hooks/useAgents'
|
||||
import AssistantSettingsPopup from '@renderer/pages/settings/AssistantSettings'
|
||||
import { createAssistantFromAgent } from '@renderer/services/AssistantService'
|
||||
@ -14,6 +7,7 @@ import type { Agent } from '@renderer/types'
|
||||
import { getLeadingEmoji } from '@renderer/utils'
|
||||
import { Button, Dropdown } from 'antd'
|
||||
import { t } from 'i18next'
|
||||
import { ArrowDownAZ, Ellipsis, PlusIcon, SquareArrowOutUpRight } from 'lucide-react'
|
||||
import { type FC, memo, useCallback, useEffect, useRef, useState } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
@ -66,7 +60,7 @@ const AgentCard: FC<Props> = ({ agent, onClick, activegroup, getLocalizedGroupNa
|
||||
{
|
||||
key: 'edit',
|
||||
label: t('agents.edit.title'),
|
||||
icon: <EditOutlined />,
|
||||
icon: <EditIcon size={14} />,
|
||||
onClick: (e: any) => {
|
||||
e.domEvent.stopPropagation()
|
||||
AssistantSettingsPopup.show({ assistant: agent })
|
||||
@ -75,7 +69,7 @@ const AgentCard: FC<Props> = ({ agent, onClick, activegroup, getLocalizedGroupNa
|
||||
{
|
||||
key: 'create',
|
||||
label: t('agents.add.button'),
|
||||
icon: <PlusOutlined />,
|
||||
icon: <PlusIcon size={14} />,
|
||||
onClick: (e: any) => {
|
||||
e.domEvent.stopPropagation()
|
||||
createAssistantFromAgent(agent)
|
||||
@ -84,7 +78,7 @@ const AgentCard: FC<Props> = ({ agent, onClick, activegroup, getLocalizedGroupNa
|
||||
{
|
||||
key: 'sort',
|
||||
label: t('agents.sorting.title'),
|
||||
icon: <SortAscendingOutlined />,
|
||||
icon: <ArrowDownAZ size={14} />,
|
||||
onClick: (e: any) => {
|
||||
e.domEvent.stopPropagation()
|
||||
ManageAgentsPopup.show()
|
||||
@ -93,7 +87,7 @@ const AgentCard: FC<Props> = ({ agent, onClick, activegroup, getLocalizedGroupNa
|
||||
{
|
||||
key: 'export',
|
||||
label: t('agents.export.agent'),
|
||||
icon: <ExportOutlined />,
|
||||
icon: <SquareArrowOutUpRight size={14} />,
|
||||
onClick: (e: any) => {
|
||||
e.domEvent.stopPropagation()
|
||||
exportAgent()
|
||||
@ -102,7 +96,7 @@ const AgentCard: FC<Props> = ({ agent, onClick, activegroup, getLocalizedGroupNa
|
||||
{
|
||||
key: 'delete',
|
||||
label: t('common.delete'),
|
||||
icon: <DeleteOutlined />,
|
||||
icon: <DeleteIcon size={14} className="lucide-custom" />,
|
||||
danger: true,
|
||||
onClick: (e: any) => {
|
||||
e.domEvent.stopPropagation()
|
||||
@ -173,7 +167,7 @@ const AgentCard: FC<Props> = ({ agent, onClick, activegroup, getLocalizedGroupNa
|
||||
color="default"
|
||||
variant="filled"
|
||||
shape="circle"
|
||||
icon={<EllipsisOutlined />}
|
||||
icon={<Ellipsis size={14} color="var(--color-text-3)" />}
|
||||
/>
|
||||
</Dropdown>
|
||||
</AgentCardHeaderInfoAction>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { DeleteOutlined, ExclamationCircleOutlined } from '@ant-design/icons'
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons'
|
||||
import { DeleteIcon } from '@renderer/components/Icons'
|
||||
import { DynamicVirtualList } from '@renderer/components/VirtualList'
|
||||
import { handleDelete } from '@renderer/services/FileAction'
|
||||
import FileManager from '@renderer/services/FileManager'
|
||||
@ -68,7 +69,7 @@ const FileList: React.FC<FileItemProps> = ({ id, list, files }) => {
|
||||
icon: <ExclamationCircleOutlined style={{ color: 'red' }} />
|
||||
})
|
||||
}}>
|
||||
<DeleteOutlined />
|
||||
<DeleteIcon size={14} className="lucide-custom" />
|
||||
</DeleteButton>
|
||||
</ImageWrapper>
|
||||
</Col>
|
||||
|
||||
@ -1,11 +1,6 @@
|
||||
import {
|
||||
DeleteOutlined,
|
||||
EditOutlined,
|
||||
ExclamationCircleOutlined,
|
||||
SortAscendingOutlined,
|
||||
SortDescendingOutlined
|
||||
} from '@ant-design/icons'
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons'
|
||||
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
||||
import { DeleteIcon, EditIcon } from '@renderer/components/Icons'
|
||||
import ListItem from '@renderer/components/ListItem'
|
||||
import db from '@renderer/databases'
|
||||
import { getFileFieldLabel } from '@renderer/i18n/label'
|
||||
@ -16,7 +11,14 @@ import { formatFileSize } from '@renderer/utils'
|
||||
import { Button, Empty, Flex, Popconfirm } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { useLiveQuery } from 'dexie-react-hooks'
|
||||
import { File as FileIcon, FileImage, FileText, FileType as FileTypeIcon } from 'lucide-react'
|
||||
import {
|
||||
ArrowDownNarrowWide,
|
||||
ArrowUpWideNarrow,
|
||||
File as FileIcon,
|
||||
FileImage,
|
||||
FileText,
|
||||
FileType as FileTypeIcon
|
||||
} from 'lucide-react'
|
||||
import { FC, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -54,7 +56,7 @@ const FilesPage: FC = () => {
|
||||
created_at_unix: dayjs(file.created_at).unix(),
|
||||
actions: (
|
||||
<Flex align="center" gap={0} style={{ opacity: 0.7 }}>
|
||||
<Button type="text" icon={<EditOutlined />} onClick={() => handleRename(file.id)} />
|
||||
<Button type="text" icon={<EditIcon size={14} />} onClick={() => handleRename(file.id)} />
|
||||
<Popconfirm
|
||||
title={t('files.delete.title')}
|
||||
description={t('files.delete.content')}
|
||||
@ -62,7 +64,7 @@ const FilesPage: FC = () => {
|
||||
cancelText={t('common.cancel')}
|
||||
onConfirm={() => handleDelete(file.id, t)}
|
||||
icon={<ExclamationCircleOutlined style={{ color: 'red' }} />}>
|
||||
<Button type="text" danger icon={<DeleteOutlined />} />
|
||||
<Button type="text" danger icon={<DeleteIcon size={14} className="lucide-custom" />} />
|
||||
</Popconfirm>
|
||||
</Flex>
|
||||
)
|
||||
@ -108,7 +110,8 @@ const FilesPage: FC = () => {
|
||||
}
|
||||
}}>
|
||||
{getFileFieldLabel(field)}
|
||||
{sortField === field && (sortOrder === 'desc' ? <SortDescendingOutlined /> : <SortAscendingOutlined />)}
|
||||
{sortField === field &&
|
||||
(sortOrder === 'desc' ? <ArrowUpWideNarrow size={12} /> : <ArrowDownNarrowWide size={12} />)}
|
||||
</SortButton>
|
||||
))}
|
||||
</SortContainer>
|
||||
|
||||
@ -940,8 +940,8 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
<TranslateButton text={text} onTranslated={onTranslated} isLoading={isTranslating} />
|
||||
{loading && (
|
||||
<Tooltip placement="top" title={t('chat.input.pause')} mouseLeaveDelay={0} arrow>
|
||||
<ToolbarButton type="text" onClick={onPause} style={{ marginRight: -2, marginTop: 1 }}>
|
||||
<CirclePause style={{ color: 'var(--color-error)', fontSize: 20 }} />
|
||||
<ToolbarButton type="text" onClick={onPause} style={{ marginRight: -2 }}>
|
||||
<CirclePause size={20} color="var(--color-error)" />
|
||||
</ToolbarButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
@ -15,6 +15,7 @@ const SendMessageButton: FC<Props> = ({ disabled, sendMessage }) => {
|
||||
color: disabled ? 'var(--color-text-3)' : 'var(--color-primary)',
|
||||
fontSize: 22,
|
||||
transition: 'all 0.2s',
|
||||
marginTop: 1,
|
||||
marginRight: 2
|
||||
}}
|
||||
/>
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { ArrowUpOutlined, MenuOutlined } from '@ant-design/icons'
|
||||
import { HStack, VStack } from '@renderer/components/Layout'
|
||||
import MaxContextCount from '@renderer/components/MaxContextCount'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { Divider, Popover } from 'antd'
|
||||
import { ArrowUp, MenuIcon } from 'lucide-react'
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -49,13 +49,14 @@ const TokenCount: FC<Props> = ({ estimateTokenCount, inputTokenCount, contextCou
|
||||
<Popover content={PopoverContent} arrow={false}>
|
||||
<HStack>
|
||||
<HStack style={{ alignItems: 'center' }}>
|
||||
<MenuOutlined /> {contextCount.current}
|
||||
<MenuIcon size={12} className="icon" />
|
||||
{contextCount.current}
|
||||
<SlashSeparatorSpan>/</SlashSeparatorSpan>
|
||||
<MaxContextCount maxContext={contextCount.max} />
|
||||
</HStack>
|
||||
<Divider type="vertical" style={{ marginTop: 0, marginLeft: 5, marginRight: 5 }} />
|
||||
<Divider type="vertical" style={{ marginTop: 3, marginLeft: 5, marginRight: 3 }} />
|
||||
<HStack style={{ alignItems: 'center' }}>
|
||||
<ArrowUpOutlined />
|
||||
<ArrowUp size={12} className="icon" />
|
||||
{inputTokenCount}
|
||||
<SlashSeparatorSpan>/</SlashSeparatorSpan>
|
||||
{estimateTokenCount}
|
||||
@ -77,8 +78,7 @@ const Container = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
.anticon {
|
||||
font-size: 10px;
|
||||
.icon {
|
||||
margin-right: 3px;
|
||||
}
|
||||
@media (max-width: 800px) {
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { CopyIcon } from '@renderer/components/Icons'
|
||||
import store from '@renderer/store'
|
||||
import { messageBlocksSelectors } from '@renderer/store/messageBlock'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Check, Copy } from 'lucide-react'
|
||||
import { Check } from 'lucide-react'
|
||||
import React, { memo, useCallback, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -40,11 +41,7 @@ const Table: React.FC<Props> = ({ children, node, blockId }) => {
|
||||
<ToolbarWrapper className="table-toolbar">
|
||||
<Tooltip title={t('common.copy')} mouseEnterDelay={0.8}>
|
||||
<ToolButton role="button" aria-label={t('common.copy')} onClick={handleCopyTable}>
|
||||
{copied ? (
|
||||
<Check size={14} style={{ color: 'var(--color-primary)' }} data-testid="check-icon" />
|
||||
) : (
|
||||
<Copy size={14} data-testid="copy-icon" />
|
||||
)}
|
||||
{copied ? <Check size={14} color="var(--color-primary)" /> : <CopyIcon size={14} />}
|
||||
</ToolButton>
|
||||
</Tooltip>
|
||||
</ToolbarWrapper>
|
||||
|
||||
@ -28,6 +28,14 @@ vi.mock('@renderer/store/messageBlock', () => ({
|
||||
messageBlocksSelectors: mocks.messageBlocksSelectors
|
||||
}))
|
||||
|
||||
vi.mock('@renderer/components/Icons', () => ({
|
||||
CopyIcon: ({ size }: { size: number }) => <div data-testid="copy-icon" style={{ width: size, height: size }} />
|
||||
}))
|
||||
|
||||
vi.mock('lucide-react', () => ({
|
||||
Check: ({ size }: { size: number }) => <div data-testid="check-icon" style={{ width: size, height: size }} />
|
||||
}))
|
||||
|
||||
vi.mock('react-i18next', () => ({
|
||||
useTranslation: () => ({
|
||||
t: (key: string) => key
|
||||
|
||||
@ -71,32 +71,10 @@ exports[`Table > rendering > should match snapshot 1`] = `
|
||||
class="c2"
|
||||
role="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="lucide lucide-copy"
|
||||
<div
|
||||
data-testid="copy-icon"
|
||||
fill="none"
|
||||
height="14"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
width="14"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect
|
||||
height="14"
|
||||
rx="2"
|
||||
ry="2"
|
||||
width="14"
|
||||
x="8"
|
||||
y="8"
|
||||
/>
|
||||
<path
|
||||
d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"
|
||||
/>
|
||||
</svg>
|
||||
style="width: 14px; height: 14px;"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import SvgSpinners180Ring from '@renderer/components/Icons/SvgSpinners180Ring'
|
||||
import { LoadingIcon } from '@renderer/components/Icons'
|
||||
import { MessageBlockStatus, MessageBlockType, type PlaceholderMessageBlock } from '@renderer/types/newMessage'
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
@ -10,7 +10,7 @@ const PlaceholderBlock: React.FC<PlaceholderBlockProps> = ({ block }) => {
|
||||
if (block.status === MessageBlockStatus.PROCESSING && block.type === MessageBlockType.UNKNOWN) {
|
||||
return (
|
||||
<MessageContentLoading>
|
||||
<SvgSpinners180Ring />
|
||||
<LoadingIcon />
|
||||
</MessageContentLoading>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { CheckOutlined, EditOutlined, QuestionCircleOutlined, SyncOutlined } from '@ant-design/icons'
|
||||
import { InfoCircleOutlined } from '@ant-design/icons'
|
||||
import { CopyIcon, DeleteIcon, EditIcon, RefreshIcon } from '@renderer/components/Icons'
|
||||
import ObsidianExportPopup from '@renderer/components/Popups/ObsidianExportPopup'
|
||||
import SaveToKnowledgePopup from '@renderer/components/Popups/SaveToKnowledgePopup'
|
||||
import SelectModelPopup from '@renderer/components/Popups/SelectModelPopup'
|
||||
@ -32,20 +33,7 @@ import { removeTrailingDoubleSpaces } from '@renderer/utils/markdown'
|
||||
import { findMainTextBlocks, findTranslationBlocks, getMainTextContent } from '@renderer/utils/messageUtils/find'
|
||||
import { Dropdown, Popconfirm, Tooltip } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import {
|
||||
AtSign,
|
||||
Copy,
|
||||
FilePenLine,
|
||||
Languages,
|
||||
ListChecks,
|
||||
Menu,
|
||||
RefreshCw,
|
||||
Save,
|
||||
Share,
|
||||
Split,
|
||||
ThumbsUp,
|
||||
Trash
|
||||
} from 'lucide-react'
|
||||
import { AtSign, Check, FilePenLine, Languages, ListChecks, Menu, Save, Split, ThumbsUp, Upload } from 'lucide-react'
|
||||
import { FC, memo, useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useSelector } from 'react-redux'
|
||||
@ -223,7 +211,7 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
{
|
||||
label: t('chat.save.label'),
|
||||
key: 'save',
|
||||
icon: <Save size={15} color="var(--color-icon)" style={{ marginTop: 3 }} />,
|
||||
icon: <Save size={15} />,
|
||||
children: [
|
||||
{
|
||||
label: t('chat.save.file.title'),
|
||||
@ -245,7 +233,7 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
{
|
||||
label: t('chat.topics.export.title'),
|
||||
key: 'export',
|
||||
icon: <Share size={15} color="var(--color-icon)" style={{ marginTop: 3 }} />,
|
||||
icon: <Upload size={15} />,
|
||||
children: [
|
||||
exportMenuOptions.plain_text && {
|
||||
label: t('chat.topics.copy.plain_text'),
|
||||
@ -440,28 +428,28 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
className="message-action-button"
|
||||
onClick={() => handleResendUserMessage()}
|
||||
$softHoverBg={isBubbleStyle}>
|
||||
<SyncOutlined />
|
||||
<RefreshIcon size={15} />
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
{message.role === 'user' && (
|
||||
<Tooltip title={t('common.edit')} mouseEnterDelay={0.8}>
|
||||
<ActionButton className="message-action-button" onClick={onEdit} $softHoverBg={softHoverBg}>
|
||||
<EditOutlined />
|
||||
<EditIcon size={15} />
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip title={t('common.copy')} mouseEnterDelay={0.8}>
|
||||
<ActionButton className="message-action-button" onClick={onCopy} $softHoverBg={softHoverBg}>
|
||||
{!copied && <Copy size={15} />}
|
||||
{copied && <CheckOutlined style={{ color: 'var(--color-primary)' }} />}
|
||||
{!copied && <CopyIcon size={15} />}
|
||||
{copied && <Check size={15} color="var(--color-primary)" />}
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
{isAssistantMessage && (
|
||||
<Popconfirm
|
||||
title={t('message.regenerate.confirm')}
|
||||
okButtonProps={{ danger: true }}
|
||||
icon={<QuestionCircleOutlined style={{ color: 'red' }} />}
|
||||
icon={<InfoCircleOutlined style={{ color: 'red' }} />}
|
||||
onConfirm={onRegenerate}
|
||||
onOpenChange={(open) => open && setShowRegenerateTooltip(false)}>
|
||||
<Tooltip
|
||||
@ -470,7 +458,7 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
open={showRegenerateTooltip}
|
||||
onOpenChange={setShowRegenerateTooltip}>
|
||||
<ActionButton className="message-action-button" $softHoverBg={softHoverBg}>
|
||||
<RefreshCw size={15} />
|
||||
<RefreshIcon size={15} />
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
</Popconfirm>
|
||||
@ -571,7 +559,7 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
<Popconfirm
|
||||
title={t('message.message.delete.content')}
|
||||
okButtonProps={{ danger: true }}
|
||||
icon={<QuestionCircleOutlined style={{ color: 'red' }} />}
|
||||
icon={<InfoCircleOutlined style={{ color: 'red' }} />}
|
||||
onOpenChange={(open) => open && setShowDeleteTooltip(false)}
|
||||
onConfirm={() => deleteMessage(message.id, message.traceId, message.model?.name)}>
|
||||
<ActionButton
|
||||
@ -583,7 +571,7 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
mouseEnterDelay={1}
|
||||
open={showDeleteTooltip}
|
||||
onOpenChange={setShowDeleteTooltip}>
|
||||
<Trash size={15} />
|
||||
<DeleteIcon size={15} />
|
||||
</Tooltip>
|
||||
</ActionButton>
|
||||
</Popconfirm>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { CheckOutlined, CloseOutlined, ExpandOutlined, LoadingOutlined, WarningOutlined } from '@ant-design/icons'
|
||||
import { loggerService } from '@logger'
|
||||
import { CopyIcon, LoadingIcon } from '@renderer/components/Icons'
|
||||
import { useCodeStyle } from '@renderer/context/CodeStyleProvider'
|
||||
import { useMCPServers } from '@renderer/hooks/useMCPServers'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
@ -19,7 +19,18 @@ import {
|
||||
Tooltip
|
||||
} from 'antd'
|
||||
import { message } from 'antd'
|
||||
import { ChevronDown, ChevronRight, CirclePlay, CircleX, PauseCircle, ShieldCheck } from 'lucide-react'
|
||||
import {
|
||||
Check,
|
||||
ChevronDown,
|
||||
ChevronRight,
|
||||
CirclePlay,
|
||||
CircleX,
|
||||
Maximize,
|
||||
PauseCircle,
|
||||
ShieldCheck,
|
||||
TriangleAlert,
|
||||
X
|
||||
} from 'lucide-react'
|
||||
import { FC, memo, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -191,23 +202,23 @@ const MessageTools: FC<Props> = ({ block }) => {
|
||||
switch (status) {
|
||||
case 'pending':
|
||||
label = t('message.tools.pending', 'Awaiting Approval')
|
||||
icon = <LoadingOutlined spin style={{ marginLeft: 6, color: 'var(--status-color-warning)' }} />
|
||||
icon = <LoadingIcon style={{ marginLeft: 6, color: 'var(--status-color-warning)' }} />
|
||||
break
|
||||
case 'invoking':
|
||||
label = t('message.tools.invoking')
|
||||
icon = <LoadingOutlined spin style={{ marginLeft: 6 }} />
|
||||
icon = <LoadingIcon style={{ marginLeft: 6 }} />
|
||||
break
|
||||
case 'cancelled':
|
||||
label = t('message.tools.cancelled')
|
||||
icon = <CloseOutlined style={{ marginLeft: 6 }} />
|
||||
icon = <X size={13} style={{ marginLeft: 6 }} className="lucide-custom" />
|
||||
break
|
||||
case 'done':
|
||||
if (hasError) {
|
||||
label = t('message.tools.error')
|
||||
icon = <WarningOutlined style={{ marginLeft: 6 }} />
|
||||
icon = <TriangleAlert size={13} style={{ marginLeft: 6 }} className="lucide-custom" />
|
||||
} else {
|
||||
label = t('message.tools.completed')
|
||||
icon = <CheckOutlined style={{ marginLeft: 6 }} />
|
||||
icon = <Check size={13} style={{ marginLeft: 6 }} className="lucide-custom" />
|
||||
}
|
||||
break
|
||||
default:
|
||||
@ -262,7 +273,7 @@ const MessageTools: FC<Props> = ({ block }) => {
|
||||
})
|
||||
}}
|
||||
aria-label={t('common.expand')}>
|
||||
<ExpandOutlined />
|
||||
<Maximize size={14} />
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
{!isPending && !isInvoking && (
|
||||
@ -274,8 +285,8 @@ const MessageTools: FC<Props> = ({ block }) => {
|
||||
copyContent(JSON.stringify(result, null, 2), id)
|
||||
}}
|
||||
aria-label={t('common.copy')}>
|
||||
{!copiedMap[id] && <i className="iconfont icon-copy"></i>}
|
||||
{copiedMap[id] && <CheckOutlined style={{ color: 'var(--color-primary)' }} />}
|
||||
{!copiedMap[id] && <CopyIcon size={14} />}
|
||||
{copiedMap[id] && <Check size={14} color="var(--status-color-success)" />}
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
@ -394,7 +405,7 @@ const MessageTools: FC<Props> = ({ block }) => {
|
||||
e.stopPropagation()
|
||||
handleAbortTool()
|
||||
}}>
|
||||
<PauseCircle className="lucide-custom" size={14} />
|
||||
<PauseCircle size={14} className="lucide-custom" />
|
||||
{t('chat.input.pause')}
|
||||
</Button>
|
||||
) : (
|
||||
@ -572,10 +583,10 @@ const ExpandIcon = styled(ChevronRight)<{ $isActive?: boolean }>`
|
||||
`
|
||||
|
||||
const CollapseContainer = styled(Collapse)`
|
||||
--status-color-warning: var(--color-warning, #faad14);
|
||||
--status-color-warning: var(--color-status-warning, #faad14);
|
||||
--status-color-invoking: var(--color-primary);
|
||||
--status-color-error: var(--color-error, #ff4d4f);
|
||||
--status-color-success: var(--color-success, green);
|
||||
--status-color-error: var(--color-status-error, #ff4d4f);
|
||||
--status-color-success: var(--color-primary, green);
|
||||
border-radius: 7px;
|
||||
border: none;
|
||||
background-color: var(--color-background);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { TranslationOutlined } from '@ant-design/icons'
|
||||
import SvgSpinners180Ring from '@renderer/components/Icons/SvgSpinners180Ring'
|
||||
import { LoadingIcon } from '@renderer/components/Icons'
|
||||
import type { TranslationMessageBlock } from '@renderer/types/newMessage'
|
||||
import { Divider } from 'antd'
|
||||
import { FC, Fragment } from 'react'
|
||||
@ -20,7 +20,7 @@ const MessageTranslate: FC<Props> = ({ block }) => {
|
||||
<TranslationOutlined />
|
||||
</Divider>
|
||||
{!block.content || block.content === t('translate.processing') ? (
|
||||
<SvgSpinners180Ring color="var(--color-text-2)" style={{ marginBottom: 15 }} />
|
||||
<LoadingIcon color="var(--color-text-2)" style={{ marginBottom: 15 }} />
|
||||
) : (
|
||||
<Markdown block={block} />
|
||||
)}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { loggerService } from '@logger'
|
||||
import ContextMenu from '@renderer/components/ContextMenu'
|
||||
import SvgSpinners180Ring from '@renderer/components/Icons/SvgSpinners180Ring'
|
||||
import { LoadingIcon } from '@renderer/components/Icons'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import { LOAD_MORE_COUNT } from '@renderer/config/constant'
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
@ -309,7 +309,7 @@ const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic, o
|
||||
))}
|
||||
{isLoadingMore && (
|
||||
<LoaderContainer>
|
||||
<SvgSpinners180Ring color="var(--color-text-2)" />
|
||||
<LoadingIcon color="var(--color-text-2)" />
|
||||
</LoaderContainer>
|
||||
)}
|
||||
</ScrollContainer>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { DownOutlined, PlusOutlined, RightOutlined } from '@ant-design/icons'
|
||||
import { DownOutlined, RightOutlined } from '@ant-design/icons'
|
||||
import { DraggableList } from '@renderer/components/DraggableList'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import { useAgents } from '@renderer/hooks/useAgents'
|
||||
@ -6,8 +6,9 @@ import { useAssistants } from '@renderer/hooks/useAssistant'
|
||||
import { useAssistantsTabSortType } from '@renderer/hooks/useStore'
|
||||
import { useTags } from '@renderer/hooks/useTags'
|
||||
import { Assistant, AssistantsSortType } from '@renderer/types'
|
||||
import { Tooltip } from 'antd'
|
||||
import { FC, useCallback, useRef, useState } from 'react'
|
||||
import { Tooltip, Typography } from 'antd'
|
||||
import { Plus } from 'lucide-react'
|
||||
import { FC, useCallback, useMemo, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
|
||||
@ -69,6 +70,19 @@ const Assistants: FC<AssistantsTabProps> = ({
|
||||
[assistants, t, updateAssistants]
|
||||
)
|
||||
|
||||
const renderAddAssistantButton = useMemo(() => {
|
||||
return (
|
||||
<AssistantAddItem onClick={onCreateAssistant}>
|
||||
<AddItemWrapper>
|
||||
<Plus size={16} style={{ marginRight: 4, flexShrink: 0 }} />
|
||||
<Typography.Text style={{ color: 'inherit' }} ellipsis={{ tooltip: t('chat.add.assistant.title') }}>
|
||||
{t('chat.add.assistant.title')}
|
||||
</Typography.Text>
|
||||
</AddItemWrapper>
|
||||
</AssistantAddItem>
|
||||
)
|
||||
}, [onCreateAssistant, t])
|
||||
|
||||
if (assistantsTabSortType === 'tags') {
|
||||
return (
|
||||
<Container className="assistants-tab" ref={containerRef}>
|
||||
@ -117,12 +131,7 @@ const Assistants: FC<AssistantsTabProps> = ({
|
||||
</TagsContainer>
|
||||
))}
|
||||
</div>
|
||||
<AssistantAddItem onClick={onCreateAssistant}>
|
||||
<AssistantName>
|
||||
<PlusOutlined style={{ color: 'var(--color-text-2)', marginRight: 4 }} />
|
||||
{t('chat.add.assistant.title')}
|
||||
</AssistantName>
|
||||
</AssistantAddItem>
|
||||
{renderAddAssistantButton}
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
@ -149,14 +158,7 @@ const Assistants: FC<AssistantsTabProps> = ({
|
||||
/>
|
||||
)}
|
||||
</DraggableList>
|
||||
{!dragging && (
|
||||
<AssistantAddItem onClick={onCreateAssistant}>
|
||||
<AssistantName>
|
||||
<PlusOutlined style={{ color: 'var(--color-text-2)', marginRight: 4 }} />
|
||||
{t('chat.add.assistant.title')}
|
||||
</AssistantName>
|
||||
</AssistantAddItem>
|
||||
)}
|
||||
{!dragging && renderAddAssistantButton}
|
||||
<div style={{ minHeight: 10 }}></div>
|
||||
</Container>
|
||||
)
|
||||
@ -224,13 +226,13 @@ const GroupTitleDivider = styled.div`
|
||||
border-top: 1px solid var(--color-border);
|
||||
`
|
||||
|
||||
const AssistantName = styled.div`
|
||||
color: var(--color-text);
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
const AddItemWrapper = styled.div`
|
||||
color: var(--color-text-2);
|
||||
font-size: 13px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
`
|
||||
|
||||
export default Assistants
|
||||
|
||||
@ -1,17 +1,5 @@
|
||||
import {
|
||||
ClearOutlined,
|
||||
CloseOutlined,
|
||||
DeleteOutlined,
|
||||
EditOutlined,
|
||||
FolderOutlined,
|
||||
MenuOutlined,
|
||||
PlusOutlined,
|
||||
PushpinOutlined,
|
||||
QuestionCircleOutlined,
|
||||
UploadOutlined
|
||||
} from '@ant-design/icons'
|
||||
import { DraggableVirtualList } from '@renderer/components/DraggableList'
|
||||
import CopyIcon from '@renderer/components/Icons/CopyIcon'
|
||||
import { CopyIcon, DeleteIcon, EditIcon } from '@renderer/components/Icons'
|
||||
import ObsidianExportPopup from '@renderer/components/Popups/ObsidianExportPopup'
|
||||
import PromptPopup from '@renderer/components/Popups/PromptPopup'
|
||||
import { isMac } from '@renderer/config/constant'
|
||||
@ -40,6 +28,19 @@ import { Dropdown, MenuProps, Tooltip } from 'antd'
|
||||
import { ItemType, MenuItemType } from 'antd/es/menu/interface'
|
||||
import dayjs from 'dayjs'
|
||||
import { findIndex } from 'lodash'
|
||||
import {
|
||||
BrushCleaning,
|
||||
FolderOpen,
|
||||
HelpCircle,
|
||||
MenuIcon,
|
||||
PackagePlus,
|
||||
PinIcon,
|
||||
PinOffIcon,
|
||||
PlusIcon,
|
||||
Sparkles,
|
||||
UploadIcon,
|
||||
XIcon
|
||||
} from 'lucide-react'
|
||||
import { FC, useCallback, useDeferredValue, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
@ -177,7 +178,7 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic,
|
||||
{
|
||||
label: t('chat.topics.auto_rename'),
|
||||
key: 'auto-rename',
|
||||
icon: <i className="iconfont icon-business-smart-assistant" style={{ fontSize: '14px' }} />,
|
||||
icon: <Sparkles size={14} />,
|
||||
disabled: isRenaming(topic.id),
|
||||
async onClick() {
|
||||
const messages = await TopicManager.getTopicMessages(topic.id)
|
||||
@ -200,7 +201,7 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic,
|
||||
{
|
||||
label: t('chat.topics.edit.title'),
|
||||
key: 'rename',
|
||||
icon: <EditOutlined />,
|
||||
icon: <EditIcon size={14} />,
|
||||
disabled: isRenaming(topic.id),
|
||||
async onClick() {
|
||||
const name = await PromptPopup.show({
|
||||
@ -217,10 +218,10 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic,
|
||||
{
|
||||
label: t('chat.topics.prompt.label'),
|
||||
key: 'topic-prompt',
|
||||
icon: <i className="iconfont icon-ai-model1" style={{ fontSize: '14px' }} />,
|
||||
icon: <PackagePlus size={14} />,
|
||||
extra: (
|
||||
<Tooltip title={t('chat.topics.prompt.tips')}>
|
||||
<QuestionIcon />
|
||||
<HelpCircle size={14} />
|
||||
</Tooltip>
|
||||
),
|
||||
async onClick() {
|
||||
@ -243,9 +244,9 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic,
|
||||
}
|
||||
},
|
||||
{
|
||||
label: topic.pinned ? t('chat.topics.unpinned') : t('chat.topics.pinned'),
|
||||
label: topic.pinned ? t('chat.topics.unpin') : t('chat.topics.pin'),
|
||||
key: 'pin',
|
||||
icon: <PushpinOutlined />,
|
||||
icon: topic.pinned ? <PinOffIcon size={14} /> : <PinIcon size={14} />,
|
||||
onClick() {
|
||||
onPinTopic(topic)
|
||||
}
|
||||
@ -253,7 +254,7 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic,
|
||||
{
|
||||
label: t('chat.topics.clear.title'),
|
||||
key: 'clear-messages',
|
||||
icon: <ClearOutlined />,
|
||||
icon: <BrushCleaning size={14} />,
|
||||
async onClick() {
|
||||
window.modal.confirm({
|
||||
title: t('chat.input.clear.content'),
|
||||
@ -265,7 +266,7 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic,
|
||||
{
|
||||
label: t('settings.topic.position.label'),
|
||||
key: 'topic-position',
|
||||
icon: <MenuOutlined />,
|
||||
icon: <MenuIcon size={14} />,
|
||||
children: [
|
||||
{
|
||||
label: t('settings.topic.position.left'),
|
||||
@ -282,7 +283,7 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic,
|
||||
{
|
||||
label: t('chat.topics.copy.title'),
|
||||
key: 'copy',
|
||||
icon: <CopyIcon />,
|
||||
icon: <CopyIcon size={14} />,
|
||||
children: [
|
||||
{
|
||||
label: t('chat.topics.copy.image'),
|
||||
@ -304,7 +305,7 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic,
|
||||
{
|
||||
label: t('chat.topics.export.title'),
|
||||
key: 'export',
|
||||
icon: <UploadOutlined />,
|
||||
icon: <UploadIcon size={14} />,
|
||||
children: [
|
||||
exportMenuOptions.image && {
|
||||
label: t('chat.topics.export.image'),
|
||||
@ -375,7 +376,7 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic,
|
||||
menus.push({
|
||||
label: t('chat.topics.move_to'),
|
||||
key: 'move',
|
||||
icon: <FolderOutlined />,
|
||||
icon: <FolderOpen size={14} />,
|
||||
children: assistants
|
||||
.filter((a) => a.id !== assistant.id)
|
||||
.map((a) => ({
|
||||
@ -392,7 +393,7 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic,
|
||||
label: t('common.delete'),
|
||||
danger: true,
|
||||
key: 'delete',
|
||||
icon: <DeleteOutlined />,
|
||||
icon: <DeleteIcon size={14} className="lucide-custom" />,
|
||||
onClick: () => onDeleteTopic(topic)
|
||||
})
|
||||
}
|
||||
@ -446,7 +447,7 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic,
|
||||
itemContainerStyle={{ paddingBottom: '8px' }}
|
||||
header={
|
||||
<AddTopicButton onClick={() => EventEmitter.emit(EVENT_NAMES.ADD_NEW_TOPIC)}>
|
||||
<PlusOutlined />
|
||||
<PlusIcon size={16} />
|
||||
{t('chat.add.topic.title')}
|
||||
</AddTopicButton>
|
||||
}>
|
||||
@ -498,16 +499,16 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic,
|
||||
}
|
||||
}}>
|
||||
{deletingTopicId === topic.id ? (
|
||||
<DeleteOutlined style={{ color: 'var(--color-error)' }} />
|
||||
<DeleteIcon size={14} color="var(--color-error)" />
|
||||
) : (
|
||||
<CloseOutlined />
|
||||
<XIcon size={14} color="var(--color-text-3)" />
|
||||
)}
|
||||
</MenuButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
{topic.pinned && (
|
||||
<MenuButton className="pin">
|
||||
<PushpinOutlined />
|
||||
<PinIcon size={14} color="var(--color-text-3)" />
|
||||
</MenuButton>
|
||||
)}
|
||||
</TopicNameContainer>
|
||||
@ -704,10 +705,5 @@ const MenuButton = styled.div`
|
||||
font-size: 12px;
|
||||
}
|
||||
`
|
||||
const QuestionIcon = styled(QuestionCircleOutlined)`
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
color: var(--color-text-3);
|
||||
`
|
||||
|
||||
export default Topics
|
||||
|
||||
@ -1,17 +1,6 @@
|
||||
import {
|
||||
CheckOutlined,
|
||||
DeleteOutlined,
|
||||
EditOutlined,
|
||||
MinusCircleOutlined,
|
||||
PlusOutlined,
|
||||
SaveOutlined,
|
||||
SmileOutlined,
|
||||
SortAscendingOutlined,
|
||||
SortDescendingOutlined
|
||||
} from '@ant-design/icons'
|
||||
import ModelAvatar from '@renderer/components/Avatar/ModelAvatar'
|
||||
import EmojiIcon from '@renderer/components/EmojiIcon'
|
||||
import CopyIcon from '@renderer/components/Icons/CopyIcon'
|
||||
import { CopyIcon, DeleteIcon, EditIcon } from '@renderer/components/Icons'
|
||||
import PromptPopup from '@renderer/components/Popups/PromptPopup'
|
||||
import { useAssistant, useAssistants } from '@renderer/hooks/useAssistant'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
@ -24,7 +13,19 @@ import { getLeadingEmoji, uuid } from '@renderer/utils'
|
||||
import { hasTopicPendingRequests } from '@renderer/utils/queue'
|
||||
import { Dropdown, MenuProps } from 'antd'
|
||||
import { omit } from 'lodash'
|
||||
import { AlignJustify, Plus, Settings2, Tag, Tags } from 'lucide-react'
|
||||
import {
|
||||
AlignJustify,
|
||||
ArrowDownAZ,
|
||||
ArrowUpAZ,
|
||||
BrushCleaning,
|
||||
Check,
|
||||
Plus,
|
||||
Save,
|
||||
Settings2,
|
||||
Smile,
|
||||
Tag,
|
||||
Tags
|
||||
} from 'lucide-react'
|
||||
import { FC, memo, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -198,7 +199,7 @@ const createTagMenuItems = (
|
||||
const items: MenuProps['items'] = [
|
||||
...allTags.map((tag) => ({
|
||||
label: tag,
|
||||
icon: assistant.tags?.includes(tag) ? <CheckOutlined size={14} /> : <Tag size={12} />,
|
||||
icon: assistant.tags?.includes(tag) ? <Check size={14} /> : <Tag size={14} />,
|
||||
key: `all-tag-${tag}`,
|
||||
onClick: () => handleTagOperation(tag, assistant, assistants, updateAssistants)
|
||||
}))
|
||||
@ -211,7 +212,7 @@ const createTagMenuItems = (
|
||||
items.push({
|
||||
label: t('assistants.tags.add'),
|
||||
key: 'new-tag',
|
||||
icon: <Plus size={16} />,
|
||||
icon: <Plus size={14} />,
|
||||
onClick: async () => {
|
||||
const tagName = await PromptPopup.show({
|
||||
title: t('assistants.tags.add'),
|
||||
@ -228,7 +229,7 @@ const createTagMenuItems = (
|
||||
items.push({
|
||||
label: t('assistants.tags.manage'),
|
||||
key: 'manage-tags',
|
||||
icon: <Settings2 size={16} />,
|
||||
icon: <Settings2 size={14} />,
|
||||
onClick: () => {
|
||||
AssistantTagsPopup.show({ title: t('assistants.tags.manage') })
|
||||
}
|
||||
@ -260,13 +261,13 @@ function getMenuItems({
|
||||
{
|
||||
label: t('assistants.edit.title'),
|
||||
key: 'edit',
|
||||
icon: <EditOutlined />,
|
||||
icon: <EditIcon size={14} />,
|
||||
onClick: () => AssistantSettingsPopup.show({ assistant })
|
||||
},
|
||||
{
|
||||
label: t('assistants.copy.title'),
|
||||
key: 'duplicate',
|
||||
icon: <CopyIcon />,
|
||||
icon: <CopyIcon size={14} />,
|
||||
onClick: async () => {
|
||||
const _assistant = copyAssistant(assistant)
|
||||
if (_assistant) {
|
||||
@ -277,7 +278,7 @@ function getMenuItems({
|
||||
{
|
||||
label: t('assistants.clear.title'),
|
||||
key: 'clear',
|
||||
icon: <MinusCircleOutlined />,
|
||||
icon: <BrushCleaning size={14} />,
|
||||
onClick: () => {
|
||||
window.modal.confirm({
|
||||
title: t('assistants.clear.title'),
|
||||
@ -291,7 +292,7 @@ function getMenuItems({
|
||||
{
|
||||
label: t('assistants.save.title'),
|
||||
key: 'save-to-agent',
|
||||
icon: <SaveOutlined />,
|
||||
icon: <Save size={14} />,
|
||||
onClick: async () => {
|
||||
const agent = omit(assistant, ['model', 'emoji'])
|
||||
agent.id = uuid()
|
||||
@ -306,7 +307,7 @@ function getMenuItems({
|
||||
{
|
||||
label: t('assistants.icon.type'),
|
||||
key: 'icon-type',
|
||||
icon: <SmileOutlined />,
|
||||
icon: <Smile size={14} />,
|
||||
children: [
|
||||
{
|
||||
label: t('settings.assistant.icon.type.model'),
|
||||
@ -331,7 +332,7 @@ function getMenuItems({
|
||||
{
|
||||
label: t('assistants.tags.manage'),
|
||||
key: 'all-tags',
|
||||
icon: <PlusOutlined />,
|
||||
icon: <Plus size={14} />,
|
||||
children: createTagMenuItems(allTags, assistant, assistants, updateAssistants, t)
|
||||
},
|
||||
{
|
||||
@ -345,13 +346,13 @@ function getMenuItems({
|
||||
{
|
||||
label: t('common.sort.pinyin.asc'),
|
||||
key: 'sort-asc',
|
||||
icon: <SortAscendingOutlined />,
|
||||
icon: <ArrowDownAZ size={14} />,
|
||||
onClick: sortByPinyinAsc
|
||||
},
|
||||
{
|
||||
label: t('common.sort.pinyin.desc'),
|
||||
key: 'sort-desc',
|
||||
icon: <SortDescendingOutlined />,
|
||||
icon: <ArrowUpAZ size={14} />,
|
||||
onClick: sortByPinyinDesc
|
||||
},
|
||||
{
|
||||
@ -360,7 +361,7 @@ function getMenuItems({
|
||||
{
|
||||
label: t('common.delete'),
|
||||
key: 'delete',
|
||||
icon: <DeleteOutlined />,
|
||||
icon: <DeleteIcon size={14} className="lucide-custom" />,
|
||||
danger: true,
|
||||
onClick: () => {
|
||||
window.modal.confirm({
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { DragDropContext, Draggable, Droppable } from '@hello-pangea/dnd'
|
||||
import { DeleteIcon } from '@renderer/components/Icons'
|
||||
import { Box } from '@renderer/components/Layout'
|
||||
import { TopView } from '@renderer/components/TopView'
|
||||
import { useAssistants } from '@renderer/hooks/useAssistant'
|
||||
import { useTags } from '@renderer/hooks/useTags'
|
||||
import { Button, Empty, Modal } from 'antd'
|
||||
import { isEmpty } from 'lodash'
|
||||
import { Trash } from 'lucide-react'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -94,7 +94,7 @@ const PopupContainer: React.FC<Props> = ({ title, resolve }) => {
|
||||
<Box mr={8}>{tag}</Box>
|
||||
<Button
|
||||
type="text"
|
||||
icon={<Trash size={16} />}
|
||||
icon={<DeleteIcon size={16} className="lucide-custom" />}
|
||||
danger
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { DeleteOutlined, EditOutlined, SettingOutlined } from '@ant-design/icons'
|
||||
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
||||
import { DraggableList } from '@renderer/components/DraggableList'
|
||||
import { DeleteIcon, EditIcon } from '@renderer/components/Icons'
|
||||
import ListItem from '@renderer/components/ListItem'
|
||||
import PromptPopup from '@renderer/components/Popups/PromptPopup'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
@ -9,7 +9,7 @@ import { useShortcut } from '@renderer/hooks/useShortcuts'
|
||||
import KnowledgeSearchPopup from '@renderer/pages/knowledge/components/KnowledgeSearchPopup'
|
||||
import { KnowledgeBase } from '@renderer/types'
|
||||
import { Dropdown, Empty, MenuProps } from 'antd'
|
||||
import { Book, Plus } from 'lucide-react'
|
||||
import { Book, Plus, Settings } from 'lucide-react'
|
||||
import { FC, useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -49,7 +49,7 @@ const KnowledgePage: FC = () => {
|
||||
{
|
||||
label: t('knowledge.rename'),
|
||||
key: 'rename',
|
||||
icon: <EditOutlined />,
|
||||
icon: <EditIcon size={14} />,
|
||||
async onClick() {
|
||||
const name = await PromptPopup.show({
|
||||
title: t('knowledge.rename'),
|
||||
@ -62,9 +62,9 @@ const KnowledgePage: FC = () => {
|
||||
}
|
||||
},
|
||||
{
|
||||
label: t('knowledge.settings.title'),
|
||||
label: t('common.settings'),
|
||||
key: 'settings',
|
||||
icon: <SettingOutlined />,
|
||||
icon: <Settings size={14} />,
|
||||
onClick: () => handleEditKnowledgeBase(base)
|
||||
},
|
||||
{ type: 'divider' },
|
||||
@ -72,7 +72,7 @@ const KnowledgePage: FC = () => {
|
||||
label: t('common.delete'),
|
||||
danger: true,
|
||||
key: 'delete',
|
||||
icon: <DeleteOutlined />,
|
||||
icon: <DeleteIcon size={14} className="lucide-custom" />,
|
||||
onClick: () => {
|
||||
window.modal.confirm({
|
||||
title: t('knowledge.delete_confirm'),
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import type { KnowledgeBase, Model } from '@renderer/types'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { userEvent } from '@testing-library/user-event'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import AdvancedSettingsPanel from '../components/KnowledgeSettings/AdvancedSettingsPanel'
|
||||
@ -36,6 +35,27 @@ vi.mock('react-i18next', () => ({
|
||||
})
|
||||
}))
|
||||
|
||||
vi.mock('lucide-react', () => ({
|
||||
TriangleAlert: () => <span>warning</span>
|
||||
}))
|
||||
|
||||
vi.mock('antd', () => ({
|
||||
Alert: ({ message }: { message: string }) => <div role="alert">{message}</div>,
|
||||
InputNumber: ({ ref, value, onChange, placeholder, disabled, style, 'aria-label': ariaLabel }: any) => (
|
||||
<input
|
||||
ref={ref}
|
||||
type="number"
|
||||
data-testid="input-number"
|
||||
aria-label={ariaLabel}
|
||||
placeholder={placeholder}
|
||||
value={value ?? ''}
|
||||
onChange={(e) => onChange(e.target.valueAsNumber)}
|
||||
disabled={disabled}
|
||||
style={style}
|
||||
/>
|
||||
)
|
||||
}))
|
||||
|
||||
/**
|
||||
* 创建测试用的 KnowledgeBase 对象
|
||||
* @param overrides 可选的属性覆盖
|
||||
@ -78,23 +98,19 @@ describe('AdvancedSettingsPanel', () => {
|
||||
})
|
||||
|
||||
describe('handlers', () => {
|
||||
it('should call handlers when values are changed', async () => {
|
||||
const user = userEvent.setup()
|
||||
it('should call handlers when values are changed', () => {
|
||||
render(<AdvancedSettingsPanel newBase={mockBase} handlers={mocks.handlers} />)
|
||||
|
||||
const chunkSizeInput = screen.getByLabelText('分块大小')
|
||||
await user.clear(chunkSizeInput)
|
||||
await user.type(chunkSizeInput, '600')
|
||||
fireEvent.change(chunkSizeInput, { target: { value: '600' } })
|
||||
expect(mocks.handlers.handleChunkSizeChange).toHaveBeenCalledWith(600)
|
||||
|
||||
const chunkOverlapInput = screen.getByLabelText('分块重叠')
|
||||
await user.clear(chunkOverlapInput)
|
||||
await user.type(chunkOverlapInput, '300')
|
||||
fireEvent.change(chunkOverlapInput, { target: { value: '300' } })
|
||||
expect(mocks.handlers.handleChunkOverlapChange).toHaveBeenCalledWith(300)
|
||||
|
||||
const thresholdInput = screen.getByLabelText('检索相似度阈值')
|
||||
await user.clear(thresholdInput)
|
||||
await user.type(thresholdInput, '0.6')
|
||||
fireEvent.change(thresholdInput, { target: { value: '0.6' } })
|
||||
expect(mocks.handlers.handleThresholdChange).toHaveBeenCalledWith(0.6)
|
||||
})
|
||||
})
|
||||
|
||||
@ -31,84 +31,14 @@ exports[`AdvancedSettingsPanel > basic rendering > should match snapshot 1`] = `
|
||||
knowledge.chunk_size_tooltip
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-input-number css-dev-only-do-not-override-1261szd ant-input-number-outlined"
|
||||
<input
|
||||
aria-label="分块大小"
|
||||
data-testid="input-number"
|
||||
placeholder="knowledge.chunk_size_placeholder"
|
||||
style="width: 100%;"
|
||||
>
|
||||
<div
|
||||
class="ant-input-number-handler-wrap"
|
||||
>
|
||||
<span
|
||||
aria-disabled="false"
|
||||
aria-label="Increase Value"
|
||||
class="ant-input-number-handler ant-input-number-handler-up"
|
||||
role="button"
|
||||
unselectable="on"
|
||||
>
|
||||
<span
|
||||
aria-label="up"
|
||||
class="anticon anticon-up ant-input-number-handler-up-inner"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="up"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M890.5 755.3L537.9 269.2c-12.8-17.6-39-17.6-51.7 0L133.5 755.3A8 8 0 00140 768h75c5.1 0 9.9-2.5 12.9-6.6L512 369.8l284.1 391.6c3 4.1 7.8 6.6 12.9 6.6h75c6.5 0 10.3-7.4 6.5-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
aria-disabled="false"
|
||||
aria-label="Decrease Value"
|
||||
class="ant-input-number-handler ant-input-number-handler-down"
|
||||
role="button"
|
||||
unselectable="on"
|
||||
>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down ant-input-number-handler-down-inner"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-input-number-input-wrap"
|
||||
>
|
||||
<input
|
||||
aria-label="分块大小"
|
||||
aria-valuemin="100"
|
||||
aria-valuenow="500"
|
||||
autocomplete="off"
|
||||
class="ant-input-number-input"
|
||||
placeholder="knowledge.chunk_size_placeholder"
|
||||
role="spinbutton"
|
||||
step="1"
|
||||
value="500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
type="number"
|
||||
value="500"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="c1"
|
||||
@ -121,84 +51,14 @@ exports[`AdvancedSettingsPanel > basic rendering > should match snapshot 1`] = `
|
||||
knowledge.chunk_overlap_tooltip
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-input-number css-dev-only-do-not-override-1261szd ant-input-number-outlined"
|
||||
<input
|
||||
aria-label="分块重叠"
|
||||
data-testid="input-number"
|
||||
placeholder="knowledge.chunk_overlap_placeholder"
|
||||
style="width: 100%;"
|
||||
>
|
||||
<div
|
||||
class="ant-input-number-handler-wrap"
|
||||
>
|
||||
<span
|
||||
aria-disabled="false"
|
||||
aria-label="Increase Value"
|
||||
class="ant-input-number-handler ant-input-number-handler-up"
|
||||
role="button"
|
||||
unselectable="on"
|
||||
>
|
||||
<span
|
||||
aria-label="up"
|
||||
class="anticon anticon-up ant-input-number-handler-up-inner"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="up"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M890.5 755.3L537.9 269.2c-12.8-17.6-39-17.6-51.7 0L133.5 755.3A8 8 0 00140 768h75c5.1 0 9.9-2.5 12.9-6.6L512 369.8l284.1 391.6c3 4.1 7.8 6.6 12.9 6.6h75c6.5 0 10.3-7.4 6.5-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
aria-disabled="false"
|
||||
aria-label="Decrease Value"
|
||||
class="ant-input-number-handler ant-input-number-handler-down"
|
||||
role="button"
|
||||
unselectable="on"
|
||||
>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down ant-input-number-handler-down-inner"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-input-number-input-wrap"
|
||||
>
|
||||
<input
|
||||
aria-label="分块重叠"
|
||||
aria-valuemin="0"
|
||||
aria-valuenow="200"
|
||||
autocomplete="off"
|
||||
class="ant-input-number-input"
|
||||
placeholder="knowledge.chunk_overlap_placeholder"
|
||||
role="spinbutton"
|
||||
step="1"
|
||||
value="200"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
type="number"
|
||||
value="200"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="c1"
|
||||
@ -211,119 +71,19 @@ exports[`AdvancedSettingsPanel > basic rendering > should match snapshot 1`] = `
|
||||
knowledge.threshold_tooltip
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-input-number css-dev-only-do-not-override-1261szd ant-input-number-outlined"
|
||||
<input
|
||||
aria-label="检索相似度阈值"
|
||||
data-testid="input-number"
|
||||
placeholder="knowledge.threshold_placeholder"
|
||||
style="width: 100%;"
|
||||
>
|
||||
<div
|
||||
class="ant-input-number-handler-wrap"
|
||||
>
|
||||
<span
|
||||
aria-disabled="false"
|
||||
aria-label="Increase Value"
|
||||
class="ant-input-number-handler ant-input-number-handler-up"
|
||||
role="button"
|
||||
unselectable="on"
|
||||
>
|
||||
<span
|
||||
aria-label="up"
|
||||
class="anticon anticon-up ant-input-number-handler-up-inner"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="up"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M890.5 755.3L537.9 269.2c-12.8-17.6-39-17.6-51.7 0L133.5 755.3A8 8 0 00140 768h75c5.1 0 9.9-2.5 12.9-6.6L512 369.8l284.1 391.6c3 4.1 7.8 6.6 12.9 6.6h75c6.5 0 10.3-7.4 6.5-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
aria-disabled="false"
|
||||
aria-label="Decrease Value"
|
||||
class="ant-input-number-handler ant-input-number-handler-down"
|
||||
role="button"
|
||||
unselectable="on"
|
||||
>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down ant-input-number-handler-down-inner"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-input-number-input-wrap"
|
||||
>
|
||||
<input
|
||||
aria-label="检索相似度阈值"
|
||||
aria-valuemax="1"
|
||||
aria-valuemin="0"
|
||||
aria-valuenow="0.5"
|
||||
autocomplete="off"
|
||||
class="ant-input-number-input"
|
||||
placeholder="knowledge.threshold_placeholder"
|
||||
role="spinbutton"
|
||||
step="0.1"
|
||||
value="0.5"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
type="number"
|
||||
value="0.5"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-alert ant-alert-warning css-dev-only-do-not-override-1261szd"
|
||||
data-show="true"
|
||||
role="alert"
|
||||
>
|
||||
<span
|
||||
aria-label="warning"
|
||||
class="anticon anticon-warning ant-alert-icon"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="warning"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M464 720a48 48 0 1096 0 48 48 0 10-96 0zm16-304v184c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V416c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8zm475.7 440l-416-720c-6.2-10.7-16.9-16-27.7-16s-21.6 5.3-27.7 16l-416 720C56 877.4 71.4 904 96 904h832c24.6 0 40-26.6 27.7-48zm-783.5-27.9L512 239.9l339.8 588.2H172.2z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
<div
|
||||
class="ant-alert-content"
|
||||
>
|
||||
<div
|
||||
class="ant-alert-message"
|
||||
>
|
||||
避免修改这个高级设置。
|
||||
</div>
|
||||
</div>
|
||||
避免修改这个高级设置。
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { WarningOutlined } from '@ant-design/icons'
|
||||
import InfoTooltip from '@renderer/components/InfoTooltip'
|
||||
import { KnowledgeBase } from '@renderer/types'
|
||||
import { Alert, InputNumber } from 'antd'
|
||||
import { TriangleAlert } from 'lucide-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { SettingsItem, SettingsPanel } from './styles'
|
||||
@ -68,7 +68,12 @@ const AdvancedSettingsPanel: React.FC<AdvancedSettingsPanelProps> = ({ newBase,
|
||||
/>
|
||||
</SettingsItem>
|
||||
|
||||
<Alert message={t('knowledge.chunk_size_change_warning')} type="warning" showIcon icon={<WarningOutlined />} />
|
||||
<Alert
|
||||
message={t('knowledge.chunk_size_change_warning')}
|
||||
type="warning"
|
||||
showIcon
|
||||
icon={<TriangleAlert size={16} className="lucide-custom" />}
|
||||
/>
|
||||
</SettingsPanel>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { DeleteOutlined } from '@ant-design/icons'
|
||||
import { loggerService } from '@logger'
|
||||
import Ellipsis from '@renderer/components/Ellipsis'
|
||||
import { DeleteIcon } from '@renderer/components/Icons'
|
||||
import { DynamicVirtualList } from '@renderer/components/VirtualList'
|
||||
import { useKnowledge } from '@renderer/hooks/useKnowledge'
|
||||
import FileItem from '@renderer/pages/files/FileItem'
|
||||
@ -8,7 +8,7 @@ import { getProviderName } from '@renderer/services/ProviderService'
|
||||
import { KnowledgeBase, KnowledgeItem } from '@renderer/types'
|
||||
import { Button, Tooltip } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { Plus } from 'lucide-react'
|
||||
import { PlusIcon } from 'lucide-react'
|
||||
import { FC, useCallback, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -68,7 +68,7 @@ const KnowledgeDirectories: FC<KnowledgeContentProps> = ({ selectedBase, progres
|
||||
<ItemHeader>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<Plus size={16} />}
|
||||
icon={<PlusIcon size={16} />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleAddDirectory()
|
||||
@ -111,7 +111,12 @@ const KnowledgeDirectories: FC<KnowledgeContentProps> = ({ selectedBase, progres
|
||||
type="directory"
|
||||
/>
|
||||
</StatusIconWrapper>
|
||||
<Button type="text" danger onClick={() => removeItem(item)} icon={<DeleteOutlined />} />
|
||||
<Button
|
||||
type="text"
|
||||
danger
|
||||
onClick={() => removeItem(item)}
|
||||
icon={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
/>
|
||||
</FlexAlignCenter>
|
||||
)
|
||||
}}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { DeleteOutlined } from '@ant-design/icons'
|
||||
import { loggerService } from '@logger'
|
||||
import Ellipsis from '@renderer/components/Ellipsis'
|
||||
import { useKnowledge } from '@renderer/hooks/useKnowledge'
|
||||
@ -11,14 +10,15 @@ import { formatFileSize, uuid } from '@renderer/utils'
|
||||
import { bookExts, documentExts, textExts, thirdPartyApplicationExts } from '@shared/config/constant'
|
||||
import { Button, Tooltip, Upload } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { Plus } from 'lucide-react'
|
||||
import { FC, useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
|
||||
const logger = loggerService.withContext('KnowledgeFiles')
|
||||
|
||||
import { DeleteIcon } from '@renderer/components/Icons'
|
||||
import { DynamicVirtualList } from '@renderer/components/VirtualList'
|
||||
import { PlusIcon } from 'lucide-react'
|
||||
|
||||
import {
|
||||
ClickableSpan,
|
||||
@ -139,7 +139,7 @@ const KnowledgeFiles: FC<KnowledgeContentProps> = ({ selectedBase, progressMap,
|
||||
<ItemHeader>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<Plus size={16} />}
|
||||
icon={<PlusIcon size={16} />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleAddFile()
|
||||
@ -210,7 +210,12 @@ const KnowledgeFiles: FC<KnowledgeContentProps> = ({ selectedBase, progressMap,
|
||||
type="file"
|
||||
/>
|
||||
</StatusIconWrapper>
|
||||
<Button type="text" danger onClick={() => removeItem(item)} icon={<DeleteOutlined />} />
|
||||
<Button
|
||||
type="text"
|
||||
danger
|
||||
onClick={() => removeItem(item)}
|
||||
icon={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
/>
|
||||
</FlexAlignCenter>
|
||||
)
|
||||
}}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { DeleteOutlined, EditOutlined } from '@ant-design/icons'
|
||||
import { DeleteIcon, EditIcon } from '@renderer/components/Icons'
|
||||
import TextEditPopup from '@renderer/components/Popups/TextEditPopup'
|
||||
import { DynamicVirtualList } from '@renderer/components/VirtualList'
|
||||
import { useKnowledge } from '@renderer/hooks/useKnowledge'
|
||||
@ -7,7 +7,7 @@ import { getProviderName } from '@renderer/services/ProviderService'
|
||||
import { KnowledgeBase, KnowledgeItem } from '@renderer/types'
|
||||
import { Button } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { Plus } from 'lucide-react'
|
||||
import { PlusIcon } from 'lucide-react'
|
||||
import { FC, useCallback, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -64,7 +64,7 @@ const KnowledgeNotes: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
<ItemHeader>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<Plus size={16} />}
|
||||
icon={<PlusIcon size={16} />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleAddNote()
|
||||
@ -91,7 +91,7 @@ const KnowledgeNotes: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
extra: getDisplayTime(note),
|
||||
actions: (
|
||||
<FlexAlignCenter>
|
||||
<Button type="text" onClick={() => handleEditNote(note)} icon={<EditOutlined />} />
|
||||
<Button type="text" onClick={() => handleEditNote(note)} icon={<EditIcon size={14} />} />
|
||||
<StatusIconWrapper>
|
||||
<StatusIcon
|
||||
sourceId={note.id}
|
||||
@ -100,7 +100,12 @@ const KnowledgeNotes: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
type="note"
|
||||
/>
|
||||
</StatusIconWrapper>
|
||||
<Button type="text" danger onClick={() => removeItem(note)} icon={<DeleteOutlined />} />
|
||||
<Button
|
||||
type="text"
|
||||
danger
|
||||
onClick={() => removeItem(note)}
|
||||
icon={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
/>
|
||||
</FlexAlignCenter>
|
||||
)
|
||||
}}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { DeleteOutlined } from '@ant-design/icons'
|
||||
import { loggerService } from '@logger'
|
||||
import Ellipsis from '@renderer/components/Ellipsis'
|
||||
import { DeleteIcon } from '@renderer/components/Icons'
|
||||
import PromptPopup from '@renderer/components/Popups/PromptPopup'
|
||||
import { DynamicVirtualList } from '@renderer/components/VirtualList'
|
||||
import { useKnowledge } from '@renderer/hooks/useKnowledge'
|
||||
@ -9,7 +9,7 @@ import { getProviderName } from '@renderer/services/ProviderService'
|
||||
import { KnowledgeBase, KnowledgeItem } from '@renderer/types'
|
||||
import { Button, message, Tooltip } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { Plus } from 'lucide-react'
|
||||
import { PlusIcon } from 'lucide-react'
|
||||
import { FC, useCallback, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -87,7 +87,7 @@ const KnowledgeSitemaps: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
<ItemHeader>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<Plus size={16} />}
|
||||
icon={<PlusIcon size={16} />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleAddSitemap()
|
||||
@ -133,7 +133,12 @@ const KnowledgeSitemaps: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
type="sitemap"
|
||||
/>
|
||||
</StatusIconWrapper>
|
||||
<Button type="text" danger onClick={() => removeItem(item)} icon={<DeleteOutlined />} />
|
||||
<Button
|
||||
type="text"
|
||||
danger
|
||||
onClick={() => removeItem(item)}
|
||||
icon={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
/>
|
||||
</FlexAlignCenter>
|
||||
)
|
||||
}}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { CopyOutlined, DeleteOutlined, EditOutlined } from '@ant-design/icons'
|
||||
import Ellipsis from '@renderer/components/Ellipsis'
|
||||
import { CopyIcon, DeleteIcon, EditIcon } from '@renderer/components/Icons'
|
||||
import PromptPopup from '@renderer/components/Popups/PromptPopup'
|
||||
import { DynamicVirtualList } from '@renderer/components/VirtualList'
|
||||
import { useKnowledge } from '@renderer/hooks/useKnowledge'
|
||||
@ -8,7 +8,7 @@ import { getProviderName } from '@renderer/services/ProviderService'
|
||||
import { KnowledgeBase, KnowledgeItem } from '@renderer/types'
|
||||
import { Button, Dropdown, Tooltip } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { Plus } from 'lucide-react'
|
||||
import { PlusIcon } from 'lucide-react'
|
||||
import { FC, useCallback, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -115,7 +115,7 @@ const KnowledgeUrls: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
<ItemHeader>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<Plus size={16} />}
|
||||
icon={<PlusIcon size={16} />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleAddUrl()
|
||||
@ -143,13 +143,13 @@ const KnowledgeUrls: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
items: [
|
||||
{
|
||||
key: 'edit',
|
||||
icon: <EditOutlined />,
|
||||
icon: <EditIcon size={14} />,
|
||||
label: t('knowledge.edit_remark'),
|
||||
onClick: () => handleEditRemark(item)
|
||||
},
|
||||
{
|
||||
key: 'copy',
|
||||
icon: <CopyOutlined />,
|
||||
icon: <CopyIcon size={14} />,
|
||||
label: t('common.copy'),
|
||||
onClick: () => {
|
||||
navigator.clipboard.writeText(item.content as string)
|
||||
@ -178,7 +178,12 @@ const KnowledgeUrls: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
<StatusIconWrapper>
|
||||
<StatusIcon sourceId={item.id} base={base} getProcessingStatus={getProcessingStatus} type="url" />
|
||||
</StatusIconWrapper>
|
||||
<Button type="text" danger onClick={() => removeItem(item)} icon={<DeleteOutlined />} />
|
||||
<Button
|
||||
type="text"
|
||||
danger
|
||||
onClick={() => removeItem(item)}
|
||||
icon={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
/>
|
||||
</FlexAlignCenter>
|
||||
)
|
||||
}}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -76,8 +76,8 @@ export const DEFAULT_PAINTING: DmxapiPainting = {
|
||||
|
||||
export const MODEOPTIONS = [
|
||||
{ label: 'paintings.mode.generate', value: generationModeType.GENERATION },
|
||||
{ label: '改图', value: generationModeType.EDIT },
|
||||
{ label: '合并图', value: generationModeType.MERGE }
|
||||
{ label: 'paintings.mode.edit', value: generationModeType.EDIT },
|
||||
{ label: 'paintings.mode.merge', value: generationModeType.MERGE }
|
||||
]
|
||||
|
||||
// 获取模型分组数据
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { DeleteOutlined, PlusOutlined, QuestionCircleOutlined } from '@ant-design/icons'
|
||||
import { QuestionCircleOutlined } from '@ant-design/icons'
|
||||
import ModelAvatar from '@renderer/components/Avatar/ModelAvatar'
|
||||
import EditableNumber from '@renderer/components/EditableNumber'
|
||||
import { DeleteIcon, ResetIcon } from '@renderer/components/Icons'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import SelectModelPopup from '@renderer/components/Popups/SelectModelPopup'
|
||||
import Selector from '@renderer/components/Selector'
|
||||
@ -10,6 +11,7 @@ import { Assistant, AssistantSettingCustomParameters, AssistantSettings } from '
|
||||
import { modalConfirm } from '@renderer/utils'
|
||||
import { Button, Col, Divider, Input, InputNumber, Row, Select, Slider, Switch, Tooltip } from 'antd'
|
||||
import { isNull } from 'lodash'
|
||||
import { PlusIcon } from 'lucide-react'
|
||||
import { FC, useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -213,7 +215,7 @@ const AssistantModelSettings: FC<Props> = ({ assistant, updateAssistant, updateA
|
||||
<Label>{t('assistants.settings.default_model')}</Label>
|
||||
<HStack alignItems="center" gap={5}>
|
||||
<ModelSelectButton
|
||||
icon={defaultModel ? <ModelAvatar model={defaultModel} size={20} /> : <PlusOutlined />}
|
||||
icon={defaultModel ? <ModelAvatar model={defaultModel} size={20} /> : <PlusIcon size={18} />}
|
||||
onClick={onSelectModel}>
|
||||
<ModelName>{defaultModel ? defaultModel.name : t('agents.edit.model.select.title')}</ModelName>
|
||||
</ModelSelectButton>
|
||||
@ -221,7 +223,7 @@ const AssistantModelSettings: FC<Props> = ({ assistant, updateAssistant, updateA
|
||||
<Button
|
||||
color="danger"
|
||||
variant="filled"
|
||||
icon={<DeleteOutlined />}
|
||||
icon={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
onClick={() => {
|
||||
setDefaultModel(undefined)
|
||||
updateAssistant({ ...assistant, defaultModel: undefined })
|
||||
@ -449,7 +451,7 @@ const AssistantModelSettings: FC<Props> = ({ assistant, updateAssistant, updateA
|
||||
<Divider style={{ margin: '10px 0' }} />
|
||||
<SettingRow style={{ minHeight: 30 }}>
|
||||
<Label>{t('models.custom_parameters')}</Label>
|
||||
<Button icon={<PlusOutlined />} onClick={onAddCustomParameter}>
|
||||
<Button icon={<PlusIcon size={18} />} onClick={onAddCustomParameter}>
|
||||
{t('models.add_parameter')}
|
||||
</Button>
|
||||
</SettingRow>
|
||||
@ -478,7 +480,7 @@ const AssistantModelSettings: FC<Props> = ({ assistant, updateAssistant, updateA
|
||||
<Button
|
||||
color="danger"
|
||||
variant="filled"
|
||||
icon={<DeleteOutlined />}
|
||||
icon={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
onClick={() => onDeleteCustomParameter(index)}
|
||||
/>
|
||||
</Col>
|
||||
@ -486,7 +488,7 @@ const AssistantModelSettings: FC<Props> = ({ assistant, updateAssistant, updateA
|
||||
))}
|
||||
<Divider style={{ margin: '15px 0' }} />
|
||||
<HStack justifyContent="flex-end">
|
||||
<Button onClick={onReset} style={{ width: 80 }} danger type="primary">
|
||||
<Button onClick={onReset} danger type="primary" icon={<ResetIcon size={16} />}>
|
||||
{t('chat.settings.reset')}
|
||||
</Button>
|
||||
</HStack>
|
||||
|
||||
@ -165,10 +165,6 @@ const Container = styled.div`
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
|
||||
.ant-btn {
|
||||
line-height: 0;
|
||||
}
|
||||
`
|
||||
|
||||
const EmojiButtonWrapper = styled.div`
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import { DeleteOutlined, EditOutlined, ExclamationCircleOutlined, PlusOutlined } from '@ant-design/icons'
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons'
|
||||
import { DraggableList } from '@renderer/components/DraggableList'
|
||||
import { DeleteIcon, EditIcon } from '@renderer/components/Icons'
|
||||
import FileItem from '@renderer/pages/files/FileItem'
|
||||
import { Assistant, QuickPhrase } from '@renderer/types'
|
||||
import { Button, Flex, Input, Modal, Popconfirm, Space } from 'antd'
|
||||
import { PlusIcon } from 'lucide-react'
|
||||
import { FC, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -82,7 +84,7 @@ const AssistantRegularPromptsSettings: FC<AssistantRegularPromptsSettingsProps>
|
||||
<Container>
|
||||
<SettingTitle>
|
||||
{t('assistants.settings.regular_phrases.title', 'Regular Prompts')}
|
||||
<Button type="text" icon={<PlusOutlined />} onClick={handleAdd} />
|
||||
<Button type="text" icon={<PlusIcon size={18} />} onClick={handleAdd} />
|
||||
</SettingTitle>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
@ -102,7 +104,7 @@ const AssistantRegularPromptsSettings: FC<AssistantRegularPromptsSettingsProps>
|
||||
extra: prompt.content,
|
||||
actions: (
|
||||
<Flex gap={4} style={{ opacity: 0.6 }}>
|
||||
<Button key="edit" type="text" icon={<EditOutlined />} onClick={() => handleEdit(prompt)} />
|
||||
<Button key="edit" type="text" icon={<EditIcon size={14} />} onClick={() => handleEdit(prompt)} />
|
||||
<Popconfirm
|
||||
title={t('assistants.settings.regular_phrases.delete', 'Delete Prompt')}
|
||||
description={t(
|
||||
@ -113,7 +115,12 @@ const AssistantRegularPromptsSettings: FC<AssistantRegularPromptsSettingsProps>
|
||||
cancelText={t('common.cancel')}
|
||||
onConfirm={() => handleDelete(prompt.id)}
|
||||
icon={<ExclamationCircleOutlined style={{ color: 'red' }} />}>
|
||||
<Button key="delete" type="text" danger icon={<DeleteOutlined />} />
|
||||
<Button
|
||||
key="delete"
|
||||
type="text"
|
||||
danger
|
||||
icon={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
/>
|
||||
</Popconfirm>
|
||||
</Flex>
|
||||
)
|
||||
|
||||
@ -92,7 +92,6 @@ const AssistantSettingPopupContainer: React.FC<Props> = ({ resolve, tab, ...prop
|
||||
<StyledModal
|
||||
open={open}
|
||||
onOk={onOk}
|
||||
onClose={onCancel}
|
||||
onCancel={onCancel}
|
||||
afterClose={afterClose}
|
||||
footer={null}
|
||||
|
||||
@ -2,9 +2,7 @@ import {
|
||||
CloudServerOutlined,
|
||||
CloudSyncOutlined,
|
||||
FileSearchOutlined,
|
||||
FolderOpenOutlined,
|
||||
LoadingOutlined,
|
||||
SaveOutlined,
|
||||
YuqueOutlined
|
||||
} from '@ant-design/icons'
|
||||
import DividerWithText from '@renderer/components/DividerWithText'
|
||||
@ -22,7 +20,7 @@ import { AppInfo } from '@renderer/types'
|
||||
import { formatFileSize } from '@renderer/utils'
|
||||
import { occupiedDirs } from '@shared/config/constant'
|
||||
import { Button, Progress, Switch, Typography } from 'antd'
|
||||
import { FileText, FolderCog, FolderInput, Sparkle } from 'lucide-react'
|
||||
import { FileText, FolderCog, FolderInput, FolderOpen, SaveIcon, Sparkle } from 'lucide-react'
|
||||
import { FC, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -588,10 +586,10 @@ const DataSettings: FC = () => {
|
||||
<SettingRow>
|
||||
<SettingRowTitle>{t('settings.general.backup.title')}</SettingRowTitle>
|
||||
<HStack gap="5px" justifyContent="space-between">
|
||||
<Button onClick={BackupPopup.show} icon={<SaveOutlined />}>
|
||||
<Button onClick={BackupPopup.show} icon={<SaveIcon size={14} />}>
|
||||
{t('settings.general.backup.button')}
|
||||
</Button>
|
||||
<Button onClick={RestorePopup.show} icon={<FolderOpenOutlined />}>
|
||||
<Button onClick={RestorePopup.show} icon={<FolderOpen size={14} />}>
|
||||
{t('settings.general.restore.button')}
|
||||
</Button>
|
||||
</HStack>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import CodeEditor from '@renderer/components/CodeEditor'
|
||||
import { ResetIcon } from '@renderer/components/Icons'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import TextBadge from '@renderer/components/TextBadge'
|
||||
import { isMac, THEME_COLOR_PRESETS } from '@renderer/config/constant'
|
||||
@ -18,7 +19,7 @@ import {
|
||||
} from '@renderer/store/settings'
|
||||
import { ThemeMode } from '@renderer/types'
|
||||
import { Button, ColorPicker, Segmented, Switch } from 'antd'
|
||||
import { Minus, Monitor, Moon, Plus, RotateCcw, Sun } from 'lucide-react'
|
||||
import { Minus, Monitor, Moon, Plus, Sun } from 'lucide-react'
|
||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -247,7 +248,7 @@ const DisplaySettings: FC = () => {
|
||||
<Button
|
||||
onClick={() => handleZoomFactor(0, true)}
|
||||
style={{ marginLeft: 8 }}
|
||||
icon={<RotateCcw size="14" />}
|
||||
icon={<ResetIcon size="14" />}
|
||||
color="default"
|
||||
variant="text"
|
||||
/>
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { EditOutlined } from '@ant-design/icons'
|
||||
import { nanoid } from '@reduxjs/toolkit'
|
||||
import { DraggableList } from '@renderer/components/DraggableList'
|
||||
import { EditIcon, RefreshIcon } from '@renderer/components/Icons'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import { useMCPServers } from '@renderer/hooks/useMCPServers'
|
||||
import { getMcpTypeLabel } from '@renderer/i18n/label'
|
||||
import { MCPServer } from '@renderer/types'
|
||||
import { formatMcpError } from '@renderer/utils/error'
|
||||
import { Badge, Button, Dropdown, Empty, Switch, Tag } from 'antd'
|
||||
import { MonitorCheck, Plus, RefreshCw, Settings2, SquareArrowOutUpRight } from 'lucide-react'
|
||||
import { MonitorCheck, Plus, Settings2, SquareArrowOutUpRight } from 'lucide-react'
|
||||
import { FC, useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useNavigate } from 'react-router'
|
||||
@ -139,7 +139,7 @@ const McpServersList: FC = () => {
|
||||
<ListHeader>
|
||||
<SettingTitle style={{ gap: 3 }}>
|
||||
<span>{t('settings.mcp.newServer')}</span>
|
||||
<Button icon={<EditOutlined />} type="text" onClick={() => EditMcpJsonPopup.show()} shape="circle" />
|
||||
<Button icon={<EditIcon size={14} />} type="text" onClick={() => EditMcpJsonPopup.show()} shape="circle" />
|
||||
</SettingTitle>
|
||||
<ButtonGroup>
|
||||
<InstallNpxUv mini />
|
||||
@ -176,7 +176,7 @@ const McpServersList: FC = () => {
|
||||
{t('settings.mcp.addServer.label')}
|
||||
</Button>
|
||||
</Dropdown>
|
||||
<Button icon={<RefreshCw size={16} />} type="default" onClick={onSyncServers} shape="round">
|
||||
<Button icon={<RefreshIcon size={16} />} type="default" onClick={onSyncServers} shape="round">
|
||||
{t('settings.mcp.sync.title', 'Sync Servers')}
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { DeleteOutlined, SaveOutlined } from '@ant-design/icons'
|
||||
import { loggerService } from '@logger'
|
||||
import { DeleteIcon } from '@renderer/components/Icons'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useMCPServer, useMCPServers } from '@renderer/hooks/useMCPServers'
|
||||
import MCPDescription from '@renderer/pages/settings/MCPSettings/McpDescription'
|
||||
@ -7,7 +7,7 @@ import { MCPPrompt, MCPResource, MCPServer, MCPTool } from '@renderer/types'
|
||||
import { formatMcpError } from '@renderer/utils/error'
|
||||
import { Badge, Button, Flex, Form, Input, Radio, Select, Switch, Tabs } from 'antd'
|
||||
import TextArea from 'antd/es/input/TextArea'
|
||||
import { ChevronDown } from 'lucide-react'
|
||||
import { ChevronDown, SaveIcon } from 'lucide-react'
|
||||
import React, { useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useNavigate, useParams } from 'react-router'
|
||||
@ -732,7 +732,12 @@ const McpSettings: React.FC = () => {
|
||||
<ServerName className="text-nowrap">{server?.name}</ServerName>
|
||||
{serverVersion && <VersionBadge count={serverVersion} color="blue" />}
|
||||
</Flex>
|
||||
<Button danger icon={<DeleteOutlined />} type="text" onClick={() => onDeleteMcpServer(server)} />
|
||||
<Button
|
||||
danger
|
||||
icon={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
type="text"
|
||||
onClick={() => onDeleteMcpServer(server)}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex align="center" gap={16}>
|
||||
<Switch
|
||||
@ -743,7 +748,7 @@ const McpSettings: React.FC = () => {
|
||||
/>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<SaveOutlined />}
|
||||
icon={<SaveIcon size={14} />}
|
||||
onClick={onSave}
|
||||
loading={loading}
|
||||
shape="round"
|
||||
|
||||
@ -1,16 +1,6 @@
|
||||
import {
|
||||
CalendarOutlined,
|
||||
DeleteOutlined,
|
||||
EditOutlined,
|
||||
ExclamationCircleOutlined,
|
||||
MoreOutlined,
|
||||
PlusOutlined,
|
||||
ReloadOutlined,
|
||||
UserAddOutlined,
|
||||
UserDeleteOutlined,
|
||||
UserOutlined
|
||||
} from '@ant-design/icons'
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons'
|
||||
import { loggerService } from '@logger'
|
||||
import { DeleteIcon, EditIcon, LoadingIcon, RefreshIcon } from '@renderer/components/Icons'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import TextBadge from '@renderer/components/TextBadge'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
@ -25,24 +15,10 @@ import {
|
||||
setGlobalMemoryEnabled
|
||||
} from '@renderer/store/memory'
|
||||
import type { MemoryItem } from '@types'
|
||||
import {
|
||||
Avatar,
|
||||
Badge,
|
||||
Button,
|
||||
Dropdown,
|
||||
Empty,
|
||||
Form,
|
||||
Input,
|
||||
Modal,
|
||||
Pagination,
|
||||
Select,
|
||||
Space,
|
||||
Spin,
|
||||
Switch
|
||||
} from 'antd'
|
||||
import { Badge, Button, Dropdown, Empty, Flex, Form, Input, Modal, Pagination, Space, Spin, Switch } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import { Brain, Settings2 } from 'lucide-react'
|
||||
import { Brain, Calendar, MenuIcon, PlusIcon, Settings2, UserRound, UserRoundMinus, UserRoundPlus } from 'lucide-react'
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
@ -57,13 +33,13 @@ import {
|
||||
SettingRowTitle,
|
||||
SettingTitle
|
||||
} from '../index'
|
||||
import { DEFAULT_USER_ID } from './constants'
|
||||
import UserSelector from './UserSelector'
|
||||
|
||||
const logger = loggerService.withContext('MemorySettings')
|
||||
|
||||
dayjs.extend(relativeTime)
|
||||
|
||||
const DEFAULT_USER_ID = 'default-user'
|
||||
const { Option } = Select
|
||||
const { TextArea } = Input
|
||||
|
||||
interface AddMemoryModalProps {
|
||||
@ -112,10 +88,10 @@ const AddMemoryModal: React.FC<AddMemoryModalProps> = ({ visible, onCancel, onAd
|
||||
onOk={() => form.submit()}
|
||||
okButtonProps={{ loading: loading }}
|
||||
title={
|
||||
<Space>
|
||||
<PlusOutlined style={{ color: 'var(--color-primary)' }} />
|
||||
<Flex align="center" gap={8}>
|
||||
<PlusIcon size={16} color="var(--color-primary)" />
|
||||
<span>{t('memory.add_memory')}</span>
|
||||
</Space>
|
||||
</Flex>
|
||||
}
|
||||
styles={{
|
||||
header: {
|
||||
@ -170,10 +146,10 @@ const EditMemoryModal: React.FC<EditMemoryModalProps> = ({ visible, memory, onCa
|
||||
return (
|
||||
<Modal
|
||||
title={
|
||||
<Space>
|
||||
<EditOutlined style={{ color: 'var(--color-primary)' }} />
|
||||
<Flex align="center" gap={8}>
|
||||
<EditIcon size={16} color="var(--color-primary)" />
|
||||
<span>{t('memory.edit_memory')}</span>
|
||||
</Space>
|
||||
</Flex>
|
||||
}
|
||||
open={visible}
|
||||
onCancel={onCancel}
|
||||
@ -268,10 +244,10 @@ const AddUserModal: React.FC<AddUserModalProps> = ({ visible, onCancel, onAdd, e
|
||||
}
|
||||
}}
|
||||
title={
|
||||
<Space>
|
||||
<UserAddOutlined style={{ color: 'var(--color-primary)' }} />
|
||||
<Flex align="center" gap={8}>
|
||||
<UserRoundPlus size={16} color="var(--color-primary)" />
|
||||
<span>{t('memory.add_user')}</span>
|
||||
</Space>
|
||||
</Flex>
|
||||
}>
|
||||
<Form form={form} layout="vertical" onFinish={handleSubmit}>
|
||||
<Form.Item label={t('memory.new_user_id')} name="userId" rules={[{ validator: validateUserId }]}>
|
||||
@ -279,7 +255,7 @@ const AddUserModal: React.FC<AddUserModalProps> = ({ visible, onCancel, onAdd, e
|
||||
placeholder={t('memory.new_user_id_placeholder')}
|
||||
maxLength={50}
|
||||
size="large"
|
||||
prefix={<UserOutlined />}
|
||||
prefix={<UserRound size={16} />}
|
||||
/>
|
||||
</Form.Item>
|
||||
<div
|
||||
@ -324,10 +300,6 @@ const MemorySettings = () => {
|
||||
return user === DEFAULT_USER_ID ? t('memory.default_user') : user
|
||||
}
|
||||
|
||||
const getUserAvatar = (user: string) => {
|
||||
return user === DEFAULT_USER_ID ? user.slice(0, 1).toUpperCase() : user.slice(0, 2).toUpperCase()
|
||||
}
|
||||
|
||||
// Load unique users from database
|
||||
const loadUniqueUsers = useCallback(async () => {
|
||||
try {
|
||||
@ -616,7 +588,7 @@ const MemorySettings = () => {
|
||||
</HStack>
|
||||
<HStack style={{ alignItems: 'center', gap: 10 }}>
|
||||
<Switch checked={globalMemoryEnabled} onChange={handleGlobalMemoryToggle} />
|
||||
<Button icon={<Settings2 size={16} />} onClick={() => setSettingsModalVisible(true)} />
|
||||
<Button type="text" icon={<Settings2 size={16} />} onClick={() => setSettingsModalVisible(true)} />
|
||||
</HStack>
|
||||
</HStack>
|
||||
</SettingGroup>
|
||||
@ -632,52 +604,12 @@ const MemorySettings = () => {
|
||||
{allMemories.length} {t('memory.total_memories')}
|
||||
</SettingHelpText>
|
||||
</div>
|
||||
<Select
|
||||
value={currentUser}
|
||||
onChange={handleUserSwitch}
|
||||
style={{ width: 200 }}
|
||||
dropdownRender={(menu) => (
|
||||
<>
|
||||
{menu}
|
||||
<div style={{ padding: '8px' }}>
|
||||
<Button
|
||||
type="text"
|
||||
onClick={() => setAddUserModalVisible(true)}
|
||||
style={{
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start'
|
||||
}}>
|
||||
<HStack alignItems="center" gap={10}>
|
||||
<UserAddOutlined />
|
||||
<span>{t('memory.add_new_user')}</span>
|
||||
</HStack>
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
)}>
|
||||
<Option value={DEFAULT_USER_ID}>
|
||||
<HStack alignItems="center" gap={10}>
|
||||
<Avatar size={20} style={{ background: 'var(--color-primary)' }}>
|
||||
{getUserAvatar(DEFAULT_USER_ID)}
|
||||
</Avatar>
|
||||
<span>{t('memory.default_user')}</span>
|
||||
</HStack>
|
||||
</Option>
|
||||
{uniqueUsers
|
||||
.filter((user) => user !== DEFAULT_USER_ID)
|
||||
.map((user) => (
|
||||
<Option key={user} value={user}>
|
||||
<HStack alignItems="center" gap={10}>
|
||||
<Avatar size={20} style={{ background: 'var(--color-primary)' }}>
|
||||
{getUserAvatar(user)}
|
||||
</Avatar>
|
||||
<span>{user}</span>
|
||||
</HStack>
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
<UserSelector
|
||||
currentUser={currentUser}
|
||||
uniqueUsers={uniqueUsers}
|
||||
onUserSwitch={handleUserSwitch}
|
||||
onAddUser={() => setAddUserModalVisible(true)}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
@ -703,7 +635,7 @@ const MemorySettings = () => {
|
||||
allowClear
|
||||
style={{ width: 240 }}
|
||||
/>
|
||||
<Button type="primary" icon={<PlusOutlined />} onClick={() => setAddMemoryModalVisible(true)}>
|
||||
<Button type="primary" icon={<PlusIcon size={18} />} onClick={() => setAddMemoryModalVisible(true)}>
|
||||
{t('memory.add_memory')}
|
||||
</Button>
|
||||
<Dropdown
|
||||
@ -712,7 +644,7 @@ const MemorySettings = () => {
|
||||
{
|
||||
key: 'refresh',
|
||||
label: t('common.refresh'),
|
||||
icon: <ReloadOutlined />,
|
||||
icon: <RefreshIcon size={14} />,
|
||||
onClick: () => loadMemories(currentUser)
|
||||
},
|
||||
{
|
||||
@ -722,7 +654,7 @@ const MemorySettings = () => {
|
||||
{
|
||||
key: 'reset',
|
||||
label: t('memory.reset_memories'),
|
||||
icon: <DeleteOutlined />,
|
||||
icon: <DeleteIcon size={14} className="lucide-custom" />,
|
||||
danger: true,
|
||||
onClick: () => handleResetMemories(currentUser)
|
||||
},
|
||||
@ -735,7 +667,7 @@ const MemorySettings = () => {
|
||||
{
|
||||
key: 'deleteUser',
|
||||
label: t('memory.delete_user'),
|
||||
icon: <UserDeleteOutlined />,
|
||||
icon: <UserRoundMinus size={14} className="lucide-custom" />,
|
||||
danger: true,
|
||||
onClick: () => handleDeleteUser(currentUser)
|
||||
}
|
||||
@ -745,7 +677,7 @@ const MemorySettings = () => {
|
||||
}}
|
||||
trigger={['click']}
|
||||
placement="bottomRight">
|
||||
<Button icon={<MoreOutlined />}>{t('common.more')}</Button>
|
||||
<Button icon={<MenuIcon size={16} />}>{t('common.more')}</Button>
|
||||
</Dropdown>
|
||||
</Space>
|
||||
</div>
|
||||
@ -765,7 +697,7 @@ const MemorySettings = () => {
|
||||
</div>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<PlusOutlined />}
|
||||
icon={<PlusIcon size={18} />}
|
||||
onClick={() => setAddMemoryModalVisible(true)}
|
||||
size="large">
|
||||
{t('memory.add_first_memory')}
|
||||
@ -777,7 +709,7 @@ const MemorySettings = () => {
|
||||
<>
|
||||
{loading && (
|
||||
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', minHeight: 300 }}>
|
||||
<Spin size="large" />
|
||||
<Spin indicator={<LoadingIcon color="var(--color-text-2)" />} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -792,21 +724,21 @@ const MemorySettings = () => {
|
||||
<MemoryItem key={memory.id}>
|
||||
<div className="memory-header">
|
||||
<div className="memory-meta">
|
||||
<CalendarOutlined style={{ marginRight: 4 }} />
|
||||
<Calendar size={14} style={{ marginRight: 4 }} />
|
||||
<span>{memory.createdAt ? dayjs(memory.createdAt).fromNow() : '-'}</span>
|
||||
</div>
|
||||
<Space size="small">
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
icon={<EditOutlined />}
|
||||
icon={<EditIcon size={14} />}
|
||||
onClick={() => handleEditMemory(memory)}
|
||||
/>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
danger
|
||||
icon={<DeleteOutlined />}
|
||||
icon={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
onClick={() => {
|
||||
window.modal.confirm({
|
||||
centered: true,
|
||||
|
||||
@ -0,0 +1,63 @@
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import { Avatar, Button, Select, Space, Tooltip } from 'antd'
|
||||
import { UserRoundPlus } from 'lucide-react'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { DEFAULT_USER_ID } from './constants'
|
||||
|
||||
interface UserSelectorProps {
|
||||
currentUser: string
|
||||
uniqueUsers: string[]
|
||||
onUserSwitch: (userId: string) => void
|
||||
onAddUser: () => void
|
||||
}
|
||||
|
||||
const UserSelector: React.FC<UserSelectorProps> = ({ currentUser, uniqueUsers, onUserSwitch, onAddUser }) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const getUserAvatar = useCallback((user: string) => {
|
||||
return user === DEFAULT_USER_ID ? user.slice(0, 1).toUpperCase() : user.slice(0, 2).toUpperCase()
|
||||
}, [])
|
||||
|
||||
const renderLabel = useCallback(
|
||||
(userId: string, userName: string) => {
|
||||
return (
|
||||
<HStack alignItems="center" gap={10}>
|
||||
<Avatar size={20} style={{ background: 'var(--color-primary)' }}>
|
||||
{getUserAvatar(userId)}
|
||||
</Avatar>
|
||||
<span>{userName}</span>
|
||||
</HStack>
|
||||
)
|
||||
},
|
||||
[getUserAvatar]
|
||||
)
|
||||
|
||||
const options = useMemo(() => {
|
||||
const defaultOption = {
|
||||
value: DEFAULT_USER_ID,
|
||||
label: renderLabel(DEFAULT_USER_ID, t('memory.default_user'))
|
||||
}
|
||||
|
||||
const userOptions = uniqueUsers
|
||||
.filter((user) => user !== DEFAULT_USER_ID)
|
||||
.map((user) => ({
|
||||
value: user,
|
||||
label: renderLabel(user, user)
|
||||
}))
|
||||
|
||||
return [defaultOption, ...userOptions]
|
||||
}, [renderLabel, t, uniqueUsers])
|
||||
|
||||
return (
|
||||
<Space.Compact>
|
||||
<Select value={currentUser} onChange={onUserSwitch} style={{ width: 200 }} options={options} />
|
||||
<Tooltip title={t('memory.add_new_user')}>
|
||||
<Button type="default" onClick={onAddUser} icon={<UserRoundPlus size={16} />} />
|
||||
</Tooltip>
|
||||
</Space.Compact>
|
||||
)
|
||||
}
|
||||
|
||||
export default UserSelector
|
||||
@ -0,0 +1 @@
|
||||
export const DEFAULT_USER_ID = 'default-user'
|
||||
@ -1,5 +1,6 @@
|
||||
import { CloseCircleFilled, QuestionCircleOutlined } from '@ant-design/icons'
|
||||
import EmojiPicker from '@renderer/components/EmojiPicker'
|
||||
import { ResetIcon } from '@renderer/components/Icons'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import { TopView } from '@renderer/components/TopView'
|
||||
import { DEFAULT_CONTEXTCOUNT, DEFAULT_MAX_TOKENS, DEFAULT_TEMPERATURE } from '@renderer/config/constant'
|
||||
@ -155,9 +156,9 @@ const AssistantSettings: FC = () => {
|
||||
marginTop: 0
|
||||
}}>
|
||||
{t('settings.assistant.model_params')}
|
||||
<Button onClick={onReset} style={{ width: 81 }}>
|
||||
{t('chat.settings.reset')}
|
||||
</Button>
|
||||
<Tooltip title={t('common.reset')} mouseLeaveDelay={0}>
|
||||
<Button type="text" onClick={onReset} icon={<ResetIcon size={16} />} />
|
||||
</Tooltip>
|
||||
</SettingSubtitle>
|
||||
<SettingRow>
|
||||
<HStack alignItems="center">
|
||||
|
||||
@ -85,7 +85,8 @@ const ApiOptionsSettings = ({ providerId }: Props) => {
|
||||
key: 'settings',
|
||||
styles: {
|
||||
header: {
|
||||
paddingLeft: 0
|
||||
paddingLeft: 0,
|
||||
paddingRight: 6
|
||||
},
|
||||
body: {
|
||||
padding: 0
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { CheckOutlined, CloseCircleFilled, LoadingOutlined } from '@ant-design/icons'
|
||||
import OpenAIAlert from '@renderer/components/Alert/OpenAIAlert'
|
||||
import { LoadingIcon } from '@renderer/components/Icons'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import { ModelList } from '@renderer/components/ModelList'
|
||||
import { ApiKeyListPopup } from '@renderer/components/Popups/ApiKeyListPopup'
|
||||
@ -16,7 +16,7 @@ import { formatErrorMessage } from '@renderer/utils/error'
|
||||
import { Button, Divider, Flex, Input, Space, Switch, Tooltip } from 'antd'
|
||||
import Link from 'antd/es/typography/Link'
|
||||
import { debounce, isEmpty } from 'lodash'
|
||||
import { Settings2, SquareArrowOutUpRight } from 'lucide-react'
|
||||
import { Check, Settings2, SquareArrowOutUpRight, TriangleAlert } from 'lucide-react'
|
||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -214,7 +214,7 @@ const ProviderSetting: FC<Props> = ({ providerId }) => {
|
||||
|
||||
return (
|
||||
<Tooltip title={<ErrorOverlay>{apiKeyConnectivity.error}</ErrorOverlay>}>
|
||||
<CloseCircleFilled style={{ color: 'var(--color-status-error)' }} />
|
||||
<TriangleAlert size={16} color="var(--color-status-warning)" />
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
@ -285,9 +285,9 @@ const ProviderSetting: FC<Props> = ({ providerId }) => {
|
||||
onClick={onCheckApi}
|
||||
disabled={!apiHost || apiKeyConnectivity.checking}>
|
||||
{apiKeyConnectivity.checking ? (
|
||||
<LoadingOutlined spin />
|
||||
<LoadingIcon />
|
||||
) : apiKeyConnectivity.status === 'success' ? (
|
||||
<CheckOutlined />
|
||||
<Check size={16} className="lucide-custom" />
|
||||
) : (
|
||||
t('settings.provider.check')
|
||||
)}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { DeleteOutlined, EditOutlined, PlusOutlined } from '@ant-design/icons'
|
||||
import { loggerService } from '@logger'
|
||||
import { DraggableVirtualList } from '@renderer/components/DraggableList'
|
||||
import { DeleteIcon, EditIcon } from '@renderer/components/Icons'
|
||||
import { getProviderLogo, isSystemProvider } from '@renderer/config/providers'
|
||||
import { useAllProviders, useProviders } from '@renderer/hooks/useProvider'
|
||||
import { getProviderLabel } from '@renderer/i18n/label'
|
||||
@ -15,7 +15,7 @@ import {
|
||||
uuid
|
||||
} from '@renderer/utils'
|
||||
import { Avatar, Button, Card, Dropdown, Input, MenuProps, Tag } from 'antd'
|
||||
import { Eye, EyeOff, Search, UserPen } from 'lucide-react'
|
||||
import { Eye, EyeOff, PlusIcon, Search, UserPen } from 'lucide-react'
|
||||
import { FC, startTransition, useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
@ -324,7 +324,7 @@ const ProvidersList: FC = () => {
|
||||
const editMenu = {
|
||||
label: t('common.edit'),
|
||||
key: 'edit',
|
||||
icon: <EditOutlined />,
|
||||
icon: <EditIcon size={14} />,
|
||||
async onClick() {
|
||||
const { name, type, logoFile, logo } = await AddProviderPopup.show(provider)
|
||||
|
||||
@ -362,7 +362,7 @@ const ProvidersList: FC = () => {
|
||||
const deleteMenu = {
|
||||
label: t('common.delete'),
|
||||
key: 'delete',
|
||||
icon: <DeleteOutlined />,
|
||||
icon: <DeleteIcon size={14} className="lucide-custom" />,
|
||||
danger: true,
|
||||
async onClick() {
|
||||
window.modal.confirm({
|
||||
@ -492,7 +492,7 @@ const ProvidersList: FC = () => {
|
||||
<AddButtonWrapper>
|
||||
<Button
|
||||
style={{ width: '100%', borderRadius: 'var(--list-item-border-radius)' }}
|
||||
icon={<PlusOutlined />}
|
||||
icon={<PlusIcon size={16} />}
|
||||
onClick={onAddProvider}
|
||||
disabled={dragging}>
|
||||
{t('button.add')}
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import { DeleteOutlined, EditOutlined, ExclamationCircleOutlined, PlusOutlined } from '@ant-design/icons'
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons'
|
||||
import { DraggableList } from '@renderer/components/DraggableList'
|
||||
import { DeleteIcon, EditIcon } from '@renderer/components/Icons'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import FileItem from '@renderer/pages/files/FileItem'
|
||||
import QuickPhraseService from '@renderer/services/QuickPhraseService'
|
||||
import { QuickPhrase } from '@renderer/types'
|
||||
import { Button, Flex, Input, Modal, Popconfirm, Space } from 'antd'
|
||||
import { PlusIcon } from 'lucide-react'
|
||||
import { FC, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -74,7 +76,7 @@ const QuickPhraseSettings: FC = () => {
|
||||
<SettingGroup style={{ marginBottom: 0 }} theme={theme}>
|
||||
<SettingTitle>
|
||||
{t('settings.quickPhrase.title')}
|
||||
<Button type="text" icon={<PlusOutlined />} onClick={handleAdd} />
|
||||
<Button type="text" icon={<PlusIcon size={18} />} onClick={handleAdd} />
|
||||
</SettingTitle>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
@ -94,7 +96,12 @@ const QuickPhraseSettings: FC = () => {
|
||||
extra: phrase.content,
|
||||
actions: (
|
||||
<Flex gap={4} style={{ opacity: 0.6 }}>
|
||||
<Button key="edit" type="text" icon={<EditOutlined />} onClick={() => handleEdit(phrase)} />
|
||||
<Button
|
||||
key="edit"
|
||||
type="text"
|
||||
icon={<EditIcon size={14} />}
|
||||
onClick={() => handleEdit(phrase)}
|
||||
/>
|
||||
<Popconfirm
|
||||
title={t('settings.quickPhrase.delete')}
|
||||
description={t('settings.quickPhrase.deleteConfirm')}
|
||||
@ -102,7 +109,12 @@ const QuickPhraseSettings: FC = () => {
|
||||
cancelText={t('common.cancel')}
|
||||
onConfirm={() => handleDelete(phrase.id)}
|
||||
icon={<ExclamationCircleOutlined style={{ color: 'red' }} />}>
|
||||
<Button key="delete" type="text" danger icon={<DeleteOutlined />} />
|
||||
<Button
|
||||
key="delete"
|
||||
type="text"
|
||||
danger
|
||||
icon={<DeleteIcon size={14} className="lucide-custom" />}
|
||||
/>
|
||||
</Popconfirm>
|
||||
</Flex>
|
||||
)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { LoadingOutlined } from '@ant-design/icons'
|
||||
import { CircleX, Copy, Pause, RefreshCw } from 'lucide-react'
|
||||
import { RefreshIcon } from '@renderer/components/Icons'
|
||||
import { CircleX, Copy, Pause } from 'lucide-react'
|
||||
import { FC, useEffect, useRef, useState } from 'react'
|
||||
import { useHotkeys } from 'react-hotkeys-hook'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -165,7 +166,7 @@ const WindowFooter: FC<FooterProps> = ({
|
||||
</OpButton>
|
||||
{onRegenerate && (
|
||||
<OpButton onClick={handleRegenerate} $isWindowFocus={isWindowFocus} data-hovered={isRegenerateHovered}>
|
||||
<RefreshCw size={14} className="btn-icon" />
|
||||
<RefreshIcon size={14} className="btn-icon" />
|
||||
{t('selection.action.window.r_regenerate')}
|
||||
</OpButton>
|
||||
)}
|
||||
|
||||
184
yarn.lock
184
yarn.lock
@ -84,7 +84,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ant-design/colors@npm:^7.0.0, @ant-design/colors@npm:^7.2.0":
|
||||
"@ant-design/colors@npm:^7.0.0":
|
||||
version: 7.2.0
|
||||
resolution: "@ant-design/colors@npm:7.2.0"
|
||||
dependencies:
|
||||
@ -93,6 +93,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ant-design/colors@npm:^7.2.1":
|
||||
version: 7.2.1
|
||||
resolution: "@ant-design/colors@npm:7.2.1"
|
||||
dependencies:
|
||||
"@ant-design/fast-color": "npm:^2.0.6"
|
||||
checksum: 10c0/4748a0bfb1ea98e08e29dcd4f7afd2781ae2119f783e6e9f80e889fd15fc19f7137e2a3d91f26bae2ab1ee76c04d520cc35f2bb0a708cd71e463f4d9deb4192d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ant-design/cssinjs-utils@npm:^1.1.3":
|
||||
version: 1.1.3
|
||||
resolution: "@ant-design/cssinjs-utils@npm:1.1.3"
|
||||
@ -4702,7 +4711,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@rc-component/trigger@npm:^2.0.0, @rc-component/trigger@npm:^2.1.1, @rc-component/trigger@npm:^2.2.6":
|
||||
"@rc-component/trigger@npm:^2.0.0, @rc-component/trigger@npm:^2.1.1":
|
||||
version: 2.2.6
|
||||
resolution: "@rc-component/trigger@npm:2.2.6"
|
||||
dependencies:
|
||||
@ -4719,6 +4728,23 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@rc-component/trigger@npm:^2.3.0":
|
||||
version: 2.3.0
|
||||
resolution: "@rc-component/trigger@npm:2.3.0"
|
||||
dependencies:
|
||||
"@babel/runtime": "npm:^7.23.2"
|
||||
"@rc-component/portal": "npm:^1.1.0"
|
||||
classnames: "npm:^2.3.2"
|
||||
rc-motion: "npm:^2.0.0"
|
||||
rc-resize-observer: "npm:^1.3.1"
|
||||
rc-util: "npm:^5.44.0"
|
||||
peerDependencies:
|
||||
react: ">=16.9.0"
|
||||
react-dom: ">=16.9.0"
|
||||
checksum: 10c0/84a0f3da8beca249ac86d2870ef9e1603ed26ff6b869a545e6d5c3793f23413cf6a11fafe001406a86c49917d31ec105776402dba834f1b79db98305ff8bd2f4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@reduxjs/toolkit@npm:^2.2.5":
|
||||
version: 2.6.1
|
||||
resolution: "@reduxjs/toolkit@npm:2.6.1"
|
||||
@ -7702,7 +7728,7 @@ __metadata:
|
||||
"@viz-js/lang-dot": "npm:^1.0.5"
|
||||
"@viz-js/viz": "npm:^3.14.0"
|
||||
"@xyflow/react": "npm:^12.4.4"
|
||||
antd: "patch:antd@npm%3A5.24.7#~/.yarn/patches/antd-npm-5.24.7-356a553ae5.patch"
|
||||
antd: "patch:antd@npm%3A5.26.7#~/.yarn/patches/antd-npm-5.26.7-029c5c381a.patch"
|
||||
archiver: "npm:^7.0.1"
|
||||
async-mutex: "npm:^0.5.0"
|
||||
axios: "npm:^1.7.3"
|
||||
@ -8017,11 +8043,11 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"antd@npm:5.24.7":
|
||||
version: 5.24.7
|
||||
resolution: "antd@npm:5.24.7"
|
||||
"antd@npm:5.26.7":
|
||||
version: 5.26.7
|
||||
resolution: "antd@npm:5.26.7"
|
||||
dependencies:
|
||||
"@ant-design/colors": "npm:^7.2.0"
|
||||
"@ant-design/colors": "npm:^7.2.1"
|
||||
"@ant-design/cssinjs": "npm:^1.23.0"
|
||||
"@ant-design/cssinjs-utils": "npm:^1.1.3"
|
||||
"@ant-design/fast-color": "npm:^2.0.6"
|
||||
@ -8032,56 +8058,56 @@ __metadata:
|
||||
"@rc-component/mutate-observer": "npm:^1.1.0"
|
||||
"@rc-component/qrcode": "npm:~1.0.0"
|
||||
"@rc-component/tour": "npm:~1.15.1"
|
||||
"@rc-component/trigger": "npm:^2.2.6"
|
||||
"@rc-component/trigger": "npm:^2.3.0"
|
||||
classnames: "npm:^2.5.1"
|
||||
copy-to-clipboard: "npm:^3.3.3"
|
||||
dayjs: "npm:^1.11.11"
|
||||
rc-cascader: "npm:~3.33.1"
|
||||
rc-cascader: "npm:~3.34.0"
|
||||
rc-checkbox: "npm:~3.5.0"
|
||||
rc-collapse: "npm:~3.9.0"
|
||||
rc-dialog: "npm:~9.6.0"
|
||||
rc-drawer: "npm:~7.2.0"
|
||||
rc-drawer: "npm:~7.3.0"
|
||||
rc-dropdown: "npm:~4.2.1"
|
||||
rc-field-form: "npm:~2.7.0"
|
||||
rc-image: "npm:~7.11.1"
|
||||
rc-image: "npm:~7.12.0"
|
||||
rc-input: "npm:~1.8.0"
|
||||
rc-input-number: "npm:~9.5.0"
|
||||
rc-mentions: "npm:~2.20.0"
|
||||
rc-menu: "npm:~9.16.1"
|
||||
rc-motion: "npm:^2.9.5"
|
||||
rc-notification: "npm:~5.6.3"
|
||||
rc-notification: "npm:~5.6.4"
|
||||
rc-pagination: "npm:~5.1.0"
|
||||
rc-picker: "npm:~4.11.3"
|
||||
rc-progress: "npm:~4.0.0"
|
||||
rc-rate: "npm:~2.13.1"
|
||||
rc-resize-observer: "npm:^1.4.3"
|
||||
rc-segmented: "npm:~2.7.0"
|
||||
rc-select: "npm:~14.16.6"
|
||||
rc-select: "npm:~14.16.8"
|
||||
rc-slider: "npm:~11.1.8"
|
||||
rc-steps: "npm:~6.0.1"
|
||||
rc-switch: "npm:~4.1.0"
|
||||
rc-table: "npm:~7.50.4"
|
||||
rc-tabs: "npm:~15.5.2"
|
||||
rc-textarea: "npm:~1.10.0"
|
||||
rc-table: "npm:~7.51.1"
|
||||
rc-tabs: "npm:~15.6.1"
|
||||
rc-textarea: "npm:~1.10.1"
|
||||
rc-tooltip: "npm:~6.4.0"
|
||||
rc-tree: "npm:~5.13.1"
|
||||
rc-tree-select: "npm:~5.27.0"
|
||||
rc-upload: "npm:~4.8.1"
|
||||
rc-upload: "npm:~4.9.2"
|
||||
rc-util: "npm:^5.44.4"
|
||||
scroll-into-view-if-needed: "npm:^3.1.0"
|
||||
throttle-debounce: "npm:^5.0.2"
|
||||
peerDependencies:
|
||||
react: ">=16.9.0"
|
||||
react-dom: ">=16.9.0"
|
||||
checksum: 10c0/d9b6d24cf0c74c3d22b5f799158694aba946e1971b0c1602b3319c85663b5ba6fc7b2135c91a0839d13ecd28a1643c5eb84de8a2586b8362e5a3a166c709b1ed
|
||||
checksum: 10c0/2ff4469091790986faf7ad76854c3ea9ff231df2c2ba1eed93caf93986401193a8265d3b1a4074be79a9a9705a8c823508cfbbd370c5c8db04f7dcc90895ccf5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"antd@patch:antd@npm%3A5.24.7#~/.yarn/patches/antd-npm-5.24.7-356a553ae5.patch":
|
||||
version: 5.24.7
|
||||
resolution: "antd@patch:antd@npm%3A5.24.7#~/.yarn/patches/antd-npm-5.24.7-356a553ae5.patch::version=5.24.7&hash=ff9154"
|
||||
"antd@patch:antd@npm%3A5.26.7#~/.yarn/patches/antd-npm-5.26.7-029c5c381a.patch":
|
||||
version: 5.26.7
|
||||
resolution: "antd@patch:antd@npm%3A5.26.7#~/.yarn/patches/antd-npm-5.26.7-029c5c381a.patch::version=5.26.7&hash=a9067b"
|
||||
dependencies:
|
||||
"@ant-design/colors": "npm:^7.2.0"
|
||||
"@ant-design/colors": "npm:^7.2.1"
|
||||
"@ant-design/cssinjs": "npm:^1.23.0"
|
||||
"@ant-design/cssinjs-utils": "npm:^1.1.3"
|
||||
"@ant-design/fast-color": "npm:^2.0.6"
|
||||
@ -8092,48 +8118,48 @@ __metadata:
|
||||
"@rc-component/mutate-observer": "npm:^1.1.0"
|
||||
"@rc-component/qrcode": "npm:~1.0.0"
|
||||
"@rc-component/tour": "npm:~1.15.1"
|
||||
"@rc-component/trigger": "npm:^2.2.6"
|
||||
"@rc-component/trigger": "npm:^2.3.0"
|
||||
classnames: "npm:^2.5.1"
|
||||
copy-to-clipboard: "npm:^3.3.3"
|
||||
dayjs: "npm:^1.11.11"
|
||||
rc-cascader: "npm:~3.33.1"
|
||||
rc-cascader: "npm:~3.34.0"
|
||||
rc-checkbox: "npm:~3.5.0"
|
||||
rc-collapse: "npm:~3.9.0"
|
||||
rc-dialog: "npm:~9.6.0"
|
||||
rc-drawer: "npm:~7.2.0"
|
||||
rc-drawer: "npm:~7.3.0"
|
||||
rc-dropdown: "npm:~4.2.1"
|
||||
rc-field-form: "npm:~2.7.0"
|
||||
rc-image: "npm:~7.11.1"
|
||||
rc-image: "npm:~7.12.0"
|
||||
rc-input: "npm:~1.8.0"
|
||||
rc-input-number: "npm:~9.5.0"
|
||||
rc-mentions: "npm:~2.20.0"
|
||||
rc-menu: "npm:~9.16.1"
|
||||
rc-motion: "npm:^2.9.5"
|
||||
rc-notification: "npm:~5.6.3"
|
||||
rc-notification: "npm:~5.6.4"
|
||||
rc-pagination: "npm:~5.1.0"
|
||||
rc-picker: "npm:~4.11.3"
|
||||
rc-progress: "npm:~4.0.0"
|
||||
rc-rate: "npm:~2.13.1"
|
||||
rc-resize-observer: "npm:^1.4.3"
|
||||
rc-segmented: "npm:~2.7.0"
|
||||
rc-select: "npm:~14.16.6"
|
||||
rc-select: "npm:~14.16.8"
|
||||
rc-slider: "npm:~11.1.8"
|
||||
rc-steps: "npm:~6.0.1"
|
||||
rc-switch: "npm:~4.1.0"
|
||||
rc-table: "npm:~7.50.4"
|
||||
rc-tabs: "npm:~15.5.2"
|
||||
rc-textarea: "npm:~1.10.0"
|
||||
rc-table: "npm:~7.51.1"
|
||||
rc-tabs: "npm:~15.6.1"
|
||||
rc-textarea: "npm:~1.10.1"
|
||||
rc-tooltip: "npm:~6.4.0"
|
||||
rc-tree: "npm:~5.13.1"
|
||||
rc-tree-select: "npm:~5.27.0"
|
||||
rc-upload: "npm:~4.8.1"
|
||||
rc-upload: "npm:~4.9.2"
|
||||
rc-util: "npm:^5.44.4"
|
||||
scroll-into-view-if-needed: "npm:^3.1.0"
|
||||
throttle-debounce: "npm:^5.0.2"
|
||||
peerDependencies:
|
||||
react: ">=16.9.0"
|
||||
react-dom: ">=16.9.0"
|
||||
checksum: 10c0/e46e36f151ba0f2eef1190aaf772cbe2ab947de7d832aef2d872f6a28203a134e4ee71aa6f7a7c4c57979bf1955f1b4adfae733aca06f0e740a6b54a59d45a19
|
||||
checksum: 10c0/5ac99ea57516c212b5da37bdb9ac6538ee0afa12adb9551be4215ef2be812ad79f46620042fd3a7cb94a2b6526072c5bfa1ae48be34946726fc3c03608f01e13
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -17619,9 +17645,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rc-cascader@npm:~3.33.1":
|
||||
version: 3.33.1
|
||||
resolution: "rc-cascader@npm:3.33.1"
|
||||
"rc-cascader@npm:~3.34.0":
|
||||
version: 3.34.0
|
||||
resolution: "rc-cascader@npm:3.34.0"
|
||||
dependencies:
|
||||
"@babel/runtime": "npm:^7.25.7"
|
||||
classnames: "npm:^2.3.1"
|
||||
@ -17631,7 +17657,7 @@ __metadata:
|
||||
peerDependencies:
|
||||
react: ">=16.9.0"
|
||||
react-dom: ">=16.9.0"
|
||||
checksum: 10c0/aa77ec3e5285179dfb924d08820532ac8c8ca413cbdf7a496dc11a666199f26a4c7d0f16357a1821cff776012ff93bcf0b07a9ce8dc8c45ab42567fc499fecab
|
||||
checksum: 10c0/1fc8c55e0f78ff2be59e2bcd8faa53aafecebbb28f4bb9982ad39e8f9f9620e15d6119797c7890347e46b05c32b43177ece047e81ef04c22a9f041eb0dd53e0a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -17680,9 +17706,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rc-drawer@npm:~7.2.0":
|
||||
version: 7.2.0
|
||||
resolution: "rc-drawer@npm:7.2.0"
|
||||
"rc-drawer@npm:~7.3.0":
|
||||
version: 7.3.0
|
||||
resolution: "rc-drawer@npm:7.3.0"
|
||||
dependencies:
|
||||
"@babel/runtime": "npm:^7.23.9"
|
||||
"@rc-component/portal": "npm:^1.1.1"
|
||||
@ -17692,7 +17718,7 @@ __metadata:
|
||||
peerDependencies:
|
||||
react: ">=16.9.0"
|
||||
react-dom: ">=16.9.0"
|
||||
checksum: 10c0/d6814998983100193d6a521745324a94fa8d65cbb979b2764d1d48a78d6b6e22f9d078ebb68545b68a0cc38f062298d11ed3635e93d004a60415d384330a8573
|
||||
checksum: 10c0/e2c3211d6a3790813bf2c1626cebf3fdb3a4c48ab56bee2d208ba07dd0e5058154981563e89e02571d573dd56c2ddc65db33a0cf37c58820ecc4b08785e8d169
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -17725,9 +17751,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rc-image@npm:~7.11.1":
|
||||
version: 7.11.1
|
||||
resolution: "rc-image@npm:7.11.1"
|
||||
"rc-image@npm:~7.12.0":
|
||||
version: 7.12.0
|
||||
resolution: "rc-image@npm:7.12.0"
|
||||
dependencies:
|
||||
"@babel/runtime": "npm:^7.11.2"
|
||||
"@rc-component/portal": "npm:^1.0.2"
|
||||
@ -17738,7 +17764,7 @@ __metadata:
|
||||
peerDependencies:
|
||||
react: ">=16.9.0"
|
||||
react-dom: ">=16.9.0"
|
||||
checksum: 10c0/61db982d618c3d31e99bd1be8e7b49f53feff7170a67483aa97770e686cc7e9ab4dea787f345e0f7ea5704d42f390aeaf99ffb3d7684a2b838b1f4738306eff0
|
||||
checksum: 10c0/229f848725f8cff5b6015eb0468a24a3d92c2aead48dc98abe19e6ff15840defc9b42f1a126b7f8180f678b5380ff99528bb89e972298ad456773e4070f33934
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -17821,9 +17847,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rc-notification@npm:~5.6.3":
|
||||
version: 5.6.3
|
||||
resolution: "rc-notification@npm:5.6.3"
|
||||
"rc-notification@npm:~5.6.4":
|
||||
version: 5.6.4
|
||||
resolution: "rc-notification@npm:5.6.4"
|
||||
dependencies:
|
||||
"@babel/runtime": "npm:^7.10.1"
|
||||
classnames: "npm:2.x"
|
||||
@ -17832,7 +17858,7 @@ __metadata:
|
||||
peerDependencies:
|
||||
react: ">=16.9.0"
|
||||
react-dom: ">=16.9.0"
|
||||
checksum: 10c0/33ba437ce879f28f2773c41044aca2a6fb63855eb1535b5ca79736016996bd265df3bdff536c2b111bd82b07d5a98c4b181dc7738e98baf0e129c04fd813feb0
|
||||
checksum: 10c0/ea6a587b6a6057e8e6273d642cac5608b44948374ed636c9a83d104d21731c114b43036e33add05f755ceefb3f9258b881776672d5745c0e5d19f1d66449f37a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -17953,7 +17979,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rc-select@npm:~14.16.2, rc-select@npm:~14.16.6":
|
||||
"rc-select@npm:~14.16.2":
|
||||
version: 14.16.6
|
||||
resolution: "rc-select@npm:14.16.6"
|
||||
dependencies:
|
||||
@ -17971,6 +17997,24 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rc-select@npm:~14.16.8":
|
||||
version: 14.16.8
|
||||
resolution: "rc-select@npm:14.16.8"
|
||||
dependencies:
|
||||
"@babel/runtime": "npm:^7.10.1"
|
||||
"@rc-component/trigger": "npm:^2.1.1"
|
||||
classnames: "npm:2.x"
|
||||
rc-motion: "npm:^2.0.1"
|
||||
rc-overflow: "npm:^1.3.1"
|
||||
rc-util: "npm:^5.16.1"
|
||||
rc-virtual-list: "npm:^3.5.2"
|
||||
peerDependencies:
|
||||
react: "*"
|
||||
react-dom: "*"
|
||||
checksum: 10c0/45f93e270c4b5e5ffc4b0ba0ce5e5ea72fff591a9a7a19b460b1ead0517d17327af9a4c32ce3c7f92b765724f4dabd1aa7146f5a06db73be91c884fe13c92774
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rc-slider@npm:~11.1.8":
|
||||
version: 11.1.8
|
||||
resolution: "rc-slider@npm:11.1.8"
|
||||
@ -18013,9 +18057,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rc-table@npm:~7.50.4":
|
||||
version: 7.50.4
|
||||
resolution: "rc-table@npm:7.50.4"
|
||||
"rc-table@npm:~7.51.1":
|
||||
version: 7.51.1
|
||||
resolution: "rc-table@npm:7.51.1"
|
||||
dependencies:
|
||||
"@babel/runtime": "npm:^7.10.1"
|
||||
"@rc-component/context": "npm:^1.4.0"
|
||||
@ -18026,13 +18070,13 @@ __metadata:
|
||||
peerDependencies:
|
||||
react: ">=16.9.0"
|
||||
react-dom: ">=16.9.0"
|
||||
checksum: 10c0/ab5eb3db00bc31470d7dd5946c1a919247742703a3278ea2d9a33e719a08e170ca80977e615084c7cfcb54508a9c3da2449409cce16fc1d7ec1ea67596c30d79
|
||||
checksum: 10c0/ba6b25b7ff5555c059bdd8d504846839a786eb3eb5701b0ac648fb65e8197ed5a9d046d06881df19f6b1fbe014097f7260cc9e1c25c7644278cc6a53c71198fb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rc-tabs@npm:~15.5.2":
|
||||
version: 15.5.2
|
||||
resolution: "rc-tabs@npm:15.5.2"
|
||||
"rc-tabs@npm:~15.6.1":
|
||||
version: 15.6.1
|
||||
resolution: "rc-tabs@npm:15.6.1"
|
||||
dependencies:
|
||||
"@babel/runtime": "npm:^7.11.2"
|
||||
classnames: "npm:2.x"
|
||||
@ -18044,7 +18088,7 @@ __metadata:
|
||||
peerDependencies:
|
||||
react: ">=16.9.0"
|
||||
react-dom: ">=16.9.0"
|
||||
checksum: 10c0/59b66c809da92b3d6943020bc71ce1702f9c92c59ca48d6922aaa739bec20796f96c9ce37fd8ef0553c21e312db7a51b1ab700c6b7993761727951386276585a
|
||||
checksum: 10c0/b982582902684eae5ec1783af4de1d31bd8c8fc7419dec3abd883abfa51d7a270db01a73bc579341fc84b0c8a92fc2cbd0e8ed272ce31b4ea2ac5979eaf5215c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -18064,6 +18108,22 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rc-textarea@npm:~1.10.1":
|
||||
version: 1.10.2
|
||||
resolution: "rc-textarea@npm:1.10.2"
|
||||
dependencies:
|
||||
"@babel/runtime": "npm:^7.10.1"
|
||||
classnames: "npm:^2.2.1"
|
||||
rc-input: "npm:~1.8.0"
|
||||
rc-resize-observer: "npm:^1.0.0"
|
||||
rc-util: "npm:^5.27.0"
|
||||
peerDependencies:
|
||||
react: ">=16.9.0"
|
||||
react-dom: ">=16.9.0"
|
||||
checksum: 10c0/ccfe7bae33187c382e12bc14e9f2617fe183a4d4e8c0d3b9f71455728172f31a6140d0855ff557b6c658daf31c7ff935a1a347a336f8106ddda84e042ab23448
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rc-tooltip@npm:~6.4.0":
|
||||
version: 6.4.0
|
||||
resolution: "rc-tooltip@npm:6.4.0"
|
||||
@ -18111,9 +18171,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rc-upload@npm:~4.8.1":
|
||||
version: 4.8.1
|
||||
resolution: "rc-upload@npm:4.8.1"
|
||||
"rc-upload@npm:~4.9.2":
|
||||
version: 4.9.2
|
||||
resolution: "rc-upload@npm:4.9.2"
|
||||
dependencies:
|
||||
"@babel/runtime": "npm:^7.18.3"
|
||||
classnames: "npm:^2.2.5"
|
||||
@ -18121,7 +18181,7 @@ __metadata:
|
||||
peerDependencies:
|
||||
react: ">=16.9.0"
|
||||
react-dom: ">=16.9.0"
|
||||
checksum: 10c0/27555e114c1705b88558312beeda4b8d3e74d192c09f5a41d161045cbe621d372973acaffff8b9c79ebfe495962e2bf96aedffc9fadc96b5e7c7b5cd1af98b99
|
||||
checksum: 10c0/2299f4a3d8fa87449178761fcdc3c574b21e34d2f6816ecb6c08729f699e67b23d1284f4077b9ceceb1cc8502d7c350311bc2d1dfacec7f6780d2bf9691888cb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user