Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/renderer/src/components/message/MessageBlockError.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
<template>
<div
class="text-muted-foreground text-sm flex flex-row gap-2 items-center py-2"
v-if="block.status === 'cancel'"
>
<Icon icon="lucide:refresh-cw-off"></Icon>
<span>{{ t(block.content || '') }}</span>
</div>
<div
v-else
class="text-xs bg-red-100 text-red-700 rounded-lg border border-red-400 flex flex-col gap-2 px-2 py-2"
>
<div class="flex flex-row gap-2 items-center cursor-pointer">
Expand Down
82 changes: 53 additions & 29 deletions src/renderer/src/components/message/MessageList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
<template v-if="!isCapturingImage">
<TransitionGroup
tag="div"
class="absolute bottom-3 right-3 flex items-center gap-2"
class="absolute bottom-3 right-3 flex flex-col items-center gap-2"
enter-active-class="transition-all duration-300 ease-out"
enter-from-class="opacity-0 translate-y-2"
enter-to-class="opacity-100 translate-y-0"
Expand All @@ -49,29 +49,14 @@
@after-leave="handleActionAfterLeave"
@leave-cancelled="handleActionAfterLeave"
>
<!-- 取消按钮 -->
<Button
v-if="showCancelButton"
key="cancel"
variant="outline"
size="icon"
class="w-8 h-8 shrink-0 opacity-100 bg-card backdrop-blur-lg z-20"
@click="handleCancel"
>
<Icon
icon="lucide:square"
class="w-6 h-6 bg-red-500 p-1 text-primary-foreground rounded-full"
/>
</Button>

<!-- 新聊天按钮 (仅在非生成状态显示) -->
<Button
v-else
v-if="!showCancelButton"
key="new-chat"
variant="outline"
size="icon"
class="w-8 h-8 shrink-0 opacity-100 bg-card backdrop-blur-lg z-20"
@click="createNewThread"
@click="openCleanDialog"
>
<Icon icon="lucide:brush-cleaning" class="w-6 h-6 text-foreground" />
<!-- <span class="">{{ t('common.newChat') }}</span> -->
Expand Down Expand Up @@ -105,6 +90,24 @@
@bar-click="handleMinimapClick"
/>
</div>
<Dialog v-model:open="cleanMessagesDialog">
<DialogContent>
<DialogHeader>
<DialogTitle>{{ t('dialog.cleanMessages.title') }}</DialogTitle>
<DialogDescription>
{{ t('dialog.cleanMessages.description') }}
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button variant="outline" @click="handleCleanMessagesDialogCancel">{{
t('dialog.cancel')
}}</Button>
<Button variant="destructive" @click="handleThreadCleanMessages">{{
t('dialog.cleanMessages.confirm')
}}</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</template>

<script setup lang="ts">
Expand All @@ -124,6 +127,16 @@ import { usePageCapture } from '@/composables/usePageCapture'
import { usePresenter } from '@/composables/usePresenter'
import MessageMinimap from './MessageMinimap.vue'
import { useArtifactStore } from '@/stores/artifact'
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
DialogFooter
} from '@shadcn/components/ui/dialog'

const cleanMessagesDialog = ref(false)

const { t } = useI18n()
const props = defineProps<{
Expand Down Expand Up @@ -172,6 +185,26 @@ const handleMinimapHover = (messageId: string | null) => {
hoveredMessageId.value = messageId
}

// 取消清空消息对话框
const handleCleanMessagesDialogCancel = () => {
cleanMessagesDialog.value = false
}

// 清空会话消息
const handleThreadCleanMessages = async () => {
try {
const threadId = chatStore.getActiveThreadId()
if (!threadId) {
return
}
await chatStore.clearAllMessages(threadId)
} catch (error) {
console.error(t('common.error.cleanMessagesFailed'), error)
}

cleanMessagesDialog.value = false
}

const handleMinimapClick = () => {
// 点击迷你地图改为打开消息导航侧边栏
if (artifactStore.isOpen) {
Expand Down Expand Up @@ -466,11 +499,6 @@ const showCancelButton = computed(() => {
return chatStore.generatingThreadIds.has(chatStore.getActiveThreadId() ?? '')
})

const handleCancel = () => {
if (!chatStore.getActiveThreadId()) return
chatStore.cancelGenerating(chatStore.getActiveThreadId()!)
}

// Handle retry event from MessageItemUser
const handleRetry = async (index: number) => {
let triggered = false
Expand Down Expand Up @@ -502,12 +530,8 @@ const handleRetry = async (index: number) => {
}
}
// 创建新会话
const createNewThread = async () => {
try {
await chatStore.clearActiveThread()
} catch (error) {
console.error(t('common.error.createChatFailed'), error)
}
const openCleanDialog = async () => {
cleanMessagesDialog.value = true
}
defineExpose({
scrollToBottom,
Expand Down
28 changes: 28 additions & 0 deletions src/renderer/src/components/prompt-input/PromptInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,25 @@
size="icon"
class="w-7 h-7 text-xs rounded-lg"
:disabled="disabledSend"
v-if="!isStreaming"
@click="emitSend"
>
<Icon icon="lucide:arrow-up" class="w-4 h-4" />
</Button>
<!-- 取消按钮 -->
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Replace Chinese comment with English.

The comment on line 201 is in Chinese. Per coding guidelines, all comments must be in English.

As per coding guidelines.

Apply this diff:

-            <!-- 取消按钮 -->
+            <!-- Cancel button -->
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<!-- 取消按钮 -->
<!-- Cancel button -->
🤖 Prompt for AI Agents
In src/renderer/src/components/prompt-input/PromptInput.vue around line 201, the
inline comment "取消按钮" is in Chinese; update that comment to English (e.g.,
"Cancel button") by replacing the Chinese text with an equivalent English
comment, preserving comment style/placement and whitespace.

<Button
v-if="isStreaming"
key="cancel"
variant="outline"
size="icon"
class="w-7 h-7 text-xs rounded-lg bg-card backdrop-blur-lg"
@click="handleCancel"
>
<Icon
icon="lucide:square"
class="w-6 h-6 bg-red-500 p-1 text-primary-foreground rounded-full"
/>
</Button>
</div>
</div>
<div v-if="isDragging" class="absolute inset-0 bg-black/40 rounded-lg">
Expand Down Expand Up @@ -711,6 +726,11 @@ const previewFile = (filePath: string) => {
windowPresenter.previewFile(filePath)
}

const handleCancel = () => {
if (!chatStore.getActiveThreadId()) return
chatStore.cancelGenerating(chatStore.getActiveThreadId()!)
}

const handlePaste = async (e: ClipboardEvent, fromCapture = false) => {
// Avoid double-processing only for bubble-phase handler on wrapper.
// Allow processing when invoked from the capture-phase editor listener.
Expand Down Expand Up @@ -1050,6 +1070,14 @@ const disabledSend = computed(() => {
return false
})

const isStreaming = computed(() => {
const activeThreadId = chatStore.getActiveThreadId()
if (activeThreadId) {
return chatStore.generatingThreadIds.has(activeThreadId)
}
return false
})

const handleEditorEnter = (e: KeyboardEvent) => {
// If a mention was just selected, don't do anything
if (mentionSelected.value) {
Expand Down