refactor: Simplify topic deletion interaction

This commit is contained in:
kangfenmao 2025-02-20 15:33:14 +08:00
parent 0d236a94ab
commit 40912eaaf4
6 changed files with 69 additions and 64 deletions

View File

@ -139,7 +139,6 @@
"topics.pinned": "Pinned Topics",
"topics.title": "Topics",
"topics.unpinned": "Unpinned Topics",
"topics.delete.title": "Are you sure you want to delete this topic? This action cannot be undone",
"topics.delete.shortcut": "Hold {{key}} to delete directly",
"translate": "Translate",
"topics.prompt": "Topic Prompts",
@ -815,4 +814,4 @@
"title": "Docs"
}
}
}
}

View File

@ -139,7 +139,6 @@
"topics.pinned": "トピックを固定",
"topics.title": "トピック",
"topics.unpinned": "固定解除",
"topics.delete.title": "このトピックを削除してもよろしいですか?この操作は元に戻せません",
"topics.delete.shortcut": "{{key}}キーを押しながらで直接削除",
"translate": "翻訳",
"topics.prompt": "トピック提示語",
@ -819,4 +818,4 @@
"title": "ドキュメント"
}
}
}
}

View File

@ -139,7 +139,6 @@
"topics.pinned": "Закрепленные темы",
"topics.title": "Топики",
"topics.unpinned": "Открепленные темы",
"topics.delete.title": "Вы уверены, что хотите удалить этот топик? Это действие нельзя отменить",
"topics.delete.shortcut": "Удерживайте {{key}} для мгновенного удаления",
"translate": "Перевести",
"topics.prompt": "Тематические подсказки",
@ -798,4 +797,4 @@
"title": "Документация"
}
}
}
}

View File

@ -141,7 +141,6 @@
"topics.pinned": "固定话题",
"topics.title": "话题",
"topics.unpinned": "取消固定",
"topics.delete.title": "确定要删除此话题吗?此操作无法撤销",
"topics.delete.shortcut": "按住 {{key}} 可直接删除",
"translate": "翻译",
"topics.prompt": "话题提示词",
@ -818,4 +817,4 @@
"title": "帮助文档"
}
}
}
}

View File

@ -139,7 +139,6 @@
"topics.pinned": "固定話題",
"topics.title": "話題",
"topics.unpinned": "取消固定",
"topics.delete.title": "確定要刪除此話題嗎?此操作無法撤銷",
"topics.delete.shortcut": "按住 {{key}} 可直接刪除",
"translate": "翻譯",
"topics.prompt": "話題提示詞",
@ -800,4 +799,4 @@
"title": "幫助文件"
}
}
}
}

View File

