feat: delete all topic
This commit is contained in:
parent
90e3195e29
commit
0b6d15ec65
@ -1,6 +1,7 @@
|
|||||||
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||||
import {
|
import {
|
||||||
addTopic as _addTopic,
|
addTopic as _addTopic,
|
||||||
|
removeAllTopics as _removeAllTopics,
|
||||||
removeTopic as _removeTopic,
|
removeTopic as _removeTopic,
|
||||||
updateTopic as _updateTopic,
|
updateTopic as _updateTopic,
|
||||||
addAgent,
|
addAgent,
|
||||||
@ -35,13 +36,16 @@ export function useAgent(id: string) {
|
|||||||
return {
|
return {
|
||||||
agent,
|
agent,
|
||||||
addTopic: (topic: Topic) => {
|
addTopic: (topic: Topic) => {
|
||||||
dispatch(_addTopic({ agentId: agent?.id, topic }))
|
dispatch(_addTopic({ agentId: agent.id, topic }))
|
||||||
},
|
},
|
||||||
removeTopic: (topic: Topic) => {
|
removeTopic: (topic: Topic) => {
|
||||||
dispatch(_removeTopic({ agentId: agent?.id, topic }))
|
dispatch(_removeTopic({ agentId: agent.id, topic }))
|
||||||
},
|
},
|
||||||
updateTopic: (topic: Topic) => {
|
updateTopic: (topic: Topic) => {
|
||||||
dispatch(_updateTopic({ agentId: agent?.id, topic }))
|
dispatch(_updateTopic({ agentId: agent.id, topic }))
|
||||||
|
},
|
||||||
|
removeAllTopics: () => {
|
||||||
|
dispatch(_removeAllTopics({ agentId: agent.id }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,10 +7,10 @@ import MessageItem from './Message'
|
|||||||
import { reverse } from 'lodash'
|
import { reverse } from 'lodash'
|
||||||
import hljs from 'highlight.js'
|
import hljs from 'highlight.js'
|
||||||
import { fetchChatCompletion, fetchConversationSummary } from '@renderer/services/api'
|
import { fetchChatCompletion, fetchConversationSummary } from '@renderer/services/api'
|
||||||
import { getTopicMessages } from '@renderer/services/topic'
|
|
||||||
import { useAgent } from '@renderer/hooks/useAgents'
|
import { useAgent } from '@renderer/hooks/useAgents'
|
||||||
import { DEFAULT_TOPIC_NAME } from '@renderer/config/constant'
|
import { DEFAULT_TOPIC_NAME } from '@renderer/config/constant'
|
||||||
import { runAsyncFunction } from '@renderer/utils'
|
import { runAsyncFunction } from '@renderer/utils'
|
||||||
|
import LocalStorage from '@renderer/services/storage'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
agent: Agent
|
agent: Agent
|
||||||
@ -61,7 +61,7 @@ const Conversations: FC<Props> = ({ agent, topic }) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
runAsyncFunction(async () => {
|
runAsyncFunction(async () => {
|
||||||
const messages = await getTopicMessages(topic.id)
|
const messages = await LocalStorage.getTopicMessages(topic.id)
|
||||||
setMessages(messages)
|
setMessages(messages)
|
||||||
})
|
})
|
||||||
}, [topic.id])
|
}, [topic.id])
|
||||||
|
|||||||
@ -2,11 +2,12 @@ import PromptPopup from '@renderer/components/Popups/PromptPopup'
|
|||||||
import { useAgent } from '@renderer/hooks/useAgents'
|
import { useAgent } from '@renderer/hooks/useAgents'
|
||||||
import { useShowRightSidebar } from '@renderer/hooks/useStore'
|
import { useShowRightSidebar } from '@renderer/hooks/useStore'
|
||||||
import { fetchConversationSummary } from '@renderer/services/api'
|
import { fetchConversationSummary } from '@renderer/services/api'
|
||||||
import { getTopicMessages } from '@renderer/services/topic'
|
|
||||||
import { Agent, Topic } from '@renderer/types'
|
import { Agent, Topic } from '@renderer/types'
|
||||||
import { Dropdown, MenuProps } from 'antd'
|
import { Button, Dropdown, MenuProps, Popconfirm } from 'antd'
|
||||||
import { FC, useRef } from 'react'
|
import { FC, useRef } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
import { DeleteOutlined } from '@ant-design/icons'
|
||||||
|
import LocalStorage from '@renderer/services/storage'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
agent: Agent
|
agent: Agent
|
||||||
@ -16,16 +17,16 @@ interface Props {
|
|||||||
|
|
||||||
const TopicList: FC<Props> = ({ agent, activeTopic, setActiveTopic }) => {
|
const TopicList: FC<Props> = ({ agent, activeTopic, setActiveTopic }) => {
|
||||||
const { showRightSidebar } = useShowRightSidebar()
|
const { showRightSidebar } = useShowRightSidebar()
|
||||||
const { removeTopic, updateTopic } = useAgent(agent.id)
|
const { removeTopic, updateTopic, removeAllTopics } = useAgent(agent.id)
|
||||||
const currentTopic = useRef<Topic | null>(null)
|
const currentTopic = useRef<Topic | null>(null)
|
||||||
|
|
||||||
const items: MenuProps['items'] = [
|
const topicMenuItems: MenuProps['items'] = [
|
||||||
{
|
{
|
||||||
label: 'AI Rename',
|
label: 'AI Rename',
|
||||||
key: 'ai-rename',
|
key: 'ai-rename',
|
||||||
async onClick() {
|
async onClick() {
|
||||||
if (currentTopic.current) {
|
if (currentTopic.current) {
|
||||||
const messages = await getTopicMessages(currentTopic.current.id)
|
const messages = await LocalStorage.getTopicMessages(currentTopic.current.id)
|
||||||
if (messages.length >= 2) {
|
if (messages.length >= 2) {
|
||||||
const summaryText = await fetchConversationSummary({ messages })
|
const summaryText = await fetchConversationSummary({ messages })
|
||||||
if (summaryText) {
|
if (summaryText) {
|
||||||
@ -52,8 +53,8 @@ const TopicList: FC<Props> = ({ agent, activeTopic, setActiveTopic }) => {
|
|||||||
]
|
]
|
||||||
|
|
||||||
if (agent.topics.length > 1) {
|
if (agent.topics.length > 1) {
|
||||||
items.push({ type: 'divider' })
|
topicMenuItems.push({ type: 'divider' })
|
||||||
items.push({
|
topicMenuItems.push({
|
||||||
label: 'Delete',
|
label: 'Delete',
|
||||||
danger: true,
|
danger: true,
|
||||||
key: 'delete',
|
key: 'delete',
|
||||||
@ -72,10 +73,23 @@ const TopicList: FC<Props> = ({ agent, activeTopic, setActiveTopic }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container className={showRightSidebar ? '' : 'collapsed'}>
|
<Container className={showRightSidebar ? '' : 'collapsed'}>
|
||||||
<TopicTitle>Topics ({agent.topics.length})</TopicTitle>
|
<TopicTitle>
|
||||||
|
<span>Topics ({agent.topics.length})</span>
|
||||||
|
<Popconfirm
|
||||||
|
title="Delete all topic?"
|
||||||
|
description="Are you sure to delete all topics?"
|
||||||
|
placement="leftBottom"
|
||||||
|
onConfirm={removeAllTopics}
|
||||||
|
okText="Yes"
|
||||||
|
cancelText="No">
|
||||||
|
<DeleteButton type="text">
|
||||||
|
<DeleteIcon />
|
||||||
|
</DeleteButton>
|
||||||
|
</Popconfirm>
|
||||||
|
</TopicTitle>
|
||||||
{agent.topics.map((topic) => (
|
{agent.topics.map((topic) => (
|
||||||
<Dropdown
|
<Dropdown
|
||||||
menu={{ items }}
|
menu={{ items: topicMenuItems }}
|
||||||
trigger={['contextMenu']}
|
trigger={['contextMenu']}
|
||||||
key={topic.id}
|
key={topic.id}
|
||||||
onOpenChange={(open) => open && (currentTopic.current = topic)}>
|
onOpenChange={(open) => open && (currentTopic.current = topic)}>
|
||||||
@ -118,6 +132,26 @@ const TopicTitle = styled.div`
|
|||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: var(--color-text-1);
|
color: var(--color-text-1);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
`
|
||||||
|
|
||||||
|
const DeleteButton = styled(Button)`
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
border-radius: 50%;
|
||||||
|
padding: 0;
|
||||||
|
&:hover {
|
||||||
|
.anticon {
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const DeleteIcon = styled(DeleteOutlined)`
|
||||||
|
font-size: 16px;
|
||||||
`
|
`
|
||||||
|
|
||||||
export default TopicList
|
export default TopicList
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { DEFAULT_TOPIC_NAME } from '@renderer/config/constant'
|
|
||||||
import { Agent } from '@renderer/types'
|
import { Agent } from '@renderer/types'
|
||||||
import { uuid } from '@renderer/utils'
|
import { getDefaultTopic } from './topic'
|
||||||
|
|
||||||
export function getDefaultAgent(): Agent {
|
export function getDefaultAgent(): Agent {
|
||||||
return {
|
return {
|
||||||
@ -8,12 +7,6 @@ export function getDefaultAgent(): Agent {
|
|||||||
name: 'Default Agent',
|
name: 'Default Agent',
|
||||||
description: "Hello, I'm Default Agent.",
|
description: "Hello, I'm Default Agent.",
|
||||||
prompt: '',
|
prompt: '',
|
||||||
topics: [
|
topics: [getDefaultTopic()]
|
||||||
{
|
|
||||||
id: uuid(),
|
|
||||||
name: DEFAULT_TOPIC_NAME,
|
|
||||||
messages: []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/renderer/src/services/storage.ts
Normal file
13
src/renderer/src/services/storage.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { Topic } from '@renderer/types'
|
||||||
|
import localforage from 'localforage'
|
||||||
|
|
||||||
|
export default class LocalStorage {
|
||||||
|
static async getTopicMessages(id: string) {
|
||||||
|
const topic = await localforage.getItem<Topic>(`topic:${id}`)
|
||||||
|
return topic ? topic.messages : []
|
||||||
|
}
|
||||||
|
|
||||||
|
static async removeTopic(id: string) {
|
||||||
|
localforage.removeItem(`topic:${id}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,10 @@
|
|||||||
import { Topic } from '@renderer/types'
|
import { Topic } from '@renderer/types'
|
||||||
import localforage from 'localforage'
|
import { uuid } from '@renderer/utils'
|
||||||
|
|
||||||
export async function getTopicMessages(id: string) {
|
export function getDefaultTopic(): Topic {
|
||||||
const topic = await localforage.getItem<Topic>(`topic:${id}`)
|
return {
|
||||||
return topic ? topic.messages : []
|
id: uuid(),
|
||||||
|
name: 'Default Topic',
|
||||||
|
messages: []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
|
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
|
||||||
import { getDefaultAgent } from '@renderer/services/agent'
|
import { getDefaultAgent } from '@renderer/services/agent'
|
||||||
|
import LocalStorage from '@renderer/services/storage'
|
||||||
|
import { getDefaultTopic } from '@renderer/services/topic'
|
||||||
import { Agent, Topic } from '@renderer/types'
|
import { Agent, Topic } from '@renderer/types'
|
||||||
import { uniqBy } from 'lodash'
|
import { uniqBy } from 'lodash'
|
||||||
|
|
||||||
@ -53,10 +55,23 @@ const agentsSlice = createSlice({
|
|||||||
}
|
}
|
||||||
: agent
|
: agent
|
||||||
)
|
)
|
||||||
|
},
|
||||||
|
removeAllTopics: (state, action: PayloadAction<{ agentId: string }>) => {
|
||||||
|
state.agents = state.agents.map((agent) => {
|
||||||
|
if (agent.id === action.payload.agentId) {
|
||||||
|
agent.topics.forEach((topic) => LocalStorage.removeTopic(topic.id))
|
||||||
|
return {
|
||||||
|
...agent,
|
||||||
|
topics: [getDefaultTopic()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return agent
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export const { addAgent, removeAgent, updateAgent, addTopic, removeTopic, updateTopic } = agentsSlice.actions
|
export const { addAgent, removeAgent, updateAgent, addTopic, removeTopic, updateTopic, removeAllTopics } =
|
||||||
|
agentsSlice.actions
|
||||||
|
|
||||||
export default agentsSlice.reducer
|
export default agentsSlice.reducer
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user