feat(chat): add right-click context menus on messages (M8.9)
Reusable ContextMenu.vue glass-card component positioned at cursor. Messages get Copy, Reply, Edit (user), Regenerate (assistant), and Branch from here options. Closes on Escape or outside click. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
37e8aec920
commit
cc5ecf3091
@@ -3,6 +3,7 @@
|
||||
class="group/msg flex animate-fade-up-fast"
|
||||
:class="isUser ? 'justify-end' : 'justify-start'"
|
||||
:style="{ animationDelay: `${index * 30}ms` }"
|
||||
@contextmenu.prevent="openContextMenu"
|
||||
>
|
||||
<div class="relative max-w-[85%] md:max-w-[75%]">
|
||||
<!-- Action buttons (hover on desktop, always visible on touch) -->
|
||||
@@ -248,12 +249,23 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Context menu -->
|
||||
<ContextMenu ref="contextMenuRef">
|
||||
<ContextMenuItem v-if="isUser" @click="startEditingFromMenu">Edit</ContextMenuItem>
|
||||
<ContextMenuItem v-if="!isUser" @click="emitRegenerate">Regenerate</ContextMenuItem>
|
||||
<ContextMenuItem @click="emitReply">Reply</ContextMenuItem>
|
||||
<ContextMenuItem v-if="!isUser" @click="emitBranch">Branch from here</ContextMenuItem>
|
||||
<ContextMenuItem @click="copyContent">Copy</ContextMenuItem>
|
||||
</ContextMenu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, nextTick } from 'vue'
|
||||
import MarkdownIt from 'markdown-it'
|
||||
import ContextMenu from '@/components/ui/ContextMenu.vue'
|
||||
import ContextMenuItem from '@/components/ui/ContextMenuItem.vue'
|
||||
import type { Message, WebSearchResult } from '@aiui/core/types/message'
|
||||
import type { Film, Song, Podcast, Book, TVSeries, ImageItem, Place } from '@aiui/core/types/content'
|
||||
import { useContentPanel, type MagazineSection } from '@/composables/useContentPanel'
|
||||
@@ -497,4 +509,36 @@ function handleBubbleClick() {
|
||||
}
|
||||
if (hasContext.value) openPanel()
|
||||
}
|
||||
|
||||
// Context menu
|
||||
const contextMenuRef = ref<InstanceType<typeof ContextMenu> | null>(null)
|
||||
|
||||
function openContextMenu(e: MouseEvent) {
|
||||
contextMenuRef.value?.open(e.clientX, e.clientY)
|
||||
}
|
||||
|
||||
function startEditingFromMenu() {
|
||||
contextMenuRef.value?.close()
|
||||
startEditing()
|
||||
}
|
||||
|
||||
function emitRegenerate() {
|
||||
contextMenuRef.value?.close()
|
||||
emit('regenerate')
|
||||
}
|
||||
|
||||
function emitReply() {
|
||||
contextMenuRef.value?.close()
|
||||
emit('reply', props.message.id, props.message.content)
|
||||
}
|
||||
|
||||
function emitBranch() {
|
||||
contextMenuRef.value?.close()
|
||||
emit('branch', props.message.id)
|
||||
}
|
||||
|
||||
function copyContent() {
|
||||
contextMenuRef.value?.close()
|
||||
navigator.clipboard.writeText(props.message.content).catch(() => {})
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user