@ -22,10 +22,10 @@ import store from '@renderer/store'
import { setGenerating } from '@renderer/store/runtime'
import { Assistant, Topic } from '@renderer/types'
import { exportTopicAsMarkdown, exportTopicToNotion, topicToMarkdown } from '@renderer/utils/export'
import { Dropdown, MenuProps, Popconfirm, Tooltip } from 'antd'
import { Dropdown, MenuProps, Tooltip } from 'antd'
import dayjs from 'dayjs'
import { findIndex } from 'lodash'
import { FC, useCallback } from 'react'
import { FC, useCallback, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
@ -43,6 +43,42 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic
const borderRadius = showTopicTime ? 12 : 'var(--list-item-border-radius)'
const [deletingTopicId, setDeletingTopicId] = useState<string | null>(null)
const deleteTimerRef = useRef<NodeJS.Timeout>()
const handleDeleteClick = useCallback((topicId: string, e: React.MouseEvent) => {
e.stopPropagation()
if (deleteTimerRef.current) {
clearTimeout(deleteTimerRef.current)
}
setDeletingTopicId(topicId)
deleteTimerRef.current = setTimeout(() => setDeletingTopicId(null), 2000)
}, [])
const onClearMessages = useCallback(() => {
window.keyv.set(EVENT_NAMES.CHAT_COMPLETION_PAUSED, true)
store.dispatch(setGenerating(false))
EventEmitter.emit(EVENT_NAMES.CLEAR_MESSAGES)
}, [])
const handleConfirmDelete = useCallback(
async (topic: Topic, e: React.MouseEvent) => {
e.stopPropagation()
if (assistant.topics.length === 1) {
return onClearMessages()
}
await modelGenerating()
const index = findIndex(assistant.topics, (t) => t.id === topic.id)
setActiveTopic(assistant.topics[index + 1 === assistant.topics.length ? index - 1 : index + 1])
removeTopic(topic)
setDeletingTopicId(null)
},
[assistant.topics, onClearMessages, removeTopic, setActiveTopic]
)
const onPinTopic = useCallback(
(topic: Topic) => {
const updatedTopic = { ...topic, pinned: !topic.pinned }
@ -79,12 +115,6 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic
[setActiveTopic]
)
const onClearMessages = useCallback(() => {
window.keyv.set(EVENT_NAMES.CHAT_COMPLETION_PAUSED, true)
store.dispatch(setGenerating(false))
EventEmitter.emit(EVENT_NAMES.CLEAR_MESSAGES)
}, [])
const getTopicMenuItems = useCallback(
(topic: Topic) => {
const menus: MenuProps['items'] = [
@ -245,54 +275,34 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic
)}
<MenuButton className="pin">{topic.pinned && <PushpinOutlined />}</MenuButton>
{isActive && !topic.pinned && (
<Popconfirm
title={t('chat.topics.delete.title')}
placement="top"
okButtonProps={{ danger: true }}
okText={t('common.delete')}
onConfirm={async (e) => {
e?.stopPropagation()
if (assistant.topics.length === 1) {
return onClearMessages()
}
await modelGenerating()
const index = findIndex(assistant.topics, (t) => t.id === topic.id)
setActiveTopic(assistant.topics[index + 1 === assistant.topics.length ? index - 1 : index + 1])
removeTopic(topic)
}}
onCancel={(e) => e?.stopPropagation()}>
<Tooltip
placement="bottom"
mouseEnterDelay={0.7}
title={
<div>
<div style={{ fontSize: '12px', opacity: 0.8, fontStyle: 'italic' }}>
{t('chat.topics.delete.shortcut', {
key: isMac ? '⌘' : 'Ctrl'
})}
</div>
<Tooltip
placement="bottom"
mouseEnterDelay={0.7}
title={
<div>
<div style={{ fontSize: '12px', opacity: 0.8, fontStyle: 'italic' }}>
{t('chat.topics.delete.shortcut', { key: isMac ? '⌘' : 'Ctrl' })}
</div>
}>
<MenuButton
className="menu"
onClick={async (e) => {
e.stopPropagation()
if (assistant.topics.length === 1) {
return onClearMessages()
}
if (e.ctrlKey || e.metaKey) {
await modelGenerating()
const index = findIndex(assistant.topics, (t) => t.id === topic.id)
setActiveTopic(
assistant.topics[index + 1 === assistant.topics.length ? index - 1 : index + 1]
)
removeTopic(topic)
}
}}>
</div>
}>
<MenuButton
className="menu"
onClick={(e) => {
if (e.ctrlKey || e.metaKey) {
handleConfirmDelete(topic, e)
} else if (deletingTopicId === topic.id) {
handleConfirmDelete(topic, e)
} else {
handleDeleteClick(topic.id, e)
}
}}>
{deletingTopicId === topic.id ? (
<DeleteOutlined style={{ color: 'var(--color-error)' }} />
) : (
<CloseOutlined />
</MenuButton>
</Tooltip>
</Popconfirm>
)}
</MenuButton>
</Tooltip>
)}
</TopicListItem>
</Dropdown>