feat: new icon style
This commit is contained in:
parent
39c614e4db
commit
5f7d8652bc
@ -87,12 +87,10 @@
|
||||
"fs-extra": "^11.2.0",
|
||||
"got-scraping": "^4.1.1",
|
||||
"jsdom": "^26.0.0",
|
||||
"lucide-react": "^0.487.0",
|
||||
"markdown-it": "^14.1.0",
|
||||
"officeparser": "^4.1.1",
|
||||
"proxy-agent": "^6.5.0",
|
||||
"tar": "^7.4.3",
|
||||
"tiny-pinyin": "^1.3.2",
|
||||
"turndown": "^7.2.0",
|
||||
"turndown-plugin-gfm": "^1.0.2",
|
||||
"undici": "^7.4.0",
|
||||
@ -161,6 +159,7 @@
|
||||
"lint-staged": "^15.5.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lru-cache": "^11.1.0",
|
||||
"lucide-react": "^0.487.0",
|
||||
"mime": "^4.0.4",
|
||||
"npx-scope-finder": "^1.2.0",
|
||||
"openai": "patch:openai@npm%3A4.87.3#~/.yarn/patches/openai-npm-4.87.3-2b30a7685f.patch",
|
||||
@ -190,6 +189,7 @@
|
||||
"shiki": "^3.2.1",
|
||||
"string-width": "^7.2.0",
|
||||
"styled-components": "^6.1.11",
|
||||
"tiny-pinyin": "^1.3.2",
|
||||
"tinycolor2": "^1.6.0",
|
||||
"tokenx": "^0.4.1",
|
||||
"typescript": "^5.6.2",
|
||||
|
||||
@ -281,3 +281,7 @@ body,
|
||||
color: var(--color-text);
|
||||
}
|
||||
}
|
||||
|
||||
.lucide {
|
||||
color: var(--color-icon);
|
||||
}
|
||||
|
||||
@ -52,7 +52,7 @@ const ListItemContainer = styled.div`
|
||||
const ListItemContent = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
gap: 2px;
|
||||
overflow: hidden;
|
||||
font-size: 13px;
|
||||
`
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { SearchOutlined } from '@ant-design/icons'
|
||||
import { TopView } from '@renderer/components/TopView'
|
||||
import { useAgents } from '@renderer/hooks/useAgents'
|
||||
import { useAssistants, useDefaultAssistant } from '@renderer/hooks/useAssistant'
|
||||
@ -9,6 +8,7 @@ import { Agent, Assistant } from '@renderer/types'
|
||||
import { uuid } from '@renderer/utils'
|
||||
import { Divider, Input, InputRef, Modal, Tag } from 'antd'
|
||||
import { take } from 'lodash'
|
||||
import { Search } from 'lucide-react'
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -163,7 +163,7 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
<Input
|
||||
prefix={
|
||||
<SearchIcon>
|
||||
<SearchOutlined />
|
||||
<Search size={14} />
|
||||
</SearchIcon>
|
||||
}
|
||||
ref={inputRef}
|
||||
@ -177,7 +177,7 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
size="middle"
|
||||
/>
|
||||
</HStack>
|
||||
<Divider style={{ margin: 0, borderBlockStartWidth: 0.5 }} />
|
||||
<Divider style={{ margin: 0, marginTop: 4, borderBlockStartWidth: 0.5 }} />
|
||||
<Container ref={containerRef}>
|
||||
{take(agents, 100).map((agent, index) => (
|
||||
<AgentItem
|
||||
@ -237,8 +237,8 @@ const AgentItem = styled.div`
|
||||
`
|
||||
|
||||
const SearchIcon = styled.div`
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { PushpinOutlined, SearchOutlined } from '@ant-design/icons'
|
||||
import { PushpinOutlined } from '@ant-design/icons'
|
||||
import { TopView } from '@renderer/components/TopView'
|
||||
import { getModelLogo, isEmbeddingModel, isRerankModel } from '@renderer/config/models'
|
||||
import db from '@renderer/databases'
|
||||
@ -7,6 +7,7 @@ import { getModelUniqId } from '@renderer/services/ModelService'
|
||||
import { Model } from '@renderer/types'
|
||||
import { Avatar, Divider, Empty, Input, InputRef, Menu, MenuProps, Modal } from 'antd'
|
||||
import { first, sortBy } from 'lodash'
|
||||
import { Search } from 'lucide-react'
|
||||
import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -383,7 +384,7 @@ const PopupContainer: React.FC<PopupContainerProps> = ({ model, resolve }) => {
|
||||
<Input
|
||||
prefix={
|
||||
<SearchIcon>
|
||||
<SearchOutlined />
|
||||
<Search size={15} />
|
||||
</SearchIcon>
|
||||
}
|
||||
ref={inputRef}
|
||||
@ -403,7 +404,7 @@ const PopupContainer: React.FC<PopupContainerProps> = ({ model, resolve }) => {
|
||||
}}
|
||||
/>
|
||||
</HStack>
|
||||
<Divider style={{ margin: 0, borderBlockStartWidth: 0.5 }} />
|
||||
<Divider style={{ margin: 0, marginTop: 4, borderBlockStartWidth: 0.5 }} />
|
||||
<Scrollbar style={{ height: '50vh' }} ref={scrollContainerRef}>
|
||||
<Container>
|
||||
{processedItems.length > 0 ? (
|
||||
@ -510,8 +511,8 @@ const EmptyState = styled.div`
|
||||
`
|
||||
|
||||
const SearchIcon = styled.div`
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
@ -603,6 +603,7 @@ const QuickPanelItem = styled.div`
|
||||
cursor: pointer;
|
||||
transition: background-color 0.1s ease;
|
||||
margin-bottom: 1px;
|
||||
font-family: Ubuntu;
|
||||
&.selected {
|
||||
background-color: var(--selected-color);
|
||||
&.focused {
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import { LoadingOutlined, TranslationOutlined } from '@ant-design/icons'
|
||||
import { LoadingOutlined } from '@ant-design/icons'
|
||||
import { useDefaultModel } from '@renderer/hooks/useAssistant'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { fetchTranslate } from '@renderer/services/ApiService'
|
||||
import { getDefaultTopic, getDefaultTranslateAssistant } from '@renderer/services/AssistantService'
|
||||
import { getUserMessage } from '@renderer/services/MessagesService'
|
||||
import { Button, Tooltip } from 'antd'
|
||||
import { Languages } from 'lucide-react'
|
||||
import { FC, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -82,7 +83,7 @@ const TranslateButton: FC<Props> = ({ text, onTranslated, disabled, style, isLoa
|
||||
title={t('chat.input.translate', { target_language: t(`languages.${targetLanguage.toString()}`) })}
|
||||
arrow>
|
||||
<ToolbarButton onClick={handleTranslate} disabled={disabled || isTranslating} style={style} type="text">
|
||||
{isTranslating ? <LoadingOutlined spin /> : <TranslationOutlined />}
|
||||
{isTranslating ? <LoadingOutlined spin /> : <Languages size={18} />}
|
||||
</ToolbarButton>
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
@ -1,10 +1,3 @@
|
||||
import {
|
||||
FileSearchOutlined,
|
||||
FolderOutlined,
|
||||
PictureOutlined,
|
||||
QuestionCircleOutlined,
|
||||
TranslationOutlined
|
||||
} from '@ant-design/icons'
|
||||
import { isMac } from '@renderer/config/constant'
|
||||
import { AppLogo, UserAvatar } from '@renderer/config/env'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
@ -17,6 +10,19 @@ import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { isEmoji } from '@renderer/utils'
|
||||
import type { MenuProps } from 'antd'
|
||||
import { Avatar, Dropdown, Tooltip } from 'antd'
|
||||
import {
|
||||
CircleHelp,
|
||||
Folder,
|
||||
Languages,
|
||||
LayoutGrid,
|
||||
LibraryBig,
|
||||
MessageSquareQuote,
|
||||
Moon,
|
||||
Palette,
|
||||
Settings,
|
||||
Sparkle,
|
||||
Sun
|
||||
} from 'lucide-react'
|
||||
import { FC, useEffect } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useLocation, useNavigate } from 'react-router-dom'
|
||||
@ -84,7 +90,7 @@ const Sidebar: FC = () => {
|
||||
<Menus>
|
||||
<Tooltip title={t('docs.title')} mouseEnterDelay={0.8} placement="right">
|
||||
<Icon theme={theme} onClick={onOpenDocs} className={minappShow && currentMinappId === docsId ? 'active' : ''}>
|
||||
<QuestionCircleOutlined />
|
||||
<CircleHelp size={20} />
|
||||
</Icon>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
@ -92,22 +98,17 @@ const Sidebar: FC = () => {
|
||||
mouseEnterDelay={0.8}
|
||||
placement="right">
|
||||
<Icon theme={theme} onClick={() => toggleTheme()}>
|
||||
{theme === 'dark' ? (
|
||||
<i className="iconfont icon-theme icon-dark1" />
|
||||
) : (
|
||||
<i className="iconfont icon-theme icon-theme-light" />
|
||||
)}
|
||||
{theme === 'dark' ? <Moon size={20} /> : <Sun size={20} />}
|
||||
</Icon>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('settings.title')} mouseEnterDelay={0.8} placement="right">
|
||||
<StyledLink
|
||||
onClick={async () => {
|
||||
hideMinappPopup()
|
||||
await modelGenerating()
|
||||
await to('/settings/provider')
|
||||
}}>
|
||||
<Icon theme={theme} className={pathname.startsWith('/settings') && !minappShow ? 'active' : ''}>
|
||||
<i className="iconfont icon-setting" />
|
||||
<Settings size={20} />
|
||||
</Icon>
|
||||
</StyledLink>
|
||||
</Tooltip>
|
||||
@ -129,13 +130,13 @@ const MainMenus: FC = () => {
|
||||
const isRoutes = (path: string): string => (pathname.startsWith(path) && !minappShow ? 'active' : '')
|
||||
|
||||
const iconMap = {
|
||||
assistants: <i className="iconfont icon-chat" />,
|
||||
agents: <i className="iconfont icon-business-smart-assistant" />,
|
||||
paintings: <PictureOutlined style={{ fontSize: 16 }} />,
|
||||
translate: <TranslationOutlined />,
|
||||
minapp: <i className="iconfont icon-appstore" />,
|
||||
knowledge: <FileSearchOutlined />,
|
||||
files: <FolderOutlined />
|
||||
assistants: <MessageSquareQuote size={18} />,
|
||||
agents: <Sparkle size={18} />,
|
||||
paintings: <Palette size={18} />,
|
||||
translate: <Languages size={18} />,
|
||||
minapp: <LayoutGrid size={18} />,
|
||||
knowledge: <LibraryBig size={18} />,
|
||||
files: <Folder size={17} />
|
||||
}
|
||||
|
||||
const pathMap = {
|
||||
|
||||
@ -33,7 +33,11 @@ const AntdProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||
boxShadowSecondary: 'none',
|
||||
defaultShadow: 'none',
|
||||
dangerShadow: 'none',
|
||||
primaryShadow: 'none'
|
||||
primaryShadow: 'none',
|
||||
borderRadius: 20
|
||||
},
|
||||
Select: {
|
||||
borderRadius: 20
|
||||
}
|
||||
},
|
||||
token: {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { PlusOutlined, SearchOutlined } from '@ant-design/icons'
|
||||
import { PlusOutlined } from '@ant-design/icons'
|
||||
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
||||
import CustomTag from '@renderer/components/CustomTag'
|
||||
import ListItem from '@renderer/components/ListItem'
|
||||
@ -9,6 +9,7 @@ import { Agent } from '@renderer/types'
|
||||
import { uuid } from '@renderer/utils'
|
||||
import { Button, Empty, Flex, Input } from 'antd'
|
||||
import { omit } from 'lodash'
|
||||
import { Search } from 'lucide-react'
|
||||
import { FC, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
@ -150,7 +151,7 @@ const AgentsPage: FC = () => {
|
||||
variant="filled"
|
||||
allowClear
|
||||
onClear={handleSearchClear}
|
||||
suffix={<SearchOutlined onClick={handleSearch} />}
|
||||
suffix={<Search size={14} color="var(--color-icon)" onClick={handleSearch} />}
|
||||
value={searchInput}
|
||||
maxLength={50}
|
||||
onChange={(e) => setSearchInput(e.target.value)}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { SearchOutlined } from '@ant-design/icons'
|
||||
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
||||
import { Center } from '@renderer/components/Layout'
|
||||
import { useMinapps } from '@renderer/hooks/useMinapps'
|
||||
import { Empty, Input } from 'antd'
|
||||
import { isEmpty } from 'lodash'
|
||||
import { Search } from 'lucide-react'
|
||||
import React, { FC, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -40,10 +40,10 @@ const AppsPage: FC = () => {
|
||||
<Input
|
||||
placeholder={t('common.search')}
|
||||
className="nodrag"
|
||||
style={{ width: '30%', height: 28 }}
|
||||
style={{ width: '30%', height: 28, borderRadius: 15 }}
|
||||
size="small"
|
||||
variant="filled"
|
||||
suffix={<SearchOutlined />}
|
||||
suffix={<Search size={18} />}
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
/>
|
||||
|
||||
@ -2,24 +2,21 @@ import {
|
||||
DeleteOutlined,
|
||||
EditOutlined,
|
||||
ExclamationCircleOutlined,
|
||||
FileImageOutlined,
|
||||
FilePdfOutlined,
|
||||
FileTextOutlined,
|
||||
SortAscendingOutlined,
|
||||
SortDescendingOutlined
|
||||
} from '@ant-design/icons'
|
||||
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
||||
import ListItem from '@renderer/components/ListItem'
|
||||
import TextEditPopup from '@renderer/components/Popups/TextEditPopup'
|
||||
import db from '@renderer/databases'
|
||||
import { useProviders } from '@renderer/hooks/useProvider'
|
||||
import FileManager from '@renderer/services/FileManager'
|
||||
import store from '@renderer/store'
|
||||
import { FileType, FileTypes } from '@renderer/types'
|
||||
import { formatFileSize } from '@renderer/utils'
|
||||
import type { MenuProps } from 'antd'
|
||||
import { Button, Empty, Flex, Menu, Popconfirm } from 'antd'
|
||||
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 { FC, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -34,9 +31,6 @@ const FilesPage: FC = () => {
|
||||
const [fileType, setFileType] = useState<string>('document')
|
||||
const [sortField, setSortField] = useState<SortField>('created_at')
|
||||
const [sortOrder, setSortOrder] = useState<SortOrder>('desc')
|
||||
const { providers } = useProviders()
|
||||
|
||||
const geminiProviders = providers.filter((provider) => provider.type === 'gemini')
|
||||
|
||||
const tempFilesSort = (files: FileType[]) => {
|
||||
return files.sort((a, b) => {
|
||||
@ -144,16 +138,11 @@ const FilesPage: FC = () => {
|
||||
})
|
||||
|
||||
const menuItems = [
|
||||
{ key: FileTypes.DOCUMENT, label: t('files.document'), icon: <FilePdfOutlined /> },
|
||||
{ key: FileTypes.IMAGE, label: t('files.image'), icon: <FileImageOutlined /> },
|
||||
{ key: FileTypes.TEXT, label: t('files.text'), icon: <FileTextOutlined /> },
|
||||
...geminiProviders.map((provider) => ({
|
||||
key: 'gemini_' + provider.id,
|
||||
label: provider.name,
|
||||
icon: <FilePdfOutlined />
|
||||
})),
|
||||
{ key: 'all', label: t('files.all'), icon: <FileTextOutlined /> }
|
||||
].filter(Boolean) as MenuProps['items']
|
||||
{ key: FileTypes.DOCUMENT, label: t('files.document'), icon: <FileIcon size={16} /> },
|
||||
{ key: FileTypes.IMAGE, label: t('files.image'), icon: <FileImage size={16} /> },
|
||||
{ key: FileTypes.TEXT, label: t('files.text'), icon: <FileTypeIcon size={16} /> },
|
||||
{ key: 'all', label: t('files.all'), icon: <FileText size={16} /> }
|
||||
]
|
||||
|
||||
return (
|
||||
<Container>
|
||||
@ -162,7 +151,15 @@ const FilesPage: FC = () => {
|
||||
</Navbar>
|
||||
<ContentContainer id="content-container">
|
||||
<SideNav>
|
||||
<Menu selectedKeys={[fileType]} items={menuItems} onSelect={({ key }) => setFileType(key as FileTypes)} />
|
||||
{menuItems.map((item) => (
|
||||
<ListItem
|
||||
key={item.key}
|
||||
icon={item.icon}
|
||||
title={item.label}
|
||||
active={fileType === item.key}
|
||||
onClick={() => setFileType(item.key as FileTypes)}
|
||||
/>
|
||||
))}
|
||||
</SideNav>
|
||||
<MainContent>
|
||||
<SortContainer>
|
||||
@ -223,10 +220,13 @@ const ContentContainer = styled.div`
|
||||
`
|
||||
|
||||
const SideNav = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: var(--settings-width);
|
||||
border-right: 0.5px solid var(--color-border);
|
||||
padding: 7px 12px;
|
||||
padding: 12px 10px;
|
||||
user-select: none;
|
||||
gap: 6px;
|
||||
|
||||
.ant-menu {
|
||||
border-inline-end: none !important;
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { ArrowLeftOutlined, EnterOutlined, SearchOutlined } from '@ant-design/icons'
|
||||
import { ArrowLeftOutlined, EnterOutlined } from '@ant-design/icons'
|
||||
import { Message, Topic } from '@renderer/types'
|
||||
import { Input, InputRef } from 'antd'
|
||||
import { last } from 'lodash'
|
||||
import { Search } from 'lucide-react'
|
||||
import { FC, useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -83,7 +84,7 @@ const TopicsPage: FC = () => {
|
||||
allowClear
|
||||
ref={inputRef}
|
||||
onChange={(e) => setSearch(e.target.value.trimStart())}
|
||||
suffix={search.length >= 2 ? <EnterOutlined /> : <SearchOutlined />}
|
||||
suffix={search.length >= 2 ? <EnterOutlined /> : <Search size={16} />}
|
||||
onPressEnter={onSearch}
|
||||
/>
|
||||
</Header>
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { PaperClipOutlined } from '@ant-design/icons'
|
||||
import { isVisionModel } from '@renderer/config/models'
|
||||
import { FileType, Model } from '@renderer/types'
|
||||
import { documentExts, imageExts, textExts } from '@shared/config/constant'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Paperclip } from 'lucide-react'
|
||||
import { FC, useCallback, useImperativeHandle, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@ -57,9 +57,7 @@ const AttachmentButton: FC<Props> = ({ ref, model, files, setFiles, ToolbarButto
|
||||
title={isVisionModel(model) ? t('chat.input.upload') : t('chat.input.upload.document')}
|
||||
arrow>
|
||||
<ToolbarButton type="text" onClick={onSelectFile} disabled={disabled}>
|
||||
<PaperClipOutlined
|
||||
style={{ fontSize: 17, color: files.length ? 'var(--color-primary)' : 'var(--color-icon)' }}
|
||||
/>
|
||||
<Paperclip size={18} style={{ color: files.length ? 'var(--color-primary)' : 'var(--color-icon)' }} />
|
||||
</ToolbarButton>
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { PictureOutlined } from '@ant-design/icons'
|
||||
import { isGenerateImageModel } from '@renderer/config/models'
|
||||
import { Assistant, Model } from '@renderer/types'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Image } from 'lucide-react'
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@ -27,7 +27,7 @@ const GenerateImageButton: FC<Props> = ({ model, ToolbarButton, assistant, onEna
|
||||
}
|
||||
arrow>
|
||||
<ToolbarButton type="text" disabled={!isGenerateImageModel(model)} onClick={onEnableGenerateImage}>
|
||||
<PictureOutlined style={{ color: assistant.enableGenerateImage ? 'var(--color-link)' : 'var(--color-icon)' }} />
|
||||
<Image size={18} color={assistant.enableGenerateImage ? 'var(--color-link)' : 'var(--color-icon)'} />
|
||||
</ToolbarButton>
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
@ -1,11 +1,6 @@
|
||||
import {
|
||||
ClearOutlined,
|
||||
CodeOutlined,
|
||||
FileSearchOutlined,
|
||||
FormOutlined,
|
||||
FullscreenExitOutlined,
|
||||
FullscreenOutlined,
|
||||
GlobalOutlined,
|
||||
HolderOutlined,
|
||||
PaperClipOutlined,
|
||||
PauseCircleOutlined,
|
||||
@ -44,6 +39,7 @@ import TextArea, { TextAreaRef } from 'antd/es/input/TextArea'
|
||||
import dayjs from 'dayjs'
|
||||
import Logger from 'electron-log/renderer'
|
||||
import { debounce, isEmpty } from 'lodash'
|
||||
import { Globe, Maximize, MessageSquareDiff, Minimize, PaintbrushVertical } from 'lucide-react'
|
||||
import React, { CSSProperties, FC, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
@ -935,7 +931,7 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
<ToolbarMenu>
|
||||
<Tooltip placement="top" title={t('chat.input.new_topic', { Command: newTopicShortcut })} arrow>
|
||||
<ToolbarButton type="text" onClick={addNewTopic}>
|
||||
<FormOutlined />
|
||||
<MessageSquareDiff size={18} />
|
||||
</ToolbarButton>
|
||||
</Tooltip>
|
||||
<AttachmentButton
|
||||
@ -947,7 +943,8 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
/>
|
||||
<Tooltip placement="top" title={t('chat.input.web_search')} arrow>
|
||||
<ToolbarButton type="text" onClick={onEnableWebSearch}>
|
||||
<GlobalOutlined
|
||||
<Globe
|
||||
size={18}
|
||||
style={{ color: assistant.enableWebSearch ? 'var(--color-link)' : 'var(--color-icon)' }}
|
||||
/>
|
||||
</ToolbarButton>
|
||||
@ -989,12 +986,12 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
/>
|
||||
<Tooltip placement="top" title={t('chat.input.clear', { Command: cleanTopicShortcut })} arrow>
|
||||
<ToolbarButton type="text" onClick={clearTopic}>
|
||||
<ClearOutlined style={{ fontSize: 17 }} />
|
||||
<PaintbrushVertical size={18} />
|
||||
</ToolbarButton>
|
||||
</Tooltip>
|
||||
<Tooltip placement="top" title={isExpended ? t('chat.input.collapse') : t('chat.input.expand')} arrow>
|
||||
<ToolbarButton type="text" onClick={onToggleExpended}>
|
||||
{isExpended ? <FullscreenExitOutlined /> : <FullscreenOutlined />}
|
||||
{isExpended ? <Minimize size={18} /> : <Maximize size={18} />}
|
||||
</ToolbarButton>
|
||||
</Tooltip>
|
||||
<NewContextButton onNewContext={onNewContext} ToolbarButton={ToolbarButton} />
|
||||
|
||||
@ -4,6 +4,7 @@ import { QuickPanelListItem, useQuickPanel } from '@renderer/components/QuickPan
|
||||
import { useAppSelector } from '@renderer/store'
|
||||
import { KnowledgeBase } from '@renderer/types'
|
||||
import { Tooltip } from 'antd'
|
||||
import { LibraryBig } from 'lucide-react'
|
||||
import { FC, useCallback, useEffect, useImperativeHandle, useMemo, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useNavigate } from 'react-router'
|
||||
@ -88,7 +89,7 @@ const KnowledgeBaseButton: FC<Props> = ({ ref, selectedBases, onSelect, disabled
|
||||
return (
|
||||
<Tooltip placement="top" title={t('chat.input.knowledge_base')} arrow>
|
||||
<ToolbarButton type="text" onClick={handleOpenQuickPanel} disabled={disabled}>
|
||||
<FileSearchOutlined />
|
||||
<LibraryBig size={18} />
|
||||
</ToolbarButton>
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
@ -3,6 +3,7 @@ import { QuickPanelListItem, useQuickPanel } from '@renderer/components/QuickPan
|
||||
import { useMCPServers } from '@renderer/hooks/useMCPServers'
|
||||
import { MCPPrompt, MCPServer } from '@renderer/types'
|
||||
import { Form, Input, Modal, Tooltip } from 'antd'
|
||||
import { SquareTerminal } from 'lucide-react'
|
||||
import { FC, useCallback, useImperativeHandle, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useNavigate } from 'react-router'
|
||||
@ -303,7 +304,7 @@ const MCPToolsButton: FC<Props> = ({
|
||||
return (
|
||||
<Tooltip placement="top" title={t('settings.mcp.title')} arrow>
|
||||
<ToolbarButton type="text" onClick={handleOpenQuickPanel}>
|
||||
<CodeOutlined style={{ color: buttonEnabled ? 'var(--color-primary)' : 'var(--color-icon)' }} />
|
||||
<SquareTerminal size={18} color={buttonEnabled ? 'var(--color-primary)' : 'var(--color-icon)'} />
|
||||
</ToolbarButton>
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
@ -9,6 +9,7 @@ import { getModelUniqId } from '@renderer/services/ModelService'
|
||||
import { Model } from '@renderer/types'
|
||||
import { Avatar, Tooltip } from 'antd'
|
||||
import { first, sortBy } from 'lodash'
|
||||
import { AtSign } from 'lucide-react'
|
||||
import { FC, useCallback, useEffect, useImperativeHandle, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useNavigate } from 'react-router'
|
||||
@ -104,7 +105,7 @@ const MentionModelsButton: FC<Props> = ({ ref, mentionModels, onMentionModel, To
|
||||
return (
|
||||
<Tooltip placement="top" title={t('agents.edit.model.select.title')} arrow>
|
||||
<ToolbarButton type="text" onClick={handleOpenQuickPanel}>
|
||||
<i className="iconfont icon-at" style={{ fontSize: 18 }}></i>
|
||||
<AtSign size={18} />
|
||||
</ToolbarButton>
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { PicCenterOutlined } from '@ant-design/icons'
|
||||
import { useShortcut, useShortcutDisplay } from '@renderer/hooks/useShortcuts'
|
||||
import { Tooltip } from 'antd'
|
||||
import { CircleFadingPlus } from 'lucide-react'
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -20,7 +20,7 @@ const NewContextButton: FC<Props> = ({ onNewContext, ToolbarButton }) => {
|
||||
<Container>
|
||||
<Tooltip placement="top" title={t('chat.input.new.context', { Command: newContextShortcut })} arrow>
|
||||
<ToolbarButton type="text" onClick={onNewContext}>
|
||||
<PicCenterOutlined />
|
||||
<CircleFadingPlus size={18} />
|
||||
</ToolbarButton>
|
||||
</Tooltip>
|
||||
</Container>
|
||||
|
||||
@ -4,6 +4,7 @@ import { QuickPanelListItem, QuickPanelOpenOptions } from '@renderer/components/
|
||||
import QuickPhraseService from '@renderer/services/QuickPhraseService'
|
||||
import { QuickPhrase } from '@renderer/types'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Zap } from 'lucide-react'
|
||||
import { memo, useCallback, useEffect, useImperativeHandle, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useNavigate } from 'react-router'
|
||||
@ -99,7 +100,7 @@ const QuickPhrasesButton = ({ ref, setInputValue, resizeTextArea, ToolbarButton
|
||||
return (
|
||||
<Tooltip placement="top" title={t('settings.quickPhrase.title')} arrow>
|
||||
<ToolbarButton type="text" onClick={handleOpenQuickPanel}>
|
||||
<ThunderboltOutlined />
|
||||
<Zap size={18} />
|
||||
</ToolbarButton>
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { SearchOutlined, SyncOutlined, TranslationOutlined } from '@ant-design/icons'
|
||||
import { SyncOutlined, TranslationOutlined } from '@ant-design/icons'
|
||||
import { isOpenAIWebSearch } from '@renderer/config/models'
|
||||
import { getModelUniqId } from '@renderer/services/ModelService'
|
||||
import { Message, Model } from '@renderer/types'
|
||||
@ -6,6 +6,7 @@ import { getBriefInfo } from '@renderer/utils'
|
||||
import { withMessageThought } from '@renderer/utils/formats'
|
||||
import { Divider, Flex } from 'antd'
|
||||
import { clone } from 'lodash'
|
||||
import { Search } from 'lucide-react'
|
||||
import React, { Fragment, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import BarLoader from 'react-spinners/BarLoader'
|
||||
@ -182,7 +183,7 @@ const MessageContent: React.FC<Props> = ({ message: _message, model }) => {
|
||||
if (message.status === 'searching') {
|
||||
return (
|
||||
<SearchingContainer>
|
||||
<SearchOutlined size={24} />
|
||||
<Search size={24} />
|
||||
<SearchingText>{t('message.searching')}</SearchingText>
|
||||
<BarLoader color="#1677ff" />
|
||||
</SearchingContainer>
|
||||
|
||||
@ -1,17 +1,4 @@
|
||||
import {
|
||||
CheckOutlined,
|
||||
DeleteOutlined,
|
||||
EditOutlined,
|
||||
ForkOutlined,
|
||||
LikeFilled,
|
||||
LikeOutlined,
|
||||
MenuOutlined,
|
||||
QuestionCircleOutlined,
|
||||
SaveOutlined,
|
||||
SyncOutlined,
|
||||
TranslationOutlined
|
||||
} from '@ant-design/icons'
|
||||
import { UploadOutlined } from '@ant-design/icons'
|
||||
import { CheckOutlined, EditOutlined, QuestionCircleOutlined, SyncOutlined } from '@ant-design/icons'
|
||||
import ObsidianExportPopup from '@renderer/components/Popups/ObsidianExportPopup'
|
||||
import SelectModelPopup from '@renderer/components/Popups/SelectModelPopup'
|
||||
import TextEditPopup from '@renderer/components/Popups/TextEditPopup'
|
||||
@ -37,6 +24,20 @@ import { withMessageThought } from '@renderer/utils/formats'
|
||||
import { Button, Dropdown, Popconfirm, Tooltip } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { clone } from 'lodash'
|
||||
import {
|
||||
AtSign,
|
||||
Copy,
|
||||
FilePenLine,
|
||||
Languages,
|
||||
Menu,
|
||||
RefreshCw,
|
||||
Save,
|
||||
Share,
|
||||
Split,
|
||||
ThumbsDown,
|
||||
ThumbsUp,
|
||||
Trash
|
||||
} from 'lucide-react'
|
||||
import { FC, memo, useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useSelector } from 'react-redux'
|
||||
@ -159,24 +160,31 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
content: content.trim(),
|
||||
metadata: {
|
||||
...message.metadata,
|
||||
generateImage: imageUrls.length > 0 ? {
|
||||
type: 'url',
|
||||
images: imageUrls
|
||||
} : undefined
|
||||
generateImage:
|
||||
imageUrls.length > 0
|
||||
? {
|
||||
type: 'url',
|
||||
images: imageUrls
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
})
|
||||
|
||||
resendMessage && handleResendUserMessage({
|
||||
...message,
|
||||
content: content.trim(),
|
||||
metadata: {
|
||||
...message.metadata,
|
||||
generateImage: imageUrls.length > 0 ? {
|
||||
type: 'url',
|
||||
images: imageUrls
|
||||
} : undefined
|
||||
}
|
||||
})
|
||||
resendMessage &&
|
||||
handleResendUserMessage({
|
||||
...message,
|
||||
content: content.trim(),
|
||||
metadata: {
|
||||
...message.metadata,
|
||||
generateImage:
|
||||
imageUrls.length > 0
|
||||
? {
|
||||
type: 'url',
|
||||
images: imageUrls
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
})
|
||||
}
|
||||
}, [message, editMessage, handleResendUserMessage, t])
|
||||
|
||||
@ -213,18 +221,28 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
{
|
||||
label: t('chat.save'),
|
||||
key: 'save',
|
||||
icon: <SaveOutlined />,
|
||||
icon: <Save size={16} />,
|
||||
onClick: () => {
|
||||
const fileName = dayjs(message.createdAt).format('YYYYMMDDHHmm') + '.md'
|
||||
window.api.file.save(fileName, message.content)
|
||||
}
|
||||
},
|
||||
{ label: t('common.edit'), key: 'edit', icon: <EditOutlined />, onClick: onEdit },
|
||||
{ label: t('chat.message.new.branch'), key: 'new-branch', icon: <ForkOutlined />, onClick: onNewBranch },
|
||||
{
|
||||
label: t('common.edit'),
|
||||
key: 'edit',
|
||||
icon: <FilePenLine size={16} />,
|
||||
onClick: onEdit
|
||||
},
|
||||
{
|
||||
label: t('chat.message.new.branch'),
|
||||
key: 'new-branch',
|
||||
icon: <Split size={16} />,
|
||||
onClick: onNewBranch
|
||||
},
|
||||
{
|
||||
label: t('chat.topics.export.title'),
|
||||
key: 'export',
|
||||
icon: <UploadOutlined />,
|
||||
icon: <Share size={16} color="var(--color-icon)" style={{ marginTop: 3 }} />,
|
||||
children: [
|
||||
exportMenuOptions.image && {
|
||||
label: t('chat.topics.copy.image'),
|
||||
@ -361,7 +379,7 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
)}
|
||||
<Tooltip title={t('common.copy')} mouseEnterDelay={0.8}>
|
||||
<ActionButton className="message-action-button" onClick={onCopy}>
|
||||
{!copied && <i className="iconfont icon-copy"></i>}
|
||||
{!copied && <Copy size={16} />}
|
||||
{copied && <CheckOutlined style={{ color: 'var(--color-primary)' }} />}
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
@ -378,7 +396,7 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
open={showRegenerateTooltip}
|
||||
onOpenChange={setShowRegenerateTooltip}>
|
||||
<ActionButton className="message-action-button">
|
||||
<SyncOutlined />
|
||||
<RefreshCw size={16} />
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
</Popconfirm>
|
||||
@ -386,7 +404,7 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
{isAssistantMessage && (
|
||||
<Tooltip title={t('message.mention.title')} mouseEnterDelay={0.8}>
|
||||
<ActionButton className="message-action-button" onClick={onMentionModel}>
|
||||
<i className="iconfont icon-at" style={{ fontSize: 16 }}></i>
|
||||
<AtSign size={16} />
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
@ -412,7 +430,7 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
arrow>
|
||||
<Tooltip title={t('chat.translate')} mouseEnterDelay={1.2}>
|
||||
<ActionButton className="message-action-button" onClick={(e) => e.stopPropagation()}>
|
||||
<TranslationOutlined />
|
||||
<Languages size={16} />
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
</Dropdown>
|
||||
@ -420,7 +438,7 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
{isAssistantMessage && isGrouped && (
|
||||
<Tooltip title={t('chat.message.useful')} mouseEnterDelay={0.8}>
|
||||
<ActionButton className="message-action-button" onClick={onUseful}>
|
||||
{message.useful ? <LikeFilled /> : <LikeOutlined />}
|
||||
{message.useful ? <ThumbsUp size={16} /> : <ThumbsDown size={16} />}
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
@ -436,7 +454,7 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
mouseEnterDelay={1}
|
||||
open={showDeleteTooltip}
|
||||
onOpenChange={setShowDeleteTooltip}>
|
||||
<DeleteOutlined />
|
||||
<Trash size={16} />
|
||||
</Tooltip>
|
||||
</ActionButton>
|
||||
</Popconfirm>
|
||||
@ -447,7 +465,7 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
placement="topRight"
|
||||
arrow>
|
||||
<ActionButton className="message-action-button" onClick={(e) => e.stopPropagation()}>
|
||||
<MenuOutlined />
|
||||
<Menu size={19} />
|
||||
</ActionButton>
|
||||
</Dropdown>
|
||||
)}
|
||||
|
||||
@ -29,7 +29,6 @@ import ChatNavigation from './ChatNavigation'
|
||||
import MessageAnchorLine from './MessageAnchorLine'
|
||||
import MessageGroup from './MessageGroup'
|
||||
import NarrowLayout from './NarrowLayout'
|
||||
import NewTopicButton from './NewTopicButton'
|
||||
import Prompt from './Prompt'
|
||||
|
||||
interface MessagesProps {
|
||||
@ -225,7 +224,6 @@ const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic })
|
||||
ref={containerRef}
|
||||
$right={topicPosition === 'left'}>
|
||||
<NarrowLayout style={{ display: 'flex', flexDirection: 'column-reverse' }}>
|
||||
{messages.length >= 2 && !loading && <NewTopicButton />}
|
||||
<InfiniteScroll
|
||||
dataLength={displayMessages.length}
|
||||
next={loadMoreMessages}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { FormOutlined, SearchOutlined } from '@ant-design/icons'
|
||||
import { Navbar, NavbarLeft, NavbarRight } from '@renderer/components/app/Navbar'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import MinAppsPopover from '@renderer/components/Popups/MinAppsPopover'
|
||||
@ -15,6 +14,7 @@ import { setNarrowMode } from '@renderer/store/settings'
|
||||
import { Assistant, Topic } from '@renderer/types'
|
||||
import { Tooltip } from 'antd'
|
||||
import { t } from 'i18next'
|
||||
import { LayoutGrid, MessageSquareDiff, PanelLeftClose, PanelRightClose, Search } from 'lucide-react'
|
||||
import { FC } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
@ -61,12 +61,12 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant }) => {
|
||||
<NavbarLeft style={{ justifyContent: 'space-between', borderRight: 'none', padding: 0 }}>
|
||||
<Tooltip title={t('navbar.hide_sidebar')} mouseEnterDelay={0.8}>
|
||||
<NavbarIcon onClick={toggleShowAssistants} style={{ marginLeft: isMac ? 16 : 0 }}>
|
||||
<i className="iconfont icon-hide-sidebar" />
|
||||
<PanelLeftClose size={18} />
|
||||
</NavbarIcon>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('settings.shortcuts.new_topic')} mouseEnterDelay={0.8}>
|
||||
<NavbarIcon onClick={() => EventEmitter.emit(EVENT_NAMES.ADD_NEW_TOPIC)}>
|
||||
<FormOutlined />
|
||||
<NavbarIcon onClick={() => EventEmitter.emit(EVENT_NAMES.ADD_NEW_TOPIC)} style={{ marginRight: 5 }}>
|
||||
<MessageSquareDiff size={18} />
|
||||
</NavbarIcon>
|
||||
</Tooltip>
|
||||
</NavbarLeft>
|
||||
@ -78,7 +78,7 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant }) => {
|
||||
<NavbarIcon
|
||||
onClick={() => toggleShowAssistants()}
|
||||
style={{ marginRight: 8, marginLeft: isMac ? 4 : -12 }}>
|
||||
<i className="iconfont icon-show-sidebar" />
|
||||
<PanelRightClose size={18} />
|
||||
</NavbarIcon>
|
||||
</Tooltip>
|
||||
)}
|
||||
@ -88,7 +88,7 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant }) => {
|
||||
<UpdateAppButton />
|
||||
<Tooltip title={t('chat.assistant.search.placeholder')} mouseEnterDelay={0.8}>
|
||||
<NarrowIcon onClick={() => SearchPopup.show()}>
|
||||
<SearchOutlined />
|
||||
<Search size={18} />
|
||||
</NarrowIcon>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('navbar.expand')} mouseEnterDelay={0.8}>
|
||||
@ -100,14 +100,14 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant }) => {
|
||||
<MinAppsPopover>
|
||||
<Tooltip title={t('minapp.title')} mouseEnterDelay={0.8}>
|
||||
<NarrowIcon>
|
||||
<i className="iconfont icon-appstore" />
|
||||
<LayoutGrid size={18} />
|
||||
</NarrowIcon>
|
||||
</Tooltip>
|
||||
</MinAppsPopover>
|
||||
)}
|
||||
{topicPosition === 'right' && (
|
||||
<NarrowIcon onClick={toggleShowTopics}>
|
||||
<i className={`iconfont icon-${showTopics ? 'show' : 'hide'}-sidebar`} />
|
||||
{showTopics ? <PanelRightClose size={18} /> : <PanelLeftClose size={18} />}
|
||||
</NarrowIcon>
|
||||
)}
|
||||
</HStack>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { CheckOutlined, QuestionCircleOutlined, ReloadOutlined, SettingOutlined } from '@ant-design/icons'
|
||||
import { CheckOutlined } from '@ant-design/icons'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import {
|
||||
@ -44,6 +44,7 @@ import {
|
||||
import { Assistant, AssistantSettings, CodeStyleVarious, ThemeMode, TranslateLanguageVarious } from '@renderer/types'
|
||||
import { modalConfirm } from '@renderer/utils'
|
||||
import { Button, Col, InputNumber, Row, Segmented, Select, Slider, Switch, Tooltip } from 'antd'
|
||||
import { CircleHelp, RotateCcw, Settings2 } from 'lucide-react'
|
||||
import { FC, useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -179,13 +180,13 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
<HStack alignItems="center">
|
||||
{t('assistants.settings.title')}{' '}
|
||||
<Tooltip title={t('chat.settings.reset')}>
|
||||
<ReloadOutlined onClick={onReset} style={{ cursor: 'pointer', fontSize: 12, padding: '0 3px' }} />
|
||||
<RotateCcw size={20} onClick={onReset} style={{ cursor: 'pointer', padding: '0 3px' }} />
|
||||
</Tooltip>
|
||||
</HStack>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
icon={<SettingOutlined />}
|
||||
icon={<Settings2 size={16} />}
|
||||
onClick={() => AssistantSettingsPopup.show({ assistant, tab: 'model' })}
|
||||
/>
|
||||
</SettingSubtitle>
|
||||
@ -193,7 +194,7 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
<Row align="middle">
|
||||
<Label>{t('chat.settings.temperature')}</Label>
|
||||
<Tooltip title={t('chat.settings.temperature.tip')}>
|
||||
<QuestionIcon />
|
||||
<CircleHelp size={14} color="var(--color-text-2)" />
|
||||
</Tooltip>
|
||||
</Row>
|
||||
<Row align="middle" gutter={10}>
|
||||
@ -211,7 +212,7 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
<Row align="middle">
|
||||
<Label>{t('chat.settings.context_count')}</Label>
|
||||
<Tooltip title={t('chat.settings.context_count.tip')}>
|
||||
<QuestionIcon />
|
||||
<CircleHelp size={14} color="var(--color-text-2)" />
|
||||
</Tooltip>
|
||||
</Row>
|
||||
<Row align="middle" gutter={10}>
|
||||
@ -243,7 +244,7 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
<HStack alignItems="center">
|
||||
<Label>{t('chat.settings.max_tokens')}</Label>
|
||||
<Tooltip title={t('chat.settings.max_tokens.tip')}>
|
||||
<QuestionIcon />
|
||||
<CircleHelp size={14} color="var(--color-text-2)" />
|
||||
</Tooltip>
|
||||
</HStack>
|
||||
<Switch
|
||||
@ -288,7 +289,7 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
<Row align="middle">
|
||||
<Label>{t('assistants.settings.reasoning_effort')}</Label>
|
||||
<Tooltip title={t('assistants.settings.reasoning_effort.tip')}>
|
||||
<QuestionIcon />
|
||||
<CircleHelp size={14} color="var(--color-text-2)" />
|
||||
</Tooltip>
|
||||
</Row>
|
||||
<Row align="middle" gutter={10}>
|
||||
@ -371,7 +372,7 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
<SettingRowTitleSmall>
|
||||
{t('chat.settings.code_cacheable')}{' '}
|
||||
<Tooltip title={t('chat.settings.code_cacheable.tip')}>
|
||||
<QuestionIcon style={{ marginLeft: 4 }} />
|
||||
<CircleHelp size={14} style={{ marginLeft: 4 }} color="var(--color-text-2)" />
|
||||
</Tooltip>
|
||||
</SettingRowTitleSmall>
|
||||
<Switch size="small" checked={codeCacheable} onChange={(checked) => dispatch(setCodeCacheable(checked))} />
|
||||
@ -383,7 +384,7 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
<SettingRowTitleSmall>
|
||||
{t('chat.settings.code_cache_max_size')}
|
||||
<Tooltip title={t('chat.settings.code_cache_max_size.tip')}>
|
||||
<QuestionIcon style={{ marginLeft: 4 }} />
|
||||
<CircleHelp size={14} style={{ marginLeft: 4 }} color="var(--color-text-2)" />
|
||||
</Tooltip>
|
||||
</SettingRowTitleSmall>
|
||||
<InputNumber
|
||||
@ -401,7 +402,7 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
<SettingRowTitleSmall>
|
||||
{t('chat.settings.code_cache_ttl')}
|
||||
<Tooltip title={t('chat.settings.code_cache_ttl.tip')}>
|
||||
<QuestionIcon style={{ marginLeft: 4 }} />
|
||||
<CircleHelp size={14} style={{ marginLeft: 4 }} color="var(--color-text-2)" />
|
||||
</Tooltip>
|
||||
</SettingRowTitleSmall>
|
||||
<InputNumber
|
||||
@ -419,7 +420,7 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
<SettingRowTitleSmall>
|
||||
{t('chat.settings.code_cache_threshold')}
|
||||
<Tooltip title={t('chat.settings.code_cache_threshold.tip')}>
|
||||
<QuestionIcon style={{ marginLeft: 4 }} />
|
||||
<CircleHelp size={14} style={{ marginLeft: 4 }} color="var(--color-text-2)" />
|
||||
</Tooltip>
|
||||
</SettingRowTitleSmall>
|
||||
<InputNumber
|
||||
@ -439,7 +440,7 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
<SettingRowTitleSmall>
|
||||
{t('chat.settings.thought_auto_collapse')}
|
||||
<Tooltip title={t('chat.settings.thought_auto_collapse.tip')}>
|
||||
<QuestionIcon style={{ marginLeft: 4 }} />
|
||||
<CircleHelp size={14} style={{ marginLeft: 4 }} color="var(--color-text-2)" />
|
||||
</Tooltip>
|
||||
</SettingRowTitleSmall>
|
||||
<Switch
|
||||
@ -663,12 +664,6 @@ const Label = styled.p`
|
||||
margin-right: 5px;
|
||||
`
|
||||
|
||||
const QuestionIcon = styled(QuestionCircleOutlined)`
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
color: var(--color-text-3);
|
||||
`
|
||||
|
||||
const SettingRowTitleSmall = styled(SettingRowTitle)`
|
||||
font-size: 13px;
|
||||
`
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { BarsOutlined, SettingOutlined } from '@ant-design/icons'
|
||||
import AddAssistantPopup from '@renderer/components/Popups/AddAssistantPopup'
|
||||
import { useAssistants, useDefaultAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
@ -48,8 +47,7 @@ const HomeTabs: FC<Props> = ({ activeAssistant, activeTopic, setActiveAssistant,
|
||||
|
||||
const assistantTab = {
|
||||
label: t('assistants.abbr'),
|
||||
value: 'assistants',
|
||||
icon: <i className="iconfont icon-business-smart-assistant" />
|
||||
value: 'assistants'
|
||||
}
|
||||
|
||||
const onCreateAssistant = async () => {
|
||||
@ -104,13 +102,11 @@ const HomeTabs: FC<Props> = ({ activeAssistant, activeTopic, setActiveAssistant,
|
||||
position === 'left' && topicPosition === 'left' ? assistantTab : undefined,
|
||||
{
|
||||
label: t('common.topics'),
|
||||
value: 'topic',
|
||||
icon: <BarsOutlined />
|
||||
value: 'topic'
|
||||
},
|
||||
{
|
||||
label: t('settings.title'),
|
||||
value: 'settings',
|
||||
icon: <SettingOutlined />
|
||||
value: 'settings'
|
||||
}
|
||||
].filter(Boolean) as SegmentedProps['options']
|
||||
}
|
||||
|
||||
@ -1,14 +1,4 @@
|
||||
import {
|
||||
ColumnHeightOutlined,
|
||||
CopyOutlined,
|
||||
DeleteOutlined,
|
||||
EditOutlined,
|
||||
PlusOutlined,
|
||||
RedoOutlined,
|
||||
SearchOutlined,
|
||||
SettingOutlined,
|
||||
VerticalAlignMiddleOutlined
|
||||
} from '@ant-design/icons'
|
||||
import { CopyOutlined, DeleteOutlined, EditOutlined, RedoOutlined } from '@ant-design/icons'
|
||||
import CustomTag from '@renderer/components/CustomTag'
|
||||
import Ellipsis from '@renderer/components/Ellipsis'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
@ -23,6 +13,7 @@ import { formatFileSize } from '@renderer/utils'
|
||||
import { bookExts, documentExts, textExts, thirdPartyApplicationExts } from '@shared/config/constant'
|
||||
import { Alert, Button, Dropdown, Empty, message, Tag, Tooltip, Upload } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { ChevronsDown, ChevronsUp, Plus, Search, Settings2 } from 'lucide-react'
|
||||
import VirtualList from 'rc-virtual-list'
|
||||
import { FC, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -238,7 +229,7 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
<ModelInfo>
|
||||
<Button
|
||||
type="text"
|
||||
icon={<SettingOutlined />}
|
||||
icon={<Settings2 size={18} color="var(--color-icon)" />}
|
||||
onClick={() => KnowledgeSettingsPopup.show({ base })}
|
||||
size="small"
|
||||
/>
|
||||
@ -277,7 +268,7 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
size="small"
|
||||
shape="round"
|
||||
onClick={() => KnowledgeSearchPopup.show({ base })}
|
||||
icon={<SearchOutlined />}
|
||||
icon={<Search size={14} />}
|
||||
disabled={disabled}>
|
||||
{t('knowledge.search')}
|
||||
</Button>
|
||||
@ -286,7 +277,7 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
size="small"
|
||||
shape="circle"
|
||||
onClick={() => setExpandAll(!expandAll)}
|
||||
icon={expandAll ? <VerticalAlignMiddleOutlined /> : <ColumnHeightOutlined />}
|
||||
icon={expandAll ? <ChevronsUp size={14} /> : <ChevronsDown size={14} />}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</Tooltip>
|
||||
@ -306,7 +297,7 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
extra={
|
||||
<Button
|
||||
type="text"
|
||||
icon={<PlusOutlined />}
|
||||
icon={<Plus size={16} />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleAddFile()
|
||||
@ -393,7 +384,7 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
extra={
|
||||
<Button
|
||||
type="text"
|
||||
icon={<PlusOutlined />}
|
||||
icon={<Plus size={16} />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleAddDirectory()
|
||||
@ -445,7 +436,7 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
extra={
|
||||
<Button
|
||||
type="text"
|
||||
icon={<PlusOutlined />}
|
||||
icon={<Plus size={16} />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleAddUrl()
|
||||
@ -522,7 +513,7 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
extra={
|
||||
<Button
|
||||
type="text"
|
||||
icon={<PlusOutlined />}
|
||||
icon={<Plus size={16} />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleAddSitemap()
|
||||
@ -577,7 +568,7 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
extra={
|
||||
<Button
|
||||
type="text"
|
||||
icon={<PlusOutlined />}
|
||||
icon={<Plus size={16} />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
handleAddNote()
|
||||
|
||||
@ -1,11 +1,4 @@
|
||||
import {
|
||||
DeleteOutlined,
|
||||
EditOutlined,
|
||||
FileTextOutlined,
|
||||
PlusOutlined,
|
||||
SearchOutlined,
|
||||
SettingOutlined
|
||||
} from '@ant-design/icons'
|
||||
import { DeleteOutlined, EditOutlined, SettingOutlined } from '@ant-design/icons'
|
||||
import { Navbar, NavbarCenter, NavbarRight } from '@renderer/components/app/Navbar'
|
||||
import DragableList from '@renderer/components/DragableList'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
@ -18,6 +11,7 @@ import { NavbarIcon } from '@renderer/pages/home/Navbar'
|
||||
import KnowledgeSearchPopup from '@renderer/pages/knowledge/components/KnowledgeSearchPopup'
|
||||
import { KnowledgeBase } from '@renderer/types'
|
||||
import { Dropdown, Empty, MenuProps } from 'antd'
|
||||
import { Book, Plus, Search } from 'lucide-react'
|
||||
import { FC, useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -105,7 +99,7 @@ const KnowledgePage: FC = () => {
|
||||
<NavbarRight>
|
||||
<HStack alignItems="center">
|
||||
<NarrowIcon onClick={() => selectedBase && KnowledgeSearchPopup.show({ base: selectedBase })}>
|
||||
<SearchOutlined />
|
||||
<Search size={18} />
|
||||
</NarrowIcon>
|
||||
</HStack>
|
||||
</NavbarRight>
|
||||
@ -124,7 +118,7 @@ const KnowledgePage: FC = () => {
|
||||
<div>
|
||||
<ListItem
|
||||
active={selectedBase?.id === base.id}
|
||||
icon={<FileTextOutlined />}
|
||||
icon={<Book size={16} />}
|
||||
title={base.name}
|
||||
onClick={() => setSelectedBase(base)}
|
||||
/>
|
||||
@ -135,7 +129,7 @@ const KnowledgePage: FC = () => {
|
||||
{!isDragging && (
|
||||
<AddKnowledgeItem onClick={handleAddKnowledge}>
|
||||
<AddKnowledgeName>
|
||||
<PlusOutlined style={{ color: 'var(--color-text-2)', marginRight: 4 }} />
|
||||
<Plus size={18} />
|
||||
{t('button.add')}
|
||||
</AddKnowledgeName>
|
||||
</AddKnowledgeItem>
|
||||
@ -243,6 +237,10 @@ const AddKnowledgeName = styled.div`
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
font-size: 13px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
`
|
||||
|
||||
const NarrowIcon = styled(NavbarIcon)`
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { GithubOutlined } from '@ant-design/icons'
|
||||
import { FileProtectOutlined, GlobalOutlined, MailOutlined, SoundOutlined } from '@ant-design/icons'
|
||||
import IndicatorLight from '@renderer/components/IndicatorLight'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import { isWindows } from '@renderer/config/constant'
|
||||
@ -15,6 +14,7 @@ import { ThemeMode } from '@renderer/types'
|
||||
import { compareVersions, runAsyncFunction } from '@renderer/utils'
|
||||
import { Avatar, Button, Progress, Row, Switch, Tag } from 'antd'
|
||||
import { debounce } from 'lodash'
|
||||
import { FileCheck, Github, Globe, Mail, Rss } from 'lucide-react'
|
||||
import { FC, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Markdown from 'react-markdown'
|
||||
@ -181,7 +181,7 @@ const AboutSettings: FC = () => {
|
||||
<SettingGroup theme={theme}>
|
||||
<SettingRow>
|
||||
<SettingRowTitle>
|
||||
<SoundOutlined />
|
||||
<Rss size={18} />
|
||||
{t('settings.about.releases.title')}
|
||||
</SettingRowTitle>
|
||||
<Button onClick={showReleases}>{t('settings.about.releases.button')}</Button>
|
||||
@ -189,7 +189,7 @@ const AboutSettings: FC = () => {
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>
|
||||
<GlobalOutlined />
|
||||
<Globe size={18} />
|
||||
{t('settings.about.website.title')}
|
||||
</SettingRowTitle>
|
||||
<Button onClick={() => onOpenWebsite('https://cherry-ai.com')}>{t('settings.about.website.button')}</Button>
|
||||
@ -197,7 +197,7 @@ const AboutSettings: FC = () => {
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>
|
||||
<GithubOutlined />
|
||||
<Github size={18} />
|
||||
{t('settings.about.feedback.title')}
|
||||
</SettingRowTitle>
|
||||
<Button onClick={() => onOpenWebsite('https://github.com/CherryHQ/cherry-studio/issues/new/choose')}>
|
||||
@ -207,7 +207,7 @@ const AboutSettings: FC = () => {
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>
|
||||
<FileProtectOutlined />
|
||||
<FileCheck size={18} />
|
||||
{t('settings.about.license.title')}
|
||||
</SettingRowTitle>
|
||||
<Button onClick={showLicense}>{t('settings.about.license.button')}</Button>
|
||||
@ -215,7 +215,8 @@ const AboutSettings: FC = () => {
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitle>
|
||||
<MailOutlined /> {t('settings.about.contact.title')}
|
||||
<Mail size={18} />
|
||||
{t('settings.about.contact.title')}
|
||||
</SettingRowTitle>
|
||||
<Button onClick={mailto}>{t('settings.about.contact.button')}</Button>
|
||||
</SettingRow>
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { CloseOutlined } from '@ant-design/icons'
|
||||
import { FileSearchOutlined, FolderOutlined, PictureOutlined, TranslationOutlined } from '@ant-design/icons'
|
||||
import {
|
||||
DragDropContext,
|
||||
Draggable,
|
||||
@ -11,6 +10,7 @@ import {
|
||||
import { useAppDispatch } from '@renderer/store'
|
||||
import { setSidebarIcons } from '@renderer/store/settings'
|
||||
import { message } from 'antd'
|
||||
import { Folder, Languages, LayoutGrid, LibraryBig, MessageSquareQuote, Palette, Sparkle } from 'lucide-react'
|
||||
import { FC, useCallback, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -109,13 +109,13 @@ const SidebarIconsManager: FC<SidebarIconsManagerProps> = ({
|
||||
// 使用useMemo缓存图标映射
|
||||
const iconMap = useMemo(
|
||||
() => ({
|
||||
assistants: <i className="iconfont icon-chat" />,
|
||||
agents: <i className="iconfont icon-business-smart-assistant" />,
|
||||
paintings: <PictureOutlined style={{ fontSize: 14 }} />,
|
||||
translate: <TranslationOutlined />,
|
||||
minapp: <i className="iconfont icon-appstore" />,
|
||||
knowledge: <FileSearchOutlined />,
|
||||
files: <FolderOutlined />
|
||||
assistants: <MessageSquareQuote size={16} />,
|
||||
agents: <Sparkle size={16} />,
|
||||
paintings: <Palette size={16} />,
|
||||
translate: <Languages size={16} />,
|
||||
minapp: <LayoutGrid size={16} />,
|
||||
knowledge: <LibraryBig size={16} />,
|
||||
files: <Folder size={15} />
|
||||
}),
|
||||
[]
|
||||
)
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import { EditOutlined, ExportOutlined, SearchOutlined } from '@ant-design/icons'
|
||||
import { EditOutlined, ExportOutlined } from '@ant-design/icons'
|
||||
import { NavbarRight } from '@renderer/components/app/Navbar'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import { isWindows } from '@renderer/config/constant'
|
||||
import { Button } from 'antd'
|
||||
import { Search } from 'lucide-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useNavigate } from 'react-router'
|
||||
|
||||
@ -21,7 +22,7 @@ export const McpSettingsNavbar = () => {
|
||||
size="small"
|
||||
type="text"
|
||||
onClick={() => navigate('/settings/mcp/npx-search')}
|
||||
icon={<SearchOutlined />}
|
||||
icon={<Search size={14} />}
|
||||
className="nodrag"
|
||||
style={{ fontSize: 13, height: 28, borderRadius: 20 }}>
|
||||
{t('settings.mcp.searchNpx')}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { EditOutlined, MessageOutlined, RedoOutlined, SettingOutlined, TranslationOutlined } from '@ant-design/icons'
|
||||
import { RedoOutlined } from '@ant-design/icons'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import PromptPopup from '@renderer/components/Popups/PromptPopup'
|
||||
import { isEmbeddingModel } from '@renderer/config/models'
|
||||
@ -13,6 +13,7 @@ import { setTranslateModelPrompt } from '@renderer/store/settings'
|
||||
import { Model } from '@renderer/types'
|
||||
import { Button, Select, Tooltip } from 'antd'
|
||||
import { find, sortBy } from 'lodash'
|
||||
import { FolderPen, Languages, MessageSquareMore, Settings2 } from 'lucide-react'
|
||||
import { FC, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@ -82,10 +83,10 @@ const ModelSettings: FC = () => {
|
||||
<SettingContainer theme={theme}>
|
||||
<SettingGroup theme={theme}>
|
||||
<SettingTitle style={{ marginBottom: 12 }}>
|
||||
<div>
|
||||
<MessageOutlined style={iconStyle} />
|
||||
<HStack alignItems="center" gap={10}>
|
||||
<MessageSquareMore size={18} color="var(--color-text)" />
|
||||
{t('settings.models.default_assistant_model')}
|
||||
</div>
|
||||
</HStack>
|
||||
</SettingTitle>
|
||||
<HStack alignItems="center">
|
||||
<Select
|
||||
@ -97,16 +98,16 @@ const ModelSettings: FC = () => {
|
||||
showSearch
|
||||
placeholder={t('settings.models.empty')}
|
||||
/>
|
||||
<Button icon={<SettingOutlined />} style={{ marginLeft: 8 }} onClick={DefaultAssistantSettings.show} />
|
||||
<Button icon={<Settings2 size={16} />} style={{ marginLeft: 8 }} onClick={DefaultAssistantSettings.show} />
|
||||
</HStack>
|
||||
<SettingDescription>{t('settings.models.default_assistant_model_description')}</SettingDescription>
|
||||
</SettingGroup>
|
||||
<SettingGroup theme={theme}>
|
||||
<SettingTitle style={{ marginBottom: 12 }}>
|
||||
<div>
|
||||
<EditOutlined style={iconStyle} />
|
||||
<HStack alignItems="center" gap={10}>
|
||||
<FolderPen size={18} color="var(--color-text)" />
|
||||
{t('settings.models.topic_naming_model')}
|
||||
</div>
|
||||
</HStack>
|
||||
</SettingTitle>
|
||||
<HStack alignItems="center">
|
||||
<Select
|
||||
@ -118,16 +119,16 @@ const ModelSettings: FC = () => {
|
||||
showSearch
|
||||
placeholder={t('settings.models.empty')}
|
||||
/>
|
||||
<Button icon={<SettingOutlined />} style={{ marginLeft: 8 }} onClick={TopicNamingModalPopup.show} />
|
||||
<Button icon={<Settings2 size={16} />} style={{ marginLeft: 8 }} onClick={TopicNamingModalPopup.show} />
|
||||
</HStack>
|
||||
<SettingDescription>{t('settings.models.topic_naming_model_description')}</SettingDescription>
|
||||
</SettingGroup>
|
||||
<SettingGroup theme={theme}>
|
||||
<SettingTitle style={{ marginBottom: 12 }}>
|
||||
<div>
|
||||
<TranslationOutlined style={iconStyle} />
|
||||
<HStack alignItems="center" gap={10}>
|
||||
<Languages size={18} color="var(--color-text)" />
|
||||
{t('settings.models.translate_model')}
|
||||
</div>
|
||||
</HStack>
|
||||
</SettingTitle>
|
||||
<HStack alignItems="center">
|
||||
<Select
|
||||
@ -139,7 +140,7 @@ const ModelSettings: FC = () => {
|
||||
showSearch
|
||||
placeholder={t('settings.models.empty')}
|
||||
/>
|
||||
<Button icon={<SettingOutlined />} style={{ marginLeft: 8 }} onClick={onUpdateTranslateModel} />
|
||||
<Button icon={<Settings2 size={16} />} style={{ marginLeft: 8 }} onClick={onUpdateTranslateModel} />
|
||||
{translateModelPrompt !== TRANSLATE_PROMPT && (
|
||||
<Tooltip title={t('common.reset')}>
|
||||
<Button icon={<RedoOutlined />} style={{ marginLeft: 8 }} onClick={onResetTranslatePrompt}></Button>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { LoadingOutlined, MinusOutlined, PlusOutlined, SearchOutlined } from '@ant-design/icons'
|
||||
import { LoadingOutlined, MinusOutlined, PlusOutlined } from '@ant-design/icons'
|
||||
import CustomCollapse from '@renderer/components/CustomCollapse'
|
||||
import CustomTag from '@renderer/components/CustomTag'
|
||||
import ModelTagsWithLabel from '@renderer/components/ModelTagsWithLabel'
|
||||
@ -21,6 +21,7 @@ import { getDefaultGroupName, isFreeModel, runAsyncFunction } from '@renderer/ut
|
||||
import { Avatar, Button, Empty, Flex, Modal, Tabs, Tooltip, Typography } from 'antd'
|
||||
import Input from 'antd/es/input/Input'
|
||||
import { groupBy, isEmpty, uniqBy } from 'lodash'
|
||||
import { Search } from 'lucide-react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -180,7 +181,7 @@ const PopupContainer: React.FC<Props> = ({ provider: _provider, resolve }) => {
|
||||
centered>
|
||||
<SearchContainer>
|
||||
<Input
|
||||
prefix={<SearchOutlined />}
|
||||
prefix={<Search size={14} />}
|
||||
size="large"
|
||||
ref={searchInputRef}
|
||||
placeholder={t('settings.provider.search_placeholder')}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import {
|
||||
CheckCircleFilled,
|
||||
CloseCircleFilled,
|
||||
EditOutlined,
|
||||
ExclamationCircleFilled,
|
||||
LoadingOutlined,
|
||||
MinusCircleOutlined,
|
||||
@ -23,6 +22,7 @@ import { Model } from '@renderer/types'
|
||||
import { maskApiKey } from '@renderer/utils/api'
|
||||
import { Avatar, Button, Flex, Tooltip, Typography } from 'antd'
|
||||
import { groupBy, sortBy, toPairs } from 'lodash'
|
||||
import { ListCheck } from 'lucide-react'
|
||||
import React, { memo, useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -333,7 +333,7 @@ const ModelList: React.FC<ModelListProps> = ({ providerId, modelStatuses = [], s
|
||||
)}
|
||||
</Flex>
|
||||
<Flex gap={10} style={{ marginTop: '10px' }}>
|
||||
<Button type="primary" onClick={onManageModel} icon={<EditOutlined />}>
|
||||
<Button type="primary" onClick={onManageModel} icon={<ListCheck size={18} />}>
|
||||
{t('button.manage')}
|
||||
</Button>
|
||||
<Button type="default" onClick={onAddModel} icon={<PlusOutlined />}>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { SearchOutlined } from '@ant-design/icons'
|
||||
import { Input, Tooltip } from 'antd'
|
||||
import { Search } from 'lucide-react'
|
||||
import React, { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@ -33,7 +33,7 @@ const ModelListSearchBar: React.FC<ModelListSearchBarProps> = ({ onSearch }) =>
|
||||
placeholder={t('models.search')}
|
||||
size="small"
|
||||
style={{ width: '160px' }}
|
||||
suffix={<SearchOutlined style={{ color: 'var(--color-text-3)' }} />}
|
||||
suffix={<Search size={14} />}
|
||||
onChange={(e) => handleTextChange(e.target.value)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Escape') {
|
||||
@ -50,7 +50,12 @@ const ModelListSearchBar: React.FC<ModelListSearchBarProps> = ({ onSearch }) =>
|
||||
/>
|
||||
) : (
|
||||
<Tooltip title={t('models.search')} mouseEnterDelay={0.5}>
|
||||
<SearchOutlined onClick={() => setSearchVisible(true)} />
|
||||
<Search
|
||||
size={14}
|
||||
color="var(--color-icon)"
|
||||
onClick={() => setSearchVisible(true)}
|
||||
style={{ cursor: 'pointer' }}
|
||||
/>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { CheckOutlined, ExportOutlined, LoadingOutlined, SettingOutlined } from '@ant-design/icons'
|
||||
import { CheckOutlined, LoadingOutlined, SettingOutlined } from '@ant-design/icons'
|
||||
import { StreamlineGoodHealthAndWellBeing } from '@renderer/components/Icons/SVGIcon'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import OAuthButton from '@renderer/components/OAuth/OAuthButton'
|
||||
@ -17,6 +17,7 @@ import { providerCharge } from '@renderer/utils/oauth'
|
||||
import { Button, Divider, Flex, Input, Space, Switch, Tooltip } from 'antd'
|
||||
import Link from 'antd/es/typography/Link'
|
||||
import { debounce, isEmpty } from 'lodash'
|
||||
import { SquareArrowOutUpRight } from 'lucide-react'
|
||||
import { FC, useCallback, useDeferredValue, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -279,8 +280,8 @@ const ProviderSetting: FC<Props> = ({ provider: _provider }) => {
|
||||
<Flex align="center" gap={8}>
|
||||
<ProviderName>{provider.isSystem ? t(`provider.${provider.id}`) : provider.name}</ProviderName>
|
||||
{officialWebsite! && (
|
||||
<Link target="_blank" href={providerConfig.websites.official}>
|
||||
<ExportOutlined style={{ color: 'var(--color-text)', fontSize: '12px' }} />
|
||||
<Link target="_blank" href={providerConfig.websites.official} style={{ display: 'flex' }}>
|
||||
<SquareArrowOutUpRight size={14} color="var(--color-text)" />
|
||||
</Link>
|
||||
)}
|
||||
{!provider.isSystem && (
|
||||
@ -383,10 +384,10 @@ const ProviderSetting: FC<Props> = ({ provider: _provider }) => {
|
||||
{provider.id === 'copilot' && <GithubCopilotSettings provider={provider} setApiKey={setApiKey} />}
|
||||
<SettingSubtitle style={{ marginBottom: 5 }}>
|
||||
<Space align="center" style={{ width: '100%', justifyContent: 'space-between' }}>
|
||||
<Space>
|
||||
<HStack alignItems="center" gap={5}>
|
||||
<SettingSubtitle style={{ marginTop: 0 }}>{t('common.models')}</SettingSubtitle>
|
||||
{!isEmpty(models) && <ModelListSearchBar onSearch={setModelSearchText} />}
|
||||
</Space>
|
||||
</HStack>
|
||||
{!isEmpty(models) && (
|
||||
<Tooltip title={t('settings.models.check.button_caption')} mouseEnterDelay={0.5}>
|
||||
<Button
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { DeleteOutlined, EditOutlined, PlusOutlined, SearchOutlined } from '@ant-design/icons'
|
||||
import { DeleteOutlined, EditOutlined, PlusOutlined } from '@ant-design/icons'
|
||||
import { DragDropContext, Draggable, Droppable, DropResult } from '@hello-pangea/dnd'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import { getProviderLogo } from '@renderer/config/providers'
|
||||
@ -7,6 +7,7 @@ import ImageStorage from '@renderer/services/ImageStorage'
|
||||
import { Provider } from '@renderer/types'
|
||||
import { droppableReorder, generateColorFromChar, getFirstCharacter, uuid } from '@renderer/utils'
|
||||
import { Avatar, Button, Dropdown, Input, MenuProps, Tag } from 'antd'
|
||||
import { Search } from 'lucide-react'
|
||||
import { FC, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -178,7 +179,7 @@ const ProvidersList: FC = () => {
|
||||
|
||||
const getProviderAvatar = (provider: Provider) => {
|
||||
if (provider.isSystem) {
|
||||
return <ProviderLogo shape="square" src={getProviderLogo(provider.id)} size={25} />
|
||||
return <ProviderLogo shape="circle" src={getProviderLogo(provider.id)} size={25} />
|
||||
}
|
||||
|
||||
const customLogo = providerLogos[provider.id]
|
||||
@ -222,7 +223,7 @@ const ProvidersList: FC = () => {
|
||||
placeholder={t('settings.provider.search')}
|
||||
value={searchText}
|
||||
style={{ borderRadius: 'var(--list-item-border-radius)', height: 35 }}
|
||||
suffix={<SearchOutlined style={{ color: 'var(--color-text-3)' }} />}
|
||||
suffix={<Search size={14} />}
|
||||
onChange={(e) => setSearchText(e.target.value)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Escape') {
|
||||
|
||||
@ -1,19 +1,20 @@
|
||||
import {
|
||||
AppstoreOutlined,
|
||||
CloudOutlined,
|
||||
CodeOutlined,
|
||||
GlobalOutlined,
|
||||
InfoCircleOutlined,
|
||||
LayoutOutlined,
|
||||
MacCommandOutlined,
|
||||
RocketOutlined,
|
||||
SaveOutlined,
|
||||
SettingOutlined,
|
||||
ThunderboltOutlined
|
||||
} from '@ant-design/icons'
|
||||
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
||||
import { useSidebarIconShow } from '@renderer/hooks/useSidebarIcon'
|
||||
import ModelSettings from '@renderer/pages/settings/ModelSettings/ModelSettings'
|
||||
import {
|
||||
Cloud,
|
||||
Command,
|
||||
Globe,
|
||||
HardDrive,
|
||||
Info,
|
||||
LayoutGrid,
|
||||
MonitorCog,
|
||||
Package,
|
||||
Rocket,
|
||||
Settings2,
|
||||
SquareTerminal,
|
||||
Zap
|
||||
} from 'lucide-react'
|
||||
// 导入useAppSelector
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -51,75 +52,75 @@ const SettingsPage: FC = () => {
|
||||
<SettingMenus>
|
||||
<MenuItemLink to="/settings/provider">
|
||||
<MenuItem className={isRoute('/settings/provider')}>
|
||||
<CloudOutlined />
|
||||
<Cloud size={18} />
|
||||
{t('settings.provider.title')}
|
||||
</MenuItem>
|
||||
</MenuItemLink>
|
||||
<MenuItemLink to="/settings/model">
|
||||
<MenuItem className={isRoute('/settings/model')}>
|
||||
<i className="iconfont icon-ai-model" />
|
||||
<Package size={18} />
|
||||
{t('settings.model')}
|
||||
</MenuItem>
|
||||
</MenuItemLink>
|
||||
<MenuItemLink to="/settings/web-search">
|
||||
<MenuItem className={isRoute('/settings/web-search')}>
|
||||
<GlobalOutlined />
|
||||
<Globe size={18} />
|
||||
{t('settings.websearch.title')}
|
||||
</MenuItem>
|
||||
</MenuItemLink>
|
||||
<MenuItemLink to="/settings/mcp">
|
||||
<MenuItem className={isRoute('/settings/mcp')}>
|
||||
<CodeOutlined />
|
||||
<SquareTerminal size={18} />
|
||||
{t('settings.mcp.title')}
|
||||
</MenuItem>
|
||||
</MenuItemLink>
|
||||
<MenuItemLink to="/settings/general">
|
||||
<MenuItem className={isRoute('/settings/general')}>
|
||||
<SettingOutlined />
|
||||
<Settings2 size={18} />
|
||||
{t('settings.general')}
|
||||
</MenuItem>
|
||||
</MenuItemLink>
|
||||
<MenuItemLink to="/settings/display">
|
||||
<MenuItem className={isRoute('/settings/display')}>
|
||||
<LayoutOutlined />
|
||||
<MonitorCog size={18} />
|
||||
{t('settings.display.title')}
|
||||
</MenuItem>
|
||||
</MenuItemLink>
|
||||
{showMiniAppSettings && (
|
||||
<MenuItemLink to="/settings/miniapps">
|
||||
<MenuItem className={isRoute('/settings/miniapps')}>
|
||||
<AppstoreOutlined />
|
||||
<LayoutGrid size={18} />
|
||||
{t('settings.miniapps.title')}
|
||||
</MenuItem>
|
||||
</MenuItemLink>
|
||||
)}
|
||||
<MenuItemLink to="/settings/shortcut">
|
||||
<MenuItem className={isRoute('/settings/shortcut')}>
|
||||
<MacCommandOutlined />
|
||||
<Command size={18} />
|
||||
{t('settings.shortcuts.title')}
|
||||
</MenuItem>
|
||||
</MenuItemLink>
|
||||
<MenuItemLink to="/settings/quickAssistant">
|
||||
<MenuItem className={isRoute('/settings/quickAssistant')}>
|
||||
<RocketOutlined />
|
||||
<Rocket size={18} />
|
||||
{t('settings.quickAssistant.title')}
|
||||
</MenuItem>
|
||||
</MenuItemLink>
|
||||
<MenuItemLink to="/settings/quickPhrase">
|
||||
<MenuItem className={isRoute('/settings/quickPhrase')}>
|
||||
<ThunderboltOutlined />
|
||||
<Zap size={18} />
|
||||
{t('settings.quickPhrase.title')}
|
||||
</MenuItem>
|
||||
</MenuItemLink>
|
||||
<MenuItemLink to="/settings/data">
|
||||
<MenuItem className={isRoute('/settings/data')}>
|
||||
<SaveOutlined />
|
||||
<HardDrive size={18} />
|
||||
{t('settings.data.title')}
|
||||
</MenuItem>
|
||||
</MenuItemLink>
|
||||
<MenuItemLink to="/settings/about">
|
||||
<MenuItem className={isRoute('/settings/about')}>
|
||||
<InfoCircleOutlined />
|
||||
<Info size={18} />
|
||||
{t('settings.about')}
|
||||
</MenuItem>
|
||||
</MenuItemLink>
|
||||
|
||||
@ -316,6 +316,7 @@ const ShortcutSettings: FC = () => {
|
||||
<Button
|
||||
icon={<UndoOutlined />}
|
||||
size="small"
|
||||
shape="circle"
|
||||
onClick={() => handleResetShortcut(record)}
|
||||
disabled={!isShortcutModified(record)}
|
||||
/>
|
||||
@ -324,6 +325,7 @@ const ShortcutSettings: FC = () => {
|
||||
<Button
|
||||
icon={<ClearOutlined />}
|
||||
size="small"
|
||||
shape="circle"
|
||||
onClick={() => handleClear(record)}
|
||||
disabled={record.shortcut.length === 0 || !record.editable}
|
||||
/>
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { InfoCircleOutlined } from '@ant-design/icons'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||
import { setEnhanceMode, setMaxResult, setOverwrite, setSearchWithTime } from '@renderer/store/websearch'
|
||||
import { Slider, Switch, Tooltip } from 'antd'
|
||||
import { t } from 'i18next'
|
||||
import { Info } from 'lucide-react'
|
||||
import { FC } from 'react'
|
||||
|
||||
import { SettingDivider, SettingGroup, SettingRow, SettingRowTitle, SettingTitle } from '..'
|
||||
@ -31,7 +31,7 @@ const BasicSettings: FC = () => {
|
||||
<SettingRowTitle>
|
||||
{t('settings.websearch.overwrite')}
|
||||
<Tooltip title={t('settings.websearch.overwrite_tooltip')} placement="right">
|
||||
<InfoCircleOutlined style={{ marginLeft: 5, color: 'var(--color-icon)', cursor: 'pointer' }} />
|
||||
<Info size={16} color="var(--color-icon)" style={{ marginLeft: 5, cursor: 'pointer' }} />
|
||||
</Tooltip>
|
||||
</SettingRowTitle>
|
||||
<Switch checked={overwrite} onChange={(checked) => dispatch(setOverwrite(checked))} />
|
||||
@ -41,7 +41,7 @@ const BasicSettings: FC = () => {
|
||||
<SettingRowTitle>
|
||||
{t('settings.websearch.enhance_mode')}
|
||||
<Tooltip title={t('settings.websearch.enhance_mode_tooltip')} placement="right">
|
||||
<InfoCircleOutlined style={{ marginLeft: 5, color: 'var(--color-icon)', cursor: 'pointer' }} />
|
||||
<Info size={16} color="var(--color-icon)" style={{ marginLeft: 5, cursor: 'pointer' }} />
|
||||
</Tooltip>
|
||||
</SettingRowTitle>
|
||||
<Switch checked={enhanceMode} onChange={(checked) => dispatch(setEnhanceMode(checked))} />
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { CheckOutlined, ExportOutlined, InfoCircleOutlined, LoadingOutlined } from '@ant-design/icons'
|
||||
import { CheckOutlined, ExportOutlined, LoadingOutlined } from '@ant-design/icons'
|
||||
import { getWebSearchProviderLogo, WEB_SEARCH_PROVIDER_CONFIG } from '@renderer/config/webSearchProviders'
|
||||
import { useWebSearchProvider } from '@renderer/hooks/useWebSearchProviders'
|
||||
import { formatApiKeys } from '@renderer/services/ApiService'
|
||||
@ -7,6 +7,7 @@ import { WebSearchProvider } from '@renderer/types'
|
||||
import { hasObjectKey } from '@renderer/utils'
|
||||
import { Avatar, Button, Divider, Flex, Input } from 'antd'
|
||||
import Link from 'antd/es/typography/Link'
|
||||
import { Info } from 'lucide-react'
|
||||
import { FC, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@ -53,7 +54,7 @@ const WebSearchProviderSetting: FC<Props> = ({ provider: _provider }) => {
|
||||
window.message.error({
|
||||
content: t('settings.websearch.no_provider_selected'),
|
||||
duration: 3,
|
||||
icon: <InfoCircleOutlined />,
|
||||
icon: <Info size={18} />,
|
||||
key: 'no-provider-selected'
|
||||
})
|
||||
return
|
||||
|
||||
@ -61,6 +61,9 @@ export const SettingRowTitle = styled.div`
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
color: var(--color-text-1);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
`
|
||||
|
||||
export const SettingHelpTextRow = styled.div`
|
||||
|
||||
@ -1,12 +1,4 @@
|
||||
import {
|
||||
CheckOutlined,
|
||||
DeleteOutlined,
|
||||
HistoryOutlined,
|
||||
SendOutlined,
|
||||
SettingOutlined,
|
||||
SyncOutlined,
|
||||
WarningOutlined
|
||||
} from '@ant-design/icons'
|
||||
import { CheckOutlined, DeleteOutlined, HistoryOutlined, SendOutlined } from '@ant-design/icons'
|
||||
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
||||
import CopyIcon from '@renderer/components/Icons/CopyIcon'
|
||||
import { isLocalAi } from '@renderer/config/env'
|
||||
@ -22,6 +14,7 @@ import TextArea, { TextAreaRef } from 'antd/es/input/TextArea'
|
||||
import dayjs from 'dayjs'
|
||||
import { useLiveQuery } from 'dexie-react-hooks'
|
||||
import { isEmpty } from 'lodash'
|
||||
import { Mouse, Settings2, TriangleAlert } from 'lucide-react'
|
||||
import { FC, useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Link } from 'react-router-dom'
|
||||
@ -167,18 +160,18 @@ const TranslatePage: FC = () => {
|
||||
|
||||
if (translateModel) {
|
||||
return (
|
||||
<Link to="/settings/model" style={{ color: 'var(--color-text-2)' }}>
|
||||
<SettingOutlined />
|
||||
<Link to="/settings/model" style={{ color: 'var(--color-text-2)', display: 'flex' }}>
|
||||
<Settings2 size={18} />
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Link to="/settings/model" style={{ marginLeft: -10 }}>
|
||||
<Link to="/settings/model" style={{ marginLeft: -10, display: 'flex' }}>
|
||||
<Button
|
||||
type="link"
|
||||
style={{ color: 'var(--color-error)', textDecoration: 'underline' }}
|
||||
icon={<WarningOutlined />}>
|
||||
icon={<TriangleAlert size={16} />}>
|
||||
{t('translate.error.not_configured')}
|
||||
</Button>
|
||||
</Link>
|
||||
@ -304,11 +297,11 @@ const TranslatePage: FC = () => {
|
||||
<Tooltip
|
||||
mouseEnterDelay={0.5}
|
||||
title={isScrollSyncEnabled ? t('translate.scroll_sync.disable') : t('translate.scroll_sync.enable')}>
|
||||
<SyncOutlined
|
||||
style={{
|
||||
color: isScrollSyncEnabled ? 'var(--color-primary)' : 'var(--color-text-2)'
|
||||
}}
|
||||
<Mouse
|
||||
size={16}
|
||||
onClick={toggleScrollSync}
|
||||
style={{ cursor: 'pointer' }}
|
||||
color={isScrollSyncEnabled ? 'var(--color-primary)' : 'var(--color-icon)'}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user