fix: 新的滚动条组件
This commit is contained in:
parent
27631d9cff
commit
7f0909c796
@ -93,7 +93,6 @@
|
||||
"openai": "^4.52.1",
|
||||
"prettier": "^3.2.4",
|
||||
"react": "^18.2.0",
|
||||
"react-custom-scrollbars-2": "^4.5.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-i18next": "^14.1.2",
|
||||
"react-markdown": "^9.0.1",
|
||||
|
||||
@ -156,7 +156,6 @@ body[os='mac'] {
|
||||
#content-container {
|
||||
border-top-left-radius: 10px;
|
||||
border-bottom-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
border-left: 0.5px solid var(--color-border);
|
||||
box-shadow: 0 0 15px 1px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
@ -1,11 +1,15 @@
|
||||
:root {
|
||||
--color-scrollbar-thumb: #6b6b6b;
|
||||
--color-scrollbar-thumb-hover: #939393;
|
||||
--color-scrollbar-thumb: rgba(255, 255, 255, 0.15);
|
||||
--color-scrollbar-thumb-hover: rgba(255, 255, 255, 0.2);
|
||||
--color-scrollbar-thumb-right: rgba(255, 255, 255, 0.25);
|
||||
--color-scrollbar-thumb-right-hover: rgba(255, 255, 255, 0.35);
|
||||
}
|
||||
|
||||
body[theme-mode='light'] {
|
||||
--color-scrollbar-thumb: #b1b1b1;
|
||||
--color-scrollbar-thumb-hover: #7d7d7d;
|
||||
--color-scrollbar-thumb: rgba(0, 0, 0, 0.15);
|
||||
--color-scrollbar-thumb-hover: rgba(0, 0, 0, 0.2);
|
||||
--color-scrollbar-thumb-right: rgba(0, 0, 0, 0.25);
|
||||
--color-scrollbar-thumb-right-hover: rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
||||
/* 全局初始化滚动条样式 */
|
||||
|
||||
@ -12,7 +12,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import { HStack } from '../Layout'
|
||||
import { Scrollbar } from '../Scrollbar'
|
||||
import Scrollbar from '../Scrollbar'
|
||||
|
||||
type MenuItem = Required<MenuProps>['items'][number]
|
||||
|
||||
|
||||
@ -1,22 +1,57 @@
|
||||
import { ScrollbarProps, Scrollbars } from 'react-custom-scrollbars-2'
|
||||
import { throttle } from 'lodash'
|
||||
import { FC, forwardRef, useCallback, useEffect, useRef, useState } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
export const Scrollbar: React.FC<ScrollbarProps> = ({ children, ...props }) => {
|
||||
return (
|
||||
<Scrollbars
|
||||
autoHide
|
||||
{...props}
|
||||
renderThumbVertical={(props) => <Thumb {...props} />}
|
||||
renderTrackHorizontal={(props) => <Thumb {...props} />}>
|
||||
{children}
|
||||
</Scrollbars>
|
||||
)
|
||||
interface Props extends React.HTMLAttributes<HTMLDivElement> {
|
||||
right?: boolean
|
||||
ref?: any
|
||||
}
|
||||
|
||||
const Thumb = styled.div`
|
||||
border-radius: 10px;
|
||||
background-color: var(--color-scrollbar-thumb);
|
||||
&:hover {
|
||||
background-color: var(--color-scrollbar-thumb-hover);
|
||||
const Scrollbar: FC<Props> = forwardRef<HTMLDivElement, Props>((props, ref) => {
|
||||
const [isScrolling, setIsScrolling] = useState(false)
|
||||
const timeoutRef = useRef<NodeJS.Timeout | null>(null)
|
||||
|
||||
const handleScroll = useCallback(
|
||||
throttle(() => {
|
||||
setIsScrolling(true)
|
||||
|
||||
if (timeoutRef.current) {
|
||||
clearTimeout(timeoutRef.current)
|
||||
}
|
||||
|
||||
timeoutRef.current = setTimeout(() => setIsScrolling(false), 1500) // 增加到 2 秒
|
||||
}, 200),
|
||||
[]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (timeoutRef.current) {
|
||||
clearTimeout(timeoutRef.current)
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Container {...props} isScrolling={isScrolling} onScroll={handleScroll} ref={ref}>
|
||||
{props.children}
|
||||
</Container>
|
||||
)
|
||||
})
|
||||
|
||||
Scrollbar.displayName = 'Scrollbar'
|
||||
|
||||
const Container = styled.div<{ isScrolling: boolean; right?: boolean }>`
|
||||
overflow-y: auto;
|
||||
&::-webkit-scrollbar-thumb {
|
||||
transition: background 2s ease;
|
||||
background: ${(props) =>
|
||||
props.isScrolling ? `var(--color-scrollbar-thumb${props.right ? '-right' : ''})` : 'transparent'};
|
||||
&:hover {
|
||||
background: ${(props) =>
|
||||
props.isScrolling ? `var(--color-scrollbar-thumb${props.right ? '-right' : ''}-hover)` : 'transparent'};
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export default Scrollbar
|
||||
|
||||
@ -2,7 +2,7 @@ import { DeleteOutlined, EditOutlined, MoreOutlined, PlusOutlined } from '@ant-d
|
||||
import AssistantSettingsPopup from '@renderer/components/AssistantSettings'
|
||||
import DragableList from '@renderer/components/DragableList'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import { Scrollbar } from '@renderer/components/Scrollbar'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import { useAgents } from '@renderer/hooks/useAgents'
|
||||
import { createAssistantFromAgent } from '@renderer/services/assistant'
|
||||
import { Agent } from '@renderer/types'
|
||||
@ -57,49 +57,47 @@ const Agents: React.FC<Props> = ({ onClick }) => {
|
||||
)
|
||||
|
||||
return (
|
||||
<Scrollbar style={{ maxWidth: 'var(--assistants-width)' }}>
|
||||
<Container style={{ paddingBottom: dragging ? 30 : 0 }}>
|
||||
{agents.length > 0 && (
|
||||
<DragableList
|
||||
list={agents}
|
||||
onUpdate={updateAgents}
|
||||
onDragStart={() => setDragging(true)}
|
||||
onDragEnd={() => setDragging(false)}>
|
||||
{(agent: Agent) => (
|
||||
<Dropdown menu={{ items: getMenuItems(agent) }} trigger={['contextMenu']}>
|
||||
<AgentItem onClick={() => onClick(agent)}>
|
||||
<HStack alignItems="center" justifyContent="space-between" h="36px">
|
||||
<AgentItemName className="text-nowrap">
|
||||
{agent.emoji} {agent.name}
|
||||
</AgentItemName>
|
||||
<ActionButton className="actions" gap="15px" onClick={(e) => e.stopPropagation()}>
|
||||
<Dropdown menu={{ items: getMenuItems(agent) }} trigger={['hover']}>
|
||||
<MoreOutlined style={{ cursor: 'pointer' }} />
|
||||
</Dropdown>
|
||||
</ActionButton>
|
||||
</HStack>
|
||||
<AgentItemPrompt>{agent.prompt}</AgentItemPrompt>
|
||||
</AgentItem>
|
||||
</Dropdown>
|
||||
)}
|
||||
</DragableList>
|
||||
)}
|
||||
{!dragging && (
|
||||
<Button
|
||||
type="dashed"
|
||||
icon={<PlusOutlined />}
|
||||
onClick={() => AddAgentPopup.show()}
|
||||
style={{ borderRadius: 20, height: 34 }}>
|
||||
{t('agents.add.title')}
|
||||
</Button>
|
||||
)}
|
||||
<div style={{ height: 10 }} />
|
||||
</Container>
|
||||
</Scrollbar>
|
||||
<Container style={{ paddingBottom: dragging ? 30 : 0 }}>
|
||||
{agents.length > 0 && (
|
||||
<DragableList
|
||||
list={agents}
|
||||
onUpdate={updateAgents}
|
||||
onDragStart={() => setDragging(true)}
|
||||
onDragEnd={() => setDragging(false)}>
|
||||
{(agent: Agent) => (
|
||||
<Dropdown menu={{ items: getMenuItems(agent) }} trigger={['contextMenu']}>
|
||||
<AgentItem onClick={() => onClick(agent)}>
|
||||
<HStack alignItems="center" justifyContent="space-between" h="36px">
|
||||
<AgentItemName className="text-nowrap">
|
||||
{agent.emoji} {agent.name}
|
||||
</AgentItemName>
|
||||
<ActionButton className="actions" gap="15px" onClick={(e) => e.stopPropagation()}>
|
||||
<Dropdown menu={{ items: getMenuItems(agent) }} trigger={['hover']}>
|
||||
<MoreOutlined style={{ cursor: 'pointer' }} />
|
||||
</Dropdown>
|
||||
</ActionButton>
|
||||
</HStack>
|
||||
<AgentItemPrompt>{agent.prompt}</AgentItemPrompt>
|
||||
</AgentItem>
|
||||
</Dropdown>
|
||||
)}
|
||||
</DragableList>
|
||||
)}
|
||||
{!dragging && (
|
||||
<Button
|
||||
type="dashed"
|
||||
icon={<PlusOutlined />}
|
||||
onClick={() => AddAgentPopup.show()}
|
||||
style={{ borderRadius: 20, height: 34 }}>
|
||||
{t('agents.add.title')}
|
||||
</Button>
|
||||
)}
|
||||
<div style={{ height: 10 }} />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
const Container = styled.div`
|
||||
const Container = styled(Scrollbar)`
|
||||
padding: 15px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
||||
import { VStack } from '@renderer/components/Layout'
|
||||
import { Scrollbar } from '@renderer/components/Scrollbar'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import SystemAgents from '@renderer/config/agents.json'
|
||||
import { createAssistantFromAgent } from '@renderer/services/assistant'
|
||||
import { Agent } from '@renderer/types'
|
||||
@ -61,34 +61,32 @@ const AgentsPage: FC = () => {
|
||||
</Navbar>
|
||||
<ContentContainer id="content-container">
|
||||
<Agents onClick={onAddAgentConfirm} />
|
||||
<Scrollbar>
|
||||
<AssistantsContainer>
|
||||
<VStack style={{ flex: 1 }}>
|
||||
{Object.keys(agentGroups)
|
||||
.reverse()
|
||||
.map((group) => (
|
||||
<div key={group}>
|
||||
<Title level={5} key={group} style={{ marginBottom: 16 }}>
|
||||
{group}
|
||||
</Title>
|
||||
<Row gutter={16}>
|
||||
{agentGroups[group].map((agent, index) => {
|
||||
return (
|
||||
<Col span={8} key={group + index}>
|
||||
<AgentCard
|
||||
onClick={() => onAddAgentConfirm(getAgentFromSystemAgent(agent))}
|
||||
agent={agent as any}
|
||||
/>
|
||||
</Col>
|
||||
)
|
||||
})}
|
||||
</Row>
|
||||
</div>
|
||||
))}
|
||||
<div style={{ minHeight: 20 }} />
|
||||
</VStack>
|
||||
</AssistantsContainer>
|
||||
</Scrollbar>
|
||||
<AssistantsContainer right>
|
||||
<VStack style={{ flex: 1 }}>
|
||||
{Object.keys(agentGroups)
|
||||
.reverse()
|
||||
.map((group) => (
|
||||
<div key={group}>
|
||||
<Title level={5} key={group} style={{ marginBottom: 16 }}>
|
||||
{group}
|
||||
</Title>
|
||||
<Row gutter={16}>
|
||||
{agentGroups[group].map((agent, index) => {
|
||||
return (
|
||||
<Col span={8} key={group + index}>
|
||||
<AgentCard
|
||||
onClick={() => onAddAgentConfirm(getAgentFromSystemAgent(agent))}
|
||||
agent={agent as any}
|
||||
/>
|
||||
</Col>
|
||||
)
|
||||
})}
|
||||
</Row>
|
||||
</div>
|
||||
))}
|
||||
<div style={{ minHeight: 20 }} />
|
||||
</VStack>
|
||||
</AssistantsContainer>
|
||||
</ContentContainer>
|
||||
</Container>
|
||||
)
|
||||
@ -109,12 +107,13 @@ const ContentContainer = styled.div`
|
||||
height: 100%;
|
||||
`
|
||||
|
||||
const AssistantsContainer = styled.div`
|
||||
const AssistantsContainer = styled(Scrollbar)`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
height: calc(100vh - var(--navbar-height));
|
||||
padding: 15px 20px;
|
||||
margin-right: 4px;
|
||||
`
|
||||
|
||||
const AgentPrompt = styled.div`
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
||||
import { VStack } from '@renderer/components/Layout'
|
||||
import { Scrollbar } from '@renderer/components/Scrollbar'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import db from '@renderer/databases'
|
||||
import FileManager from '@renderer/services/file'
|
||||
import { FileType, FileTypes } from '@renderer/types'
|
||||
@ -67,17 +66,15 @@ const FilesPage: FC = () => {
|
||||
<NavbarCenter style={{ borderRight: 'none' }}>{t('files.title')}</NavbarCenter>
|
||||
</Navbar>
|
||||
<ContentContainer id="content-container">
|
||||
<Scrollbar>
|
||||
<VStack style={{ width: '100%', padding: 15 }}>
|
||||
<Table
|
||||
dataSource={dataSource}
|
||||
columns={columns}
|
||||
style={{ width: '100%', marginBottom: 20 }}
|
||||
size="small"
|
||||
pagination={{ pageSize: 100 }}
|
||||
/>
|
||||
</VStack>
|
||||
</Scrollbar>
|
||||
<TableContainer right>
|
||||
<Table
|
||||
dataSource={dataSource}
|
||||
columns={columns}
|
||||
style={{ width: '100%' }}
|
||||
size="small"
|
||||
pagination={{ pageSize: 100 }}
|
||||
/>
|
||||
</TableContainer>
|
||||
</ContentContainer>
|
||||
</Container>
|
||||
)
|
||||
@ -87,7 +84,7 @@ const Container = styled.div`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
height: calc(100vh - var(--navbar-height));
|
||||
`
|
||||
|
||||
const ContentContainer = styled.div`
|
||||
@ -96,6 +93,14 @@ const ContentContainer = styled.div`
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
padding: 0 2px;
|
||||
`
|
||||
|
||||
const TableContainer = styled(Scrollbar)`
|
||||
padding: 15px;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
`
|
||||
|
||||
const FileNameText = styled.div`
|
||||
|
||||
@ -85,7 +85,7 @@ const TopicsPage: FC = () => {
|
||||
<TopicsHistory keywords={search} onClick={onTopicClick as any} style={{ display: isShow('topics') }} />
|
||||
<TopicMessages topic={topic} style={{ display: isShow('topic') }} />
|
||||
<SearchResults
|
||||
keywords={search}
|
||||
keywords={isShow('search') ? search : ''}
|
||||
onMessageClick={onMessageClick}
|
||||
onTopicClick={onTopicClick}
|
||||
style={{ display: isShow('search') }}
|
||||
|
||||
@ -48,6 +48,13 @@ const SearchResults: FC<Props> = ({ keywords, onMessageClick, onTopicClick, ...p
|
||||
|
||||
const onSearch = useCallback(async () => {
|
||||
setSearchResults([])
|
||||
|
||||
if (keywords.length === 0) {
|
||||
setSearchStats({ count: 0, time: 0 })
|
||||
setSearchTerms([])
|
||||
return
|
||||
}
|
||||
|
||||
const startTime = performance.now()
|
||||
const results: { message: Message; topic: Topic }[] = []
|
||||
const newSearchTerms = keywords
|
||||
@ -74,8 +81,12 @@ const SearchResults: FC<Props> = ({ keywords, onMessageClick, onTopicClick, ...p
|
||||
const highlightText = (text: string) => {
|
||||
let highlightedText = removeMarkdown(text)
|
||||
searchTerms.forEach((term) => {
|
||||
const regex = new RegExp(term, 'gi')
|
||||
highlightedText = highlightedText.replace(regex, (match) => `<mark>${match}</mark>`)
|
||||
try {
|
||||
const regex = new RegExp(term, 'gi')
|
||||
highlightedText = highlightedText.replace(regex, (match) => `<mark>${match}</mark>`)
|
||||
} catch (error) {
|
||||
//
|
||||
}
|
||||
})
|
||||
return <span dangerouslySetInnerHTML={{ __html: highlightedText }} />
|
||||
}
|
||||
|
||||
@ -49,6 +49,7 @@ const Markdown: FC<Props> = ({ message }) => {
|
||||
className="markdown"
|
||||
rehypePlugins={rehypePlugins}
|
||||
remarkPlugins={[remarkMath, remarkGfm]}
|
||||
disallowedElements={mathEngine === 'KaTeX' ? ['style'] : []}
|
||||
components={
|
||||
{
|
||||
a: Link,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Scrollbar } from '@renderer/components/Scrollbar'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import db from '@renderer/databases'
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
@ -220,33 +220,32 @@ const Messages: FC<Props> = ({ assistant, topic, setActiveTopic }) => {
|
||||
}, [assistant, messages])
|
||||
|
||||
return (
|
||||
<Scrollbar>
|
||||
<Container id="messages" style={{ maxWidth }} key={assistant.id} ref={containerRef}>
|
||||
<Suggestions assistant={assistant} messages={messages} lastMessage={lastMessage} />
|
||||
{lastMessage && <MessageItem key={lastMessage.id} message={lastMessage} lastMessage />}
|
||||
{reverse([...messages]).map((message, index) => (
|
||||
<MessageItem
|
||||
key={message.id}
|
||||
message={message}
|
||||
index={index}
|
||||
hidePresetMessages={assistant.settings?.hideMessages}
|
||||
onEditMessage={onEditMessage}
|
||||
onDeleteMessage={onDeleteMessage}
|
||||
/>
|
||||
))}
|
||||
<Prompt assistant={assistant} key={assistant.prompt} />
|
||||
</Container>
|
||||
</Scrollbar>
|
||||
<Container id="messages" style={{ maxWidth }} key={assistant.id} ref={containerRef} right>
|
||||
<Suggestions assistant={assistant} messages={messages} lastMessage={lastMessage} />
|
||||
{lastMessage && <MessageItem key={lastMessage.id} message={lastMessage} lastMessage />}
|
||||
{reverse([...messages]).map((message, index) => (
|
||||
<MessageItem
|
||||
key={message.id}
|
||||
message={message}
|
||||
index={index}
|
||||
hidePresetMessages={assistant.settings?.hideMessages}
|
||||
onEditMessage={onEditMessage}
|
||||
onDeleteMessage={onDeleteMessage}
|
||||
/>
|
||||
))}
|
||||
<Prompt assistant={assistant} key={assistant.prompt} />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
const Container = styled.div`
|
||||
const Container = styled(Scrollbar)`
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
padding: 10px 0;
|
||||
background-color: var(--color-background);
|
||||
padding-bottom: 20px;
|
||||
overflow-x: hidden;
|
||||
margin-right: 3px;
|
||||
`
|
||||
|
||||
export default Messages
|
||||
|
||||
@ -2,7 +2,7 @@ import { DeleteOutlined, EditOutlined, MinusCircleOutlined, PlusOutlined, SaveOu
|
||||
import AssistantSettingsPopup from '@renderer/components/AssistantSettings'
|
||||
import DragableList from '@renderer/components/DragableList'
|
||||
import CopyIcon from '@renderer/components/Icons/CopyIcon'
|
||||
import { Scrollbar } from '@renderer/components/Scrollbar'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import { useAgents } from '@renderer/hooks/useAgents'
|
||||
import { useAssistant, useAssistants } from '@renderer/hooks/useAssistant'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
@ -179,66 +179,64 @@ const Assistants: FC<Props> = ({
|
||||
}, [activeAssistant?.id, list, onSwitchAssistant])
|
||||
|
||||
return (
|
||||
<Scrollbar>
|
||||
<Container>
|
||||
{assistants.length >= 10 && (
|
||||
<SearchContainer>
|
||||
<Input
|
||||
placeholder={t('chat.assistant.search.placeholder')}
|
||||
suffix={<CommandKey>⌘+K</CommandKey>}
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
style={{ borderRadius: 16, borderWidth: 0.5 }}
|
||||
onKeyDown={onSearch}
|
||||
ref={searchRef}
|
||||
onFocus={() => dispatch(setSearching(true))}
|
||||
onBlur={() => {
|
||||
dispatch(setSearching(false))
|
||||
setSearch('')
|
||||
}}
|
||||
allowClear
|
||||
/>
|
||||
</SearchContainer>
|
||||
)}
|
||||
<DragableList
|
||||
list={list}
|
||||
onUpdate={updateAssistants}
|
||||
droppableProps={{ isDropDisabled: !isEmpty(search) }}
|
||||
style={{ paddingBottom: dragging ? '34px' : 0 }}
|
||||
onDragStart={() => setDragging(true)}
|
||||
onDragEnd={() => setDragging(false)}>
|
||||
{(assistant) => {
|
||||
const isCurrent = assistant.id === activeAssistant?.id
|
||||
return (
|
||||
<Dropdown key={assistant.id} menu={{ items: getMenuItems(assistant) }} trigger={['contextMenu']}>
|
||||
<AssistantItem onClick={() => onSwitchAssistant(assistant)} className={isCurrent ? 'active' : ''}>
|
||||
<AssistantName className="name">{assistant.name || t('chat.default.name')}</AssistantName>
|
||||
{isCurrent && (
|
||||
<ArrowRightButton onClick={() => EventEmitter.emit(EVENT_NAMES.SWITCH_TOPIC_SIDEBAR)}>
|
||||
<i className="iconfont icon-gridlines" />
|
||||
</ArrowRightButton>
|
||||
)}
|
||||
{false && <TopicCount className="topics-count">{assistant.topics.length}</TopicCount>}
|
||||
</AssistantItem>
|
||||
</Dropdown>
|
||||
)
|
||||
}}
|
||||
</DragableList>
|
||||
{!dragging && (
|
||||
<AssistantItem onClick={onCreateAssistant}>
|
||||
<AssistantName>
|
||||
<PlusOutlined style={{ color: 'var(--color-text-2)', marginRight: 4 }} />
|
||||
{t('chat.add.assistant.title')}
|
||||
</AssistantName>
|
||||
</AssistantItem>
|
||||
)}
|
||||
<div style={{ minHeight: 10 }}></div>
|
||||
</Container>
|
||||
</Scrollbar>
|
||||
<Container>
|
||||
{assistants.length >= 10 && (
|
||||
<SearchContainer>
|
||||
<Input
|
||||
placeholder={t('chat.assistant.search.placeholder')}
|
||||
suffix={<CommandKey>⌘+K</CommandKey>}
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
style={{ borderRadius: 16, borderWidth: 0.5 }}
|
||||
onKeyDown={onSearch}
|
||||
ref={searchRef}
|
||||
onFocus={() => dispatch(setSearching(true))}
|
||||
onBlur={() => {
|
||||
dispatch(setSearching(false))
|
||||
setSearch('')
|
||||
}}
|
||||
allowClear
|
||||
/>
|
||||
</SearchContainer>
|
||||
)}
|
||||
<DragableList
|
||||
list={list}
|
||||
onUpdate={updateAssistants}
|
||||
droppableProps={{ isDropDisabled: !isEmpty(search) }}
|
||||
style={{ paddingBottom: dragging ? '34px' : 0 }}
|
||||
onDragStart={() => setDragging(true)}
|
||||
onDragEnd={() => setDragging(false)}>
|
||||
{(assistant) => {
|
||||
const isCurrent = assistant.id === activeAssistant?.id
|
||||
return (
|
||||
<Dropdown key={assistant.id} menu={{ items: getMenuItems(assistant) }} trigger={['contextMenu']}>
|
||||
<AssistantItem onClick={() => onSwitchAssistant(assistant)} className={isCurrent ? 'active' : ''}>
|
||||
<AssistantName className="name">{assistant.name || t('chat.default.name')}</AssistantName>
|
||||
{isCurrent && (
|
||||
<ArrowRightButton onClick={() => EventEmitter.emit(EVENT_NAMES.SWITCH_TOPIC_SIDEBAR)}>
|
||||
<i className="iconfont icon-gridlines" />
|
||||
</ArrowRightButton>
|
||||
)}
|
||||
{false && <TopicCount className="topics-count">{assistant.topics.length}</TopicCount>}
|
||||
</AssistantItem>
|
||||
</Dropdown>
|
||||
)
|
||||
}}
|
||||
</DragableList>
|
||||
{!dragging && (
|
||||
<AssistantItem onClick={onCreateAssistant}>
|
||||
<AssistantName>
|
||||
<PlusOutlined style={{ color: 'var(--color-text-2)', marginRight: 4 }} />
|
||||
{t('chat.add.assistant.title')}
|
||||
</AssistantName>
|
||||
</AssistantItem>
|
||||
)}
|
||||
<div style={{ minHeight: 10 }}></div>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
const Container = styled.div`
|
||||
const Container = styled(Scrollbar)`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 10px;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { CheckOutlined, QuestionCircleOutlined, ReloadOutlined } from '@ant-design/icons'
|
||||
import { HStack } from '@renderer/components/Layout'
|
||||
import { Scrollbar } from '@renderer/components/Scrollbar'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import { DEFAULT_CONEXTCOUNT, DEFAULT_MAX_TOKENS, DEFAULT_TEMPERATURE } from '@renderer/config/constant'
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
@ -100,202 +100,200 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
}, [assistant])
|
||||
|
||||
return (
|
||||
<Scrollbar>
|
||||
<Container>
|
||||
<SettingSubtitle style={{ marginTop: 5 }}>
|
||||
{t('settings.messages.model.title')}{' '}
|
||||
<Tooltip title={t('chat.settings.reset')}>
|
||||
<ReloadOutlined onClick={onReset} style={{ cursor: 'pointer', fontSize: 12, padding: '0 3px' }} />
|
||||
</Tooltip>
|
||||
</SettingSubtitle>
|
||||
<SettingDivider />
|
||||
<Row align="middle">
|
||||
<Label>{t('chat.settings.temperature')}</Label>
|
||||
<Tooltip title={t('chat.settings.temperature.tip')}>
|
||||
<Container>
|
||||
<SettingSubtitle style={{ marginTop: 5 }}>
|
||||
{t('settings.messages.model.title')}{' '}
|
||||
<Tooltip title={t('chat.settings.reset')}>
|
||||
<ReloadOutlined onClick={onReset} style={{ cursor: 'pointer', fontSize: 12, padding: '0 3px' }} />
|
||||
</Tooltip>
|
||||
</SettingSubtitle>
|
||||
<SettingDivider />
|
||||
<Row align="middle">
|
||||
<Label>{t('chat.settings.temperature')}</Label>
|
||||
<Tooltip title={t('chat.settings.temperature.tip')}>
|
||||
<QuestionIcon />
|
||||
</Tooltip>
|
||||
</Row>
|
||||
<Row align="middle" gutter={10}>
|
||||
<Col span={24}>
|
||||
<Slider
|
||||
min={0}
|
||||
max={2}
|
||||
onChange={setTemperature}
|
||||
onChangeComplete={onTemperatureChange}
|
||||
value={typeof temperature === 'number' ? temperature : 0}
|
||||
step={0.1}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row align="middle">
|
||||
<Label>{t('chat.settings.conext_count')}</Label>
|
||||
<Tooltip title={t('chat.settings.conext_count.tip')}>
|
||||
<QuestionIcon />
|
||||
</Tooltip>
|
||||
</Row>
|
||||
<Row align="middle" gutter={10}>
|
||||
<Col span={24}>
|
||||
<Slider
|
||||
min={0}
|
||||
max={20}
|
||||
onChange={setConextCount}
|
||||
onChangeComplete={onConextCountChange}
|
||||
value={typeof contextCount === 'number' ? contextCount : 0}
|
||||
step={1}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('model.stream_output')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={streamOutput}
|
||||
onChange={(checked) => {
|
||||
setStreamOutput(checked)
|
||||
onUpdateAssistantSettings({ streamOutput: checked })
|
||||
}}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<Row align="middle" justify="space-between">
|
||||
<HStack alignItems="center">
|
||||
<Label>{t('chat.settings.max_tokens')}</Label>
|
||||
<Tooltip title={t('chat.settings.max_tokens.tip')}>
|
||||
<QuestionIcon />
|
||||
</Tooltip>
|
||||
</Row>
|
||||
<Row align="middle" gutter={10}>
|
||||
<Col span={24}>
|
||||
<Slider
|
||||
min={0}
|
||||
max={2}
|
||||
onChange={setTemperature}
|
||||
onChangeComplete={onTemperatureChange}
|
||||
value={typeof temperature === 'number' ? temperature : 0}
|
||||
step={0.1}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row align="middle">
|
||||
<Label>{t('chat.settings.conext_count')}</Label>
|
||||
<Tooltip title={t('chat.settings.conext_count.tip')}>
|
||||
<QuestionIcon />
|
||||
</Tooltip>
|
||||
</Row>
|
||||
<Row align="middle" gutter={10}>
|
||||
<Col span={24}>
|
||||
<Slider
|
||||
min={0}
|
||||
max={20}
|
||||
onChange={setConextCount}
|
||||
onChangeComplete={onConextCountChange}
|
||||
value={typeof contextCount === 'number' ? contextCount : 0}
|
||||
step={1}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('model.stream_output')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={streamOutput}
|
||||
onChange={(checked) => {
|
||||
setStreamOutput(checked)
|
||||
onUpdateAssistantSettings({ streamOutput: checked })
|
||||
</HStack>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={enableMaxTokens}
|
||||
onChange={(enabled) => {
|
||||
setEnableMaxTokens(enabled)
|
||||
onUpdateAssistantSettings({ enableMaxTokens: enabled })
|
||||
}}
|
||||
/>
|
||||
</Row>
|
||||
<Row align="middle" gutter={10}>
|
||||
<Col span={24}>
|
||||
<Slider
|
||||
disabled={!enableMaxTokens}
|
||||
min={0}
|
||||
max={32000}
|
||||
onChange={setMaxTokens}
|
||||
onChangeComplete={onMaxTokensChange}
|
||||
value={typeof maxTokens === 'number' ? maxTokens : 0}
|
||||
step={100}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<SettingSubtitle>{t('settings.messages.title')}</SettingSubtitle>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.divider')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={showMessageDivider}
|
||||
onChange={(checked) => dispatch(setShowMessageDivider(checked))}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.use_serif_font')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={messageFont === 'serif'}
|
||||
onChange={(checked) => dispatch(setMessageFont(checked ? 'serif' : 'system'))}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('chat.settings.show_line_numbers')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={codeShowLineNumbers}
|
||||
onChange={(checked) => dispatch(setCodeShowLineNumbers(checked))}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.math_engine')}</SettingRowTitleSmall>
|
||||
<Select
|
||||
value={mathEngine}
|
||||
onChange={(value) => dispatch(setMathEngine(value))}
|
||||
style={{ width: 100 }}
|
||||
size="small">
|
||||
<Select.Option value="KaTeX">KaTeX</Select.Option>
|
||||
<Select.Option value="MathJax">MathJax</Select.Option>
|
||||
</Select>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.font_size.title')}</SettingRowTitleSmall>
|
||||
</SettingRow>
|
||||
<Row align="middle" gutter={10}>
|
||||
<Col span={24}>
|
||||
<Slider
|
||||
value={fontSizeValue}
|
||||
onChange={(value) => setFontSizeValue(value)}
|
||||
onChangeComplete={(value) => dispatch(setFontSize(value))}
|
||||
min={12}
|
||||
max={22}
|
||||
step={1}
|
||||
marks={{
|
||||
12: <span style={{ fontSize: '12px' }}>A</span>,
|
||||
14: <span style={{ fontSize: '14px' }}>{t('common.default')}</span>,
|
||||
22: <span style={{ fontSize: '18px' }}>A</span>
|
||||
}}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<Row align="middle" justify="space-between">
|
||||
<HStack alignItems="center">
|
||||
<Label>{t('chat.settings.max_tokens')}</Label>
|
||||
<Tooltip title={t('chat.settings.max_tokens.tip')}>
|
||||
<QuestionIcon />
|
||||
</Tooltip>
|
||||
</HStack>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={enableMaxTokens}
|
||||
onChange={(enabled) => {
|
||||
setEnableMaxTokens(enabled)
|
||||
onUpdateAssistantSettings({ enableMaxTokens: enabled })
|
||||
}}
|
||||
/>
|
||||
</Row>
|
||||
<Row align="middle" gutter={10}>
|
||||
<Col span={24}>
|
||||
<Slider
|
||||
disabled={!enableMaxTokens}
|
||||
min={0}
|
||||
max={32000}
|
||||
onChange={setMaxTokens}
|
||||
onChangeComplete={onMaxTokensChange}
|
||||
value={typeof maxTokens === 'number' ? maxTokens : 0}
|
||||
step={100}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<SettingSubtitle>{t('settings.messages.title')}</SettingSubtitle>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.divider')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={showMessageDivider}
|
||||
onChange={(checked) => dispatch(setShowMessageDivider(checked))}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.use_serif_font')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={messageFont === 'serif'}
|
||||
onChange={(checked) => dispatch(setMessageFont(checked ? 'serif' : 'system'))}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('chat.settings.show_line_numbers')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={codeShowLineNumbers}
|
||||
onChange={(checked) => dispatch(setCodeShowLineNumbers(checked))}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.math_engine')}</SettingRowTitleSmall>
|
||||
<Select
|
||||
value={mathEngine}
|
||||
onChange={(value) => dispatch(setMathEngine(value))}
|
||||
style={{ width: 100 }}
|
||||
size="small">
|
||||
<Select.Option value="KaTeX">KaTeX</Select.Option>
|
||||
<Select.Option value="MathJax">MathJax</Select.Option>
|
||||
</Select>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.font_size.title')}</SettingRowTitleSmall>
|
||||
</SettingRow>
|
||||
<Row align="middle" gutter={10}>
|
||||
<Col span={24}>
|
||||
<Slider
|
||||
value={fontSizeValue}
|
||||
onChange={(value) => setFontSizeValue(value)}
|
||||
onChangeComplete={(value) => dispatch(setFontSize(value))}
|
||||
min={12}
|
||||
max={22}
|
||||
step={1}
|
||||
marks={{
|
||||
12: <span style={{ fontSize: '12px' }}>A</span>,
|
||||
14: <span style={{ fontSize: '14px' }}>{t('common.default')}</span>,
|
||||
22: <span style={{ fontSize: '18px' }}>A</span>
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<SettingSubtitle>{t('settings.messages.input.title')}</SettingSubtitle>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.input.show_estimated_tokens')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={showInputEstimatedTokens}
|
||||
onChange={(checked) => dispatch(setShowInputEstimatedTokens(checked))}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.input.paste_long_text_as_file')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={pasteLongTextAsFile}
|
||||
onChange={(checked) => dispatch(setPasteLongTextAsFile(checked))}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.markdown_rendering_input_message')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={renderInputMessageAsMarkdown}
|
||||
onChange={(checked) => dispatch(setRenderInputMessageAsMarkdown(checked))}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.input.send_shortcuts')}</SettingRowTitleSmall>
|
||||
<Select
|
||||
size="small"
|
||||
value={sendMessageShortcut}
|
||||
menuItemSelectedIcon={<CheckOutlined />}
|
||||
options={[
|
||||
{ value: 'Enter', label: 'Enter' },
|
||||
{ value: 'Shift+Enter', label: `Shift + Enter` }
|
||||
]}
|
||||
onChange={(value) => setSendMessageShortcut(value)}
|
||||
style={{ width: 100 }}
|
||||
/>
|
||||
</SettingRow>
|
||||
</Container>
|
||||
</Scrollbar>
|
||||
</Col>
|
||||
</Row>
|
||||
<SettingSubtitle>{t('settings.messages.input.title')}</SettingSubtitle>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.input.show_estimated_tokens')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={showInputEstimatedTokens}
|
||||
onChange={(checked) => dispatch(setShowInputEstimatedTokens(checked))}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.input.paste_long_text_as_file')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={pasteLongTextAsFile}
|
||||
onChange={(checked) => dispatch(setPasteLongTextAsFile(checked))}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.markdown_rendering_input_message')}</SettingRowTitleSmall>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={renderInputMessageAsMarkdown}
|
||||
onChange={(checked) => dispatch(setRenderInputMessageAsMarkdown(checked))}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>{t('settings.messages.input.send_shortcuts')}</SettingRowTitleSmall>
|
||||
<Select
|
||||
size="small"
|
||||
value={sendMessageShortcut}
|
||||
menuItemSelectedIcon={<CheckOutlined />}
|
||||
options={[
|
||||
{ value: 'Enter', label: 'Enter' },
|
||||
{ value: 'Shift+Enter', label: `Shift + Enter` }
|
||||
]}
|
||||
onChange={(value) => setSendMessageShortcut(value)}
|
||||
style={{ width: 100 }}
|
||||
/>
|
||||
</SettingRow>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
const Container = styled.div`
|
||||
const Container = styled(Scrollbar)`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
|
||||
@ -8,7 +8,7 @@ import {
|
||||
} from '@ant-design/icons'
|
||||
import DragableList from '@renderer/components/DragableList'
|
||||
import PromptPopup from '@renderer/components/Popups/PromptPopup'
|
||||
import { Scrollbar } from '@renderer/components/Scrollbar'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import { useAssistant, useAssistants } from '@renderer/hooks/useAssistant'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { TopicManager } from '@renderer/hooks/useTopic'
|
||||
@ -178,44 +178,42 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic
|
||||
)
|
||||
|
||||
return (
|
||||
<Scrollbar>
|
||||
<Container>
|
||||
<DragableList list={assistant.topics} onUpdate={updateTopics}>
|
||||
{(topic) => {
|
||||
const isActive = topic.id === activeTopic?.id
|
||||
return (
|
||||
<Dropdown menu={{ items: getTopicMenuItems(topic) }} trigger={['contextMenu']} key={topic.id}>
|
||||
<TopicListItem
|
||||
className={isActive ? 'active' : ''}
|
||||
style={{ borderRadius }}
|
||||
onClick={() => onSwitchTopic(topic)}>
|
||||
<TopicName className="name">{topic.name.replace('`', '')}</TopicName>
|
||||
{showTopicTime && <TopicTime>{dayjs(topic.createdAt).format('MM/DD HH:mm')}</TopicTime>}
|
||||
{isActive && (
|
||||
<MenuButton
|
||||
className="menu"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
if (assistant.topics.length === 1) {
|
||||
return onClearMessages()
|
||||
}
|
||||
onDeleteTopic(topic)
|
||||
}}>
|
||||
<CloseOutlined />
|
||||
</MenuButton>
|
||||
)}
|
||||
</TopicListItem>
|
||||
</Dropdown>
|
||||
)
|
||||
}}
|
||||
</DragableList>
|
||||
<div style={{ minHeight: '10px' }}></div>
|
||||
</Container>
|
||||
</Scrollbar>
|
||||
<Container>
|
||||
<DragableList list={assistant.topics} onUpdate={updateTopics}>
|
||||
{(topic) => {
|
||||
const isActive = topic.id === activeTopic?.id
|
||||
return (
|
||||
<Dropdown menu={{ items: getTopicMenuItems(topic) }} trigger={['contextMenu']} key={topic.id}>
|
||||
<TopicListItem
|
||||
className={isActive ? 'active' : ''}
|
||||
style={{ borderRadius }}
|
||||
onClick={() => onSwitchTopic(topic)}>
|
||||
<TopicName className="name">{topic.name.replace('`', '')}</TopicName>
|
||||
{showTopicTime && <TopicTime>{dayjs(topic.createdAt).format('MM/DD HH:mm')}</TopicTime>}
|
||||
{isActive && (
|
||||
<MenuButton
|
||||
className="menu"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
if (assistant.topics.length === 1) {
|
||||
return onClearMessages()
|
||||
}
|
||||
onDeleteTopic(topic)
|
||||
}}>
|
||||
<CloseOutlined />
|
||||
</MenuButton>
|
||||
)}
|
||||
</TopicListItem>
|
||||
</Dropdown>
|
||||
)
|
||||
}}
|
||||
</DragableList>
|
||||
<div style={{ minHeight: '10px' }}></div>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
const Container = styled.div`
|
||||
const Container = styled(Scrollbar)`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 10px;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { DeleteOutlined, EditOutlined, PlusOutlined } from '@ant-design/icons'
|
||||
import { DragDropContext, Draggable, Droppable, DropResult } from '@hello-pangea/dnd'
|
||||
import { Scrollbar } from '@renderer/components/Scrollbar'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import { getProviderLogo } from '@renderer/config/providers'
|
||||
import { useAllProviders, useProviders } from '@renderer/hooks/useProvider'
|
||||
import { Provider } from '@renderer/types'
|
||||
|
||||
76
yarn.lock
76
yarn.lock
@ -2344,7 +2344,6 @@ __metadata:
|
||||
openai: "npm:^4.52.1"
|
||||
prettier: "npm:^3.2.4"
|
||||
react: "npm:^18.2.0"
|
||||
react-custom-scrollbars-2: "npm:^4.5.0"
|
||||
react-dom: "npm:^18.2.0"
|
||||
react-i18next: "npm:^14.1.2"
|
||||
react-markdown: "npm:^9.0.1"
|
||||
@ -2415,13 +2414,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"add-px-to-style@npm:1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "add-px-to-style@npm:1.0.0"
|
||||
checksum: 10c0/d05d0e3242360e296b5b244d1bfbb946a06338653685af95962291da39ee6db9b33ccc2299a5a0ebef8fde62d39b085997b0b76d4c6098f4c164e539afa8d0f4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"agent-base@npm:6, agent-base@npm:^6.0.2":
|
||||
version: 6.0.2
|
||||
resolution: "agent-base@npm:6.0.2"
|
||||
@ -4301,17 +4293,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"dom-css@npm:^2.0.0":
|
||||
version: 2.1.0
|
||||
resolution: "dom-css@npm:2.1.0"
|
||||
dependencies:
|
||||
add-px-to-style: "npm:1.0.0"
|
||||
prefix-style: "npm:2.0.1"
|
||||
to-camel-case: "npm:1.0.0"
|
||||
checksum: 10c0/80975ea794f740b8da0ebde8b4a7203bcf017f44027c669f45c71822f9d298fcf62cd5333134af82d9f886719655149a3257ca3c669af920b523bc7e1fc6723c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"dom-walk@npm:^0.1.0":
|
||||
version: 0.1.2
|
||||
resolution: "dom-walk@npm:0.1.2"
|
||||
@ -9347,13 +9328,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"prefix-style@npm:2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "prefix-style@npm:2.0.1"
|
||||
checksum: 10c0/1db0449b2f7578d30e0ca96cf3014b9dbe42531f0d97dac7ecc7f1369dfbf326fa8e8a321e468ee86e2959f001115c109a0ebe0a4182ca1e920cba10b2d8344d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"prelude-ls@npm:^1.2.1":
|
||||
version: 1.2.1
|
||||
resolution: "prelude-ls@npm:1.2.1"
|
||||
@ -9445,7 +9419,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"prop-types@npm:^15.5.10, prop-types@npm:^15.8.1":
|
||||
"prop-types@npm:^15.8.1":
|
||||
version: 15.8.1
|
||||
resolution: "prop-types@npm:15.8.1"
|
||||
dependencies:
|
||||
@ -9554,15 +9528,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"raf@npm:^3.1.0":
|
||||
version: 3.4.1
|
||||
resolution: "raf@npm:3.4.1"
|
||||
dependencies:
|
||||
performance-now: "npm:^2.1.0"
|
||||
checksum: 10c0/337f0853c9e6a77647b0f499beedafea5d6facfb9f2d488a624f88b03df2be72b8a0e7f9118a3ff811377d534912039a3311815700d2b6d2313f82f736f9eb6e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rc-cascader@npm:~3.28.1":
|
||||
version: 3.28.1
|
||||
resolution: "rc-cascader@npm:3.28.1"
|
||||
@ -10111,20 +10076,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-custom-scrollbars-2@npm:^4.5.0":
|
||||
version: 4.5.0
|
||||
resolution: "react-custom-scrollbars-2@npm:4.5.0"
|
||||
dependencies:
|
||||
dom-css: "npm:^2.0.0"
|
||||
prop-types: "npm:^15.5.10"
|
||||
raf: "npm:^3.1.0"
|
||||
peerDependencies:
|
||||
react: ^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0
|
||||
react-dom: ^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0
|
||||
checksum: 10c0/9670bf15bebabbe6c5b75be577430d6a990875874725019fa75db73b0e51300d65158ef962f9b534513b9b70b900244deb11df55c429ba426e580e478634f4f9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-dom@npm:^18.2.0":
|
||||
version: 18.3.1
|
||||
resolution: "react-dom@npm:18.3.1"
|
||||
@ -11877,15 +11828,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"to-camel-case@npm:1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "to-camel-case@npm:1.0.0"
|
||||
dependencies:
|
||||
to-space-case: "npm:^1.0.0"
|
||||
checksum: 10c0/357921548908053d774d4b836f42437139c6fc9d73aaf40a1aa59d7317d760541a19667eb2884d9db83902065a90d80b0fe74c59bc13943e8489df9ef4335069
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"to-fast-properties@npm:^2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "to-fast-properties@npm:2.0.0"
|
||||
@ -11893,13 +11835,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"to-no-case@npm:^1.0.0":
|
||||
version: 1.0.2
|
||||
resolution: "to-no-case@npm:1.0.2"
|
||||
checksum: 10c0/c035b04e1042ed67ceb23dc5c7c20ccde11a83ab1d2b3947c17918472b5d26dd4ffdb4cf9464752e7707ab9f3af4a106f9b61244c724bc6810422acd5984da3d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"to-regex-range@npm:^5.0.1":
|
||||
version: 5.0.1
|
||||
resolution: "to-regex-range@npm:5.0.1"
|
||||
@ -11909,15 +11844,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"to-space-case@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "to-space-case@npm:1.0.0"
|
||||
dependencies:
|
||||
to-no-case: "npm:^1.0.0"
|
||||
checksum: 10c0/b99e1b5d0f3c90a8d47fa3b155d515027bd83a370740e82ee7cb064f86e3655f030f068bddcb8d18239e7408761b4376d89ab91e5ccdb17dc859d8fd4f570ac5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"toggle-selection@npm:^1.0.6":
|
||||
version: 1.0.6
|
||||
resolution: "toggle-selection@npm:1.0.6"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user