Skip to content

Commit 5899b04

Browse files
authored
feat: fast delete current message (#495)
1 parent 6bb7afe commit 5899b04

File tree

9 files changed

+111
-28
lines changed

9 files changed

+111
-28
lines changed

src/components/common/Setting/General.vue

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script lang="ts" setup>
22
import { computed, onMounted, ref } from 'vue'
3-
import { NButton, NDivider, NInput, NPopconfirm, NSelect, useMessage } from 'naive-ui'
3+
import { NButton, NDivider, NInput, NPopconfirm, NSelect, NSwitch, useMessage } from 'naive-ui'
44
import { UserConfig } from '@/components/common/Setting/model'
55
import type { Language, Theme } from '@/store/modules/app/helper'
66
import { SvgIcon } from '@/components/common'
@@ -271,6 +271,16 @@ function handleImportButtonClick(): void {
271271
/>
272272
</div>
273273
</div>
274+
<div class="flex items-center space-x-4">
275+
<span class="flex-shrink-0 w-[100px]">{{ $t('setting.fastDelMsg') }}</span>
276+
<div class="flex-1">
277+
<NSwitch
278+
:round="false"
279+
:value="appStore.fastDelMsg"
280+
@update-value="value => appStore.setFastDelMsg(value)"
281+
/>
282+
</div>
283+
</div>
274284
</div>
275285
</div>
276286
</template>

src/locales/en-US.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ export default {
182182
info2FAStep3Tip2: '1. After logging in, use the two-step verification on the Two-Step Verification page to disable it.',
183183
info2FAStep3Tip3: '2. Contact the administrator to disable two-step verification.',
184184
maxContextCount: 'Max Context Count',
185+
fastDelMsg: 'Fast Delete Message',
185186
},
186187
store: {
187188
siderButton: 'Prompt Store',

src/locales/ko-KR.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ export default {
179179
info2FAStep3Tip2: '1. After logging in, use the two-step verification on the Two-Step Verification page to disable it.',
180180
info2FAStep3Tip3: '2. Contact the administrator to disable two-step verification.',
181181
maxContextCount: '최대 컨텍스트 수량',
182+
fastDelMsg: '빠르게 메시지 삭제',
182183
},
183184
store: {
184185
siderButton: '프롬프트 스토어',

src/locales/zh-CN.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ export default {
182182
info2FAStep3Tip2: '1. 登录后,在 两步验证 页面使用两步验证码关闭。',
183183
info2FAStep3Tip3: '2. 联系管理员来关闭两步验证。',
184184
maxContextCount: '最大上下文数量',
185+
fastDelMsg: '快速删除消息',
185186
},
186187
store: {
187188
siderButton: '提示词商店',

src/locales/zh-TW.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ export default {
181181
info2FAStep3Tip2: '1. 登录后,在 两步验证 页面使用两步验证码关闭。',
182182
info2FAStep3Tip3: '2. 联系管理员来关闭两步验证。',
183183
maxContextCount: '最大上下文數量',
184+
fastDelMsg: '快速刪除訊息',
184185
},
185186
store: {
186187
siderButton: '提示詞商店',

src/store/modules/app/helper.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,17 @@ export type Theme = 'light' | 'dark' | 'auto'
66

77
export type Language = 'zh-CN' | 'zh-TW' | 'en-US' | 'ko-KR'
88

9+
export type FastDelMsg = '0' | '1'
10+
911
export interface AppState {
1012
siderCollapsed: boolean
1113
theme: Theme
1214
language: Language
15+
fastDelMsg: FastDelMsg
1316
}
1417

1518
export function defaultSetting(): AppState {
16-
return { siderCollapsed: false, theme: 'auto', language: 'zh-CN' }
19+
return { siderCollapsed: false, theme: 'auto', language: 'zh-CN', fastDelMsg: '0' }
1720
}
1821

1922
export function getLocalSetting(): AppState {

src/store/modules/app/index.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { defineStore } from 'pinia'
2-
import type { AppState, Language, Theme } from './helper'
2+
import type { AppState, FastDelMsg, Language, Theme } from './helper'
33
import { getLocalSetting, setLocalSetting } from './helper'
44
import { store } from '@/store/helper'
55

@@ -23,6 +23,13 @@ export const useAppStore = defineStore('app-store', {
2323
}
2424
},
2525

26+
setFastDelMsg(fastDelMsg: FastDelMsg) {
27+
if (this.fastDelMsg !== fastDelMsg) {
28+
this.fastDelMsg = fastDelMsg
29+
this.recordState()
30+
}
31+
},
32+
2633
recordState() {
2734
setLocalSetting(this.$state)
2835
},

src/views/chat/components/Message/index.vue

Lines changed: 59 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,17 @@ import { useIconRender } from '@/hooks/useIconRender'
88
import { t } from '@/locales'
99
import { useBasicLayout } from '@/hooks/useBasicLayout'
1010
import { copyToClip } from '@/utils/copy'
11+
import { useAppStore } from '@/store'
12+
13+
const props = defineProps<Props>()
14+
15+
const emit = defineEmits<Emit>()
16+
17+
const appStore = useAppStore()
1118
1219
interface Props {
20+
index: number
21+
currentNavIndex: number
1322
dateTime?: string
1423
text?: string
1524
images?: string[]
@@ -24,13 +33,10 @@ interface Props {
2433
estimated: boolean
2534
}
2635
}
27-
const props = defineProps<Props>()
28-
29-
const emit = defineEmits<Emit>()
30-
3136
interface Emit {
3237
(ev: 'regenerate'): void
33-
(ev: 'delete'): void
38+
(ev: 'delete', fast: boolean): void
39+
(ev: 'updateCurrentNavIndex', itemId: number): void
3440
(ev: 'responseHistory', historyIndex: number): void
3541
}
3642
@@ -85,7 +91,7 @@ function handleSelect(key: 'copyText' | 'delete' | 'toggleRenderType') {
8591
asRawText.value = !asRawText.value
8692
return
8793
case 'delete':
88-
emit('delete')
94+
emit('delete', false)
8995
}
9096
}
9197
@@ -110,19 +116,58 @@ async function handlePreviousResponse(next: number) {
110116
indexRef.value += next
111117
emit('responseHistory', indexRef.value - 1)
112118
}
119+
120+
function fastDelMsg() {
121+
emit('updateCurrentNavIndex', -1)
122+
emit('delete', true)
123+
}
124+
125+
function toggleShowFastDelMsg(event: any, itemId: number) {
126+
if (window?.getSelection()?.toString())
127+
return
128+
if (!isEventTargetValid(event))
129+
return
130+
131+
if (props.currentNavIndex === itemId)
132+
emit('updateCurrentNavIndex', -1)
133+
else
134+
emit('updateCurrentNavIndex', itemId)
135+
}
136+
137+
function isEventTargetValid(event: any) {
138+
let element = event.target
139+
while (element) {
140+
if (element.classList && element.classList.contains('excludeFastDel'))
141+
return false
142+
143+
element = element.parentElement
144+
}
145+
return true
146+
}
113147
</script>
114148

115149
<template>
116150
<div
117-
ref="messageRef"
118-
class="flex w-full mb-6 overflow-hidden"
151+
ref="messageRef" class="flex w-full mb-6 overflow-hidden"
119152
:class="[{ 'flex-row-reverse': inversion }]"
153+
@click="toggleShowFastDelMsg($event, props.index)"
120154
>
121-
<div
122-
class="flex items-center justify-center flex-shrink-0 h-8 overflow-hidden rounded-full basis-8"
123-
:class="[inversion ? 'ml-2' : 'mr-2']"
124-
>
125-
<AvatarComponent :image="inversion" />
155+
<div class="flex flex-col">
156+
<div
157+
class="flex items-center justify-center flex-shrink-0 h-8 overflow-hidden rounded-full basis-8"
158+
:class="[inversion ? 'ml-2' : 'mr-2']"
159+
>
160+
<AvatarComponent :image="inversion" />
161+
</div>
162+
<div
163+
v-show="props.currentNavIndex === props.index && appStore.fastDelMsg"
164+
class="flex-grow flex items-center justify-center overflow-hidden rounded-full"
165+
:class="[inversion ? 'ml-2' : 'mr-2']"
166+
>
167+
<button class="focus:outline-none" style="opacity: 0.5;" @click="fastDelMsg">
168+
<SvgIcon class="text-lg" icon="ri:delete-bin-line" />
169+
</button>
170+
</div>
126171
</div>
127172
<div class="overflow-hidden text-sm " :class="[inversion ? 'items-end' : 'items-start']">
128173
<p v-if="inversion" class="text-xs text-[#b4bbc4]" :class="[inversion ? 'text-right' : 'text-left']">
@@ -184,7 +229,7 @@ async function handlePreviousResponse(next: number) {
184229
:loading="loading"
185230
:as-raw-text="asRawText"
186231
/>
187-
<div class="flex flex-col">
232+
<div class="flex flex-col excludeFastDel">
188233
<button
189234
v-if="!inversion"
190235
class="mb-2 transition text-neutral-300 hover:text-neutral-800 dark:hover:text-neutral-300"

src/views/chat/index.vue

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ const showPrompt = ref(false)
5454
const nowSelectChatModel = ref<string | null>(null)
5555
const currentChatModel = computed(() => nowSelectChatModel.value ?? currentChatHistory.value?.chatModel ?? userStore.userInfo.config.chatModel)
5656
57+
const currentNavIndexRef = ref<number>(-1)
58+
5759
const isVisionModel = computed(() => currentChatModel.value && currentChatModel.value?.includes('vision'))
5860
5961
let loadingms: MessageReactive
@@ -438,19 +440,28 @@ function handleExport() {
438440
})
439441
}
440442
441-
function handleDelete(index: number) {
443+
function handleDelete(index: number, fast: boolean) {
442444
if (loading.value)
443445
return
444446
445-
dialog.warning({
446-
title: t('chat.deleteMessage'),
447-
content: t('chat.deleteMessageConfirm'),
448-
positiveText: t('common.yes'),
449-
negativeText: t('common.no'),
450-
onPositiveClick: () => {
451-
chatStore.deleteChatByUuid(+uuid, index)
452-
},
453-
})
447+
if (fast === true) {
448+
chatStore.deleteChatByUuid(+uuid, index)
449+
}
450+
else {
451+
dialog.warning({
452+
title: t('chat.deleteMessage'),
453+
content: t('chat.deleteMessageConfirm'),
454+
positiveText: t('common.yes'),
455+
negativeText: t('common.no'),
456+
onPositiveClick: () => {
457+
chatStore.deleteChatByUuid(+uuid, index)
458+
},
459+
})
460+
}
461+
}
462+
463+
function updateCurrentNavIndex(index: number, newIndex: number) {
464+
currentNavIndexRef.value = newIndex
454465
}
455466
456467
function handleClear() {
@@ -669,6 +680,8 @@ onUnmounted(() => {
669680
<Message
670681
v-for="(item, index) of dataSources"
671682
:key="index"
683+
:index="index"
684+
:current-nav-index="currentNavIndexRef"
672685
:date-time="item.dateTime"
673686
:text="item.text"
674687
:images="item.images"
@@ -678,7 +691,8 @@ onUnmounted(() => {
678691
:error="item.error"
679692
:loading="item.loading"
680693
@regenerate="onRegenerate(index)"
681-
@delete="handleDelete(index)"
694+
@update-current-nav-index="(itemId: number) => updateCurrentNavIndex(index, itemId)"
695+
@delete="(fast) => handleDelete(index, fast)"
682696
@response-history="(ev) => onResponseHistory(index, ev)"
683697
/>
684698
<div class="sticky bottom-0 left-0 flex justify-center">

0 commit comments

Comments
 (0